$types
*
* @return bool
*/
- public function isNextTokenAny(array $tokens)
+ public function isNextTokenAny(array $types)
{
- return $this->lookahead !== null && in_array($this->lookahead['type'], $tokens, true);
+ return $this->lookahead !== null && in_array($this->lookahead['type'], $types, true);
}
/**
@@ -209,7 +216,8 @@ abstract class AbstractLexer
/**
* Moves the lookahead token forward.
*
- * @return array|null The next token or NULL if there are no more tokens ahead.
+ * @return mixed[]|null The next token or NULL if there are no more tokens ahead.
+ * @psalm-return Token|null
*/
public function peek()
{
@@ -223,7 +231,8 @@ abstract class AbstractLexer
/**
* Peeks at the next token, returns it and immediately resets the peek.
*
- * @return array|null The next token or NULL if there are no more tokens ahead.
+ * @return mixed[]|null The next token or NULL if there are no more tokens ahead.
+ * @psalm-return Token|null
*/
public function glimpse()
{
@@ -306,14 +315,14 @@ abstract class AbstractLexer
/**
* Lexical catchable patterns.
*
- * @return array
+ * @return string[]
*/
abstract protected function getCatchablePatterns();
/**
* Lexical non-catchable patterns.
*
- * @return array
+ * @return string[]
*/
abstract protected function getNonCatchablePatterns();
diff --git a/vendor/doctrine/lexer/psalm.xml b/vendor/doctrine/lexer/psalm.xml
new file mode 100644
index 0000000..f331e50
--- /dev/null
+++ b/vendor/doctrine/lexer/psalm.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/vendor/symfony/cache-contracts/.gitignore b/vendor/symfony/cache-contracts/.gitignore
new file mode 100644
index 0000000..c49a5d8
--- /dev/null
+++ b/vendor/symfony/cache-contracts/.gitignore
@@ -0,0 +1,3 @@
+vendor/
+composer.lock
+phpunit.xml
diff --git a/vendor/symfony/cache-contracts/CHANGELOG.md b/vendor/symfony/cache-contracts/CHANGELOG.md
new file mode 100644
index 0000000..7932e26
--- /dev/null
+++ b/vendor/symfony/cache-contracts/CHANGELOG.md
@@ -0,0 +1,5 @@
+CHANGELOG
+=========
+
+The changelog is maintained for all Symfony contracts at the following URL:
+https://github.com/symfony/contracts/blob/main/CHANGELOG.md
diff --git a/vendor/symfony/cache-contracts/CacheInterface.php b/vendor/symfony/cache-contracts/CacheInterface.php
new file mode 100644
index 0000000..67e4dfd
--- /dev/null
+++ b/vendor/symfony/cache-contracts/CacheInterface.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\Contracts\Cache;
+
+use Psr\Cache\CacheItemInterface;
+use Psr\Cache\InvalidArgumentException;
+
+/**
+ * Covers most simple to advanced caching needs.
+ *
+ * @author Nicolas Grekas
+ */
+interface CacheInterface
+{
+ /**
+ * Fetches a value from the pool or computes it if not found.
+ *
+ * On cache misses, a callback is called that should return the missing value.
+ * This callback is given a PSR-6 CacheItemInterface instance corresponding to the
+ * requested key, that could be used e.g. for expiration control. It could also
+ * be an ItemInterface instance when its additional features are needed.
+ *
+ * @param string $key The key of the item to retrieve from the cache
+ * @param callable|CallbackInterface $callback Should return the computed value for the given key/item
+ * @param float|null $beta A float that, as it grows, controls the likeliness of triggering
+ * early expiration. 0 disables it, INF forces immediate expiration.
+ * The default (or providing null) is implementation dependent but should
+ * typically be 1.0, which should provide optimal stampede protection.
+ * See https://en.wikipedia.org/wiki/Cache_stampede#Probabilistic_early_expiration
+ * @param array &$metadata The metadata of the cached item {@see ItemInterface::getMetadata()}
+ *
+ * @return mixed
+ *
+ * @throws InvalidArgumentException When $key is not valid or when $beta is negative
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null);
+
+ /**
+ * Removes an item from the pool.
+ *
+ * @param string $key The key to delete
+ *
+ * @throws InvalidArgumentException When $key is not valid
+ *
+ * @return bool True if the item was successfully removed, false if there was any error
+ */
+ public function delete(string $key): bool;
+}
diff --git a/vendor/symfony/cache-contracts/CacheTrait.php b/vendor/symfony/cache-contracts/CacheTrait.php
new file mode 100644
index 0000000..d340e06
--- /dev/null
+++ b/vendor/symfony/cache-contracts/CacheTrait.php
@@ -0,0 +1,80 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Contracts\Cache;
+
+use Psr\Cache\CacheItemPoolInterface;
+use Psr\Cache\InvalidArgumentException;
+use Psr\Log\LoggerInterface;
+
+// Help opcache.preload discover always-needed symbols
+class_exists(InvalidArgumentException::class);
+
+/**
+ * An implementation of CacheInterface for PSR-6 CacheItemPoolInterface classes.
+ *
+ * @author Nicolas Grekas
+ */
+trait CacheTrait
+{
+ /**
+ * {@inheritdoc}
+ *
+ * @return mixed
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ return $this->doGet($this, $key, $callback, $beta, $metadata);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete(string $key): bool
+ {
+ return $this->deleteItem($key);
+ }
+
+ private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null, LoggerInterface $logger = null)
+ {
+ if (0 > $beta = $beta ?? 1.0) {
+ throw new class(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta)) extends \InvalidArgumentException implements InvalidArgumentException { };
+ }
+
+ $item = $pool->getItem($key);
+ $recompute = !$item->isHit() || \INF === $beta;
+ $metadata = $item instanceof ItemInterface ? $item->getMetadata() : [];
+
+ if (!$recompute && $metadata) {
+ $expiry = $metadata[ItemInterface::METADATA_EXPIRY] ?? false;
+ $ctime = $metadata[ItemInterface::METADATA_CTIME] ?? false;
+
+ if ($recompute = $ctime && $expiry && $expiry <= ($now = microtime(true)) - $ctime / 1000 * $beta * log(random_int(1, \PHP_INT_MAX) / \PHP_INT_MAX)) {
+ // force applying defaultLifetime to expiry
+ $item->expiresAt(null);
+ $logger && $logger->info('Item "{key}" elected for early recomputation {delta}s before its expiration', [
+ 'key' => $key,
+ 'delta' => sprintf('%.1f', $expiry - $now),
+ ]);
+ }
+ }
+
+ if ($recompute) {
+ $save = true;
+ $item->set($callback($item, $save));
+ if ($save) {
+ $pool->save($item);
+ }
+ }
+
+ return $item->get();
+ }
+}
diff --git a/vendor/symfony/cache-contracts/CallbackInterface.php b/vendor/symfony/cache-contracts/CallbackInterface.php
new file mode 100644
index 0000000..7dae2aa
--- /dev/null
+++ b/vendor/symfony/cache-contracts/CallbackInterface.php
@@ -0,0 +1,30 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Contracts\Cache;
+
+use Psr\Cache\CacheItemInterface;
+
+/**
+ * Computes and returns the cached value of an item.
+ *
+ * @author Nicolas Grekas
+ */
+interface CallbackInterface
+{
+ /**
+ * @param CacheItemInterface|ItemInterface $item The item to compute the value for
+ * @param bool &$save Should be set to false when the value should not be saved in the pool
+ *
+ * @return mixed The computed value for the passed item
+ */
+ public function __invoke(CacheItemInterface $item, bool &$save);
+}
diff --git a/vendor/symfony/cache-contracts/ItemInterface.php b/vendor/symfony/cache-contracts/ItemInterface.php
new file mode 100644
index 0000000..10c0488
--- /dev/null
+++ b/vendor/symfony/cache-contracts/ItemInterface.php
@@ -0,0 +1,65 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Contracts\Cache;
+
+use Psr\Cache\CacheException;
+use Psr\Cache\CacheItemInterface;
+use Psr\Cache\InvalidArgumentException;
+
+/**
+ * Augments PSR-6's CacheItemInterface with support for tags and metadata.
+ *
+ * @author Nicolas Grekas
+ */
+interface ItemInterface extends CacheItemInterface
+{
+ /**
+ * References the Unix timestamp stating when the item will expire.
+ */
+ public const METADATA_EXPIRY = 'expiry';
+
+ /**
+ * References the time the item took to be created, in milliseconds.
+ */
+ public const METADATA_CTIME = 'ctime';
+
+ /**
+ * References the list of tags that were assigned to the item, as string[].
+ */
+ public const METADATA_TAGS = 'tags';
+
+ /**
+ * Reserved characters that cannot be used in a key or tag.
+ */
+ public const RESERVED_CHARACTERS = '{}()/\@:';
+
+ /**
+ * Adds a tag to a cache item.
+ *
+ * Tags are strings that follow the same validation rules as keys.
+ *
+ * @param string|string[] $tags A tag or array of tags
+ *
+ * @return $this
+ *
+ * @throws InvalidArgumentException When $tag is not valid
+ * @throws CacheException When the item comes from a pool that is not tag-aware
+ */
+ public function tag($tags): self;
+
+ /**
+ * Returns a list of metadata info that were saved alongside with the cached value.
+ *
+ * See ItemInterface::METADATA_* consts for keys potentially found in the returned array.
+ */
+ public function getMetadata(): array;
+}
diff --git a/vendor/symfony/cache-contracts/LICENSE b/vendor/symfony/cache-contracts/LICENSE
new file mode 100644
index 0000000..74cdc2d
--- /dev/null
+++ b/vendor/symfony/cache-contracts/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2018-2022 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/symfony/cache-contracts/README.md b/vendor/symfony/cache-contracts/README.md
new file mode 100644
index 0000000..7085a69
--- /dev/null
+++ b/vendor/symfony/cache-contracts/README.md
@@ -0,0 +1,9 @@
+Symfony Cache Contracts
+=======================
+
+A set of abstractions extracted out of the Symfony components.
+
+Can be used to build on semantics that the Symfony components proved useful - and
+that already have battle tested implementations.
+
+See https://github.com/symfony/contracts/blob/main/README.md for more information.
diff --git a/vendor/symfony/cache-contracts/TagAwareCacheInterface.php b/vendor/symfony/cache-contracts/TagAwareCacheInterface.php
new file mode 100644
index 0000000..7c4cf11
--- /dev/null
+++ b/vendor/symfony/cache-contracts/TagAwareCacheInterface.php
@@ -0,0 +1,38 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Contracts\Cache;
+
+use Psr\Cache\InvalidArgumentException;
+
+/**
+ * Allows invalidating cached items using tags.
+ *
+ * @author Nicolas Grekas
+ */
+interface TagAwareCacheInterface extends CacheInterface
+{
+ /**
+ * Invalidates cached items using tags.
+ *
+ * When implemented on a PSR-6 pool, invalidation should not apply
+ * to deferred items. Instead, they should be committed as usual.
+ * This allows replacing old tagged values by new ones without
+ * race conditions.
+ *
+ * @param string[] $tags An array of tags to invalidate
+ *
+ * @return bool True on success
+ *
+ * @throws InvalidArgumentException When $tags is not valid
+ */
+ public function invalidateTags(array $tags);
+}
diff --git a/vendor/symfony/cache-contracts/composer.json b/vendor/symfony/cache-contracts/composer.json
new file mode 100644
index 0000000..9f45e17
--- /dev/null
+++ b/vendor/symfony/cache-contracts/composer.json
@@ -0,0 +1,38 @@
+{
+ "name": "symfony/cache-contracts",
+ "type": "library",
+ "description": "Generic abstractions related to caching",
+ "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=7.2.5",
+ "psr/cache": "^1.0|^2.0|^3.0"
+ },
+ "suggest": {
+ "symfony/cache-implementation": ""
+ },
+ "autoload": {
+ "psr-4": { "Symfony\\Contracts\\Cache\\": "" }
+ },
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.5-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/AbstractAdapter.php b/vendor/symfony/cache/Adapter/AbstractAdapter.php
new file mode 100644
index 0000000..3d01409
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/AbstractAdapter.php
@@ -0,0 +1,208 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerInterface;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Component\Cache\Traits\AbstractAdapterTrait;
+use Symfony\Component\Cache\Traits\ContractsTrait;
+use Symfony\Contracts\Cache\CacheInterface;
+
+/**
+ * @author Nicolas Grekas
+ */
+abstract class AbstractAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface
+{
+ use AbstractAdapterTrait;
+ use ContractsTrait;
+
+ /**
+ * @internal
+ */
+ protected const NS_SEPARATOR = ':';
+
+ private static $apcuSupported;
+ private static $phpFilesSupported;
+
+ protected function __construct(string $namespace = '', int $defaultLifetime = 0)
+ {
+ $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).static::NS_SEPARATOR;
+ $this->defaultLifetime = $defaultLifetime;
+ if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) {
+ throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s").', $this->maxIdLength - 24, \strlen($namespace), $namespace));
+ }
+ self::$createCacheItem ?? self::$createCacheItem = \Closure::bind(
+ static function ($key, $value, $isHit) {
+ $item = new CacheItem();
+ $item->key = $key;
+ $item->value = $v = $value;
+ $item->isHit = $isHit;
+ // Detect wrapped values that encode for their expiry and creation duration
+ // For compactness, these values are packed in the key of an array using
+ // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F
+ if (\is_array($v) && 1 === \count($v) && 10 === \strlen($k = (string) array_key_first($v)) && "\x9D" === $k[0] && "\0" === $k[5] && "\x5F" === $k[9]) {
+ $item->value = $v[$k];
+ $v = unpack('Ve/Nc', substr($k, 1, -1));
+ $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET;
+ $item->metadata[CacheItem::METADATA_CTIME] = $v['c'];
+ }
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ self::$mergeByLifetime ?? self::$mergeByLifetime = \Closure::bind(
+ static function ($deferred, $namespace, &$expiredIds, $getId, $defaultLifetime) {
+ $byLifetime = [];
+ $now = microtime(true);
+ $expiredIds = [];
+
+ foreach ($deferred as $key => $item) {
+ $key = (string) $key;
+ if (null === $item->expiry) {
+ $ttl = 0 < $defaultLifetime ? $defaultLifetime : 0;
+ } elseif (!$item->expiry) {
+ $ttl = 0;
+ } elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) {
+ $expiredIds[] = $getId($key);
+ continue;
+ }
+ if (isset(($metadata = $item->newMetadata)[CacheItem::METADATA_TAGS])) {
+ unset($metadata[CacheItem::METADATA_TAGS]);
+ }
+ // For compactness, expiry and creation duration are packed in the key of an array, using magic numbers as separators
+ $byLifetime[$ttl][$getId($key)] = $metadata ? ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item->value] : $item->value;
+ }
+
+ return $byLifetime;
+ },
+ null,
+ CacheItem::class
+ );
+ }
+
+ /**
+ * Returns the best possible adapter that your runtime supports.
+ *
+ * Using ApcuAdapter makes system caches compatible with read-only filesystems.
+ *
+ * @return AdapterInterface
+ */
+ public static function createSystemCache(string $namespace, int $defaultLifetime, string $version, string $directory, LoggerInterface $logger = null)
+ {
+ $opcache = new PhpFilesAdapter($namespace, $defaultLifetime, $directory, true);
+ if (null !== $logger) {
+ $opcache->setLogger($logger);
+ }
+
+ if (!self::$apcuSupported = self::$apcuSupported ?? ApcuAdapter::isSupported()) {
+ return $opcache;
+ }
+
+ if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && !filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) {
+ return $opcache;
+ }
+
+ $apcu = new ApcuAdapter($namespace, intdiv($defaultLifetime, 5), $version);
+ if (null !== $logger) {
+ $apcu->setLogger($logger);
+ }
+
+ return new ChainAdapter([$apcu, $opcache]);
+ }
+
+ public static function createConnection(string $dsn, array $options = [])
+ {
+ if (str_starts_with($dsn, 'redis:') || str_starts_with($dsn, 'rediss:')) {
+ return RedisAdapter::createConnection($dsn, $options);
+ }
+ if (str_starts_with($dsn, 'memcached:')) {
+ return MemcachedAdapter::createConnection($dsn, $options);
+ }
+ if (0 === strpos($dsn, 'couchbase:')) {
+ if (CouchbaseBucketAdapter::isSupported()) {
+ return CouchbaseBucketAdapter::createConnection($dsn, $options);
+ }
+
+ return CouchbaseCollectionAdapter::createConnection($dsn, $options);
+ }
+
+ throw new InvalidArgumentException(sprintf('Unsupported DSN: "%s".', $dsn));
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function commit()
+ {
+ $ok = true;
+ $byLifetime = (self::$mergeByLifetime)($this->deferred, $this->namespace, $expiredIds, \Closure::fromCallable([$this, 'getId']), $this->defaultLifetime);
+ $retry = $this->deferred = [];
+
+ if ($expiredIds) {
+ try {
+ $this->doDelete($expiredIds);
+ } catch (\Exception $e) {
+ $ok = false;
+ CacheItem::log($this->logger, 'Failed to delete expired items: '.$e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]);
+ }
+ }
+ foreach ($byLifetime as $lifetime => $values) {
+ try {
+ $e = $this->doSave($values, $lifetime);
+ } catch (\Exception $e) {
+ }
+ if (true === $e || [] === $e) {
+ continue;
+ }
+ if (\is_array($e) || 1 === \count($values)) {
+ foreach (\is_array($e) ? $e : array_keys($values) as $id) {
+ $ok = false;
+ $v = $values[$id];
+ $type = get_debug_type($v);
+ $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]);
+ }
+ } else {
+ foreach ($values as $id => $v) {
+ $retry[$lifetime][] = $id;
+ }
+ }
+ }
+
+ // When bulk-save failed, retry each item individually
+ foreach ($retry as $lifetime => $ids) {
+ foreach ($ids as $id) {
+ try {
+ $v = $byLifetime[$lifetime][$id];
+ $e = $this->doSave([$id => $v], $lifetime);
+ } catch (\Exception $e) {
+ }
+ if (true === $e || [] === $e) {
+ continue;
+ }
+ $ok = false;
+ $type = get_debug_type($v);
+ $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]);
+ }
+ }
+
+ return $ok;
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php b/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php
new file mode 100644
index 0000000..a384b16
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php
@@ -0,0 +1,330 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Psr\Log\LoggerAwareInterface;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Component\Cache\Traits\AbstractAdapterTrait;
+use Symfony\Component\Cache\Traits\ContractsTrait;
+use Symfony\Contracts\Cache\TagAwareCacheInterface;
+
+/**
+ * Abstract for native TagAware adapters.
+ *
+ * To keep info on tags, the tags are both serialized as part of cache value and provided as tag ids
+ * to Adapters on operations when needed for storage to doSave(), doDelete() & doInvalidate().
+ *
+ * @author Nicolas Grekas
+ * @author André Rømcke
+ *
+ * @internal
+ */
+abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface, LoggerAwareInterface, ResettableInterface
+{
+ use AbstractAdapterTrait;
+ use ContractsTrait;
+
+ private const TAGS_PREFIX = "\0tags\0";
+
+ protected function __construct(string $namespace = '', int $defaultLifetime = 0)
+ {
+ $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':';
+ $this->defaultLifetime = $defaultLifetime;
+ if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) {
+ throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s").', $this->maxIdLength - 24, \strlen($namespace), $namespace));
+ }
+ self::$createCacheItem ?? self::$createCacheItem = \Closure::bind(
+ static function ($key, $value, $isHit) {
+ $item = new CacheItem();
+ $item->key = $key;
+ $item->isTaggable = true;
+ // If structure does not match what we expect return item as is (no value and not a hit)
+ if (!\is_array($value) || !\array_key_exists('value', $value)) {
+ return $item;
+ }
+ $item->isHit = $isHit;
+ // Extract value, tags and meta data from the cache value
+ $item->value = $value['value'];
+ $item->metadata[CacheItem::METADATA_TAGS] = $value['tags'] ?? [];
+ if (isset($value['meta'])) {
+ // For compactness these values are packed, & expiry is offset to reduce size
+ $v = unpack('Ve/Nc', $value['meta']);
+ $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET;
+ $item->metadata[CacheItem::METADATA_CTIME] = $v['c'];
+ }
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ self::$mergeByLifetime ?? self::$mergeByLifetime = \Closure::bind(
+ static function ($deferred, &$expiredIds, $getId, $tagPrefix, $defaultLifetime) {
+ $byLifetime = [];
+ $now = microtime(true);
+ $expiredIds = [];
+
+ foreach ($deferred as $key => $item) {
+ $key = (string) $key;
+ if (null === $item->expiry) {
+ $ttl = 0 < $defaultLifetime ? $defaultLifetime : 0;
+ } elseif (!$item->expiry) {
+ $ttl = 0;
+ } elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) {
+ $expiredIds[] = $getId($key);
+ continue;
+ }
+ // Store Value and Tags on the cache value
+ if (isset(($metadata = $item->newMetadata)[CacheItem::METADATA_TAGS])) {
+ $value = ['value' => $item->value, 'tags' => $metadata[CacheItem::METADATA_TAGS]];
+ unset($metadata[CacheItem::METADATA_TAGS]);
+ } else {
+ $value = ['value' => $item->value, 'tags' => []];
+ }
+
+ if ($metadata) {
+ // For compactness, expiry and creation duration are packed, using magic numbers as separators
+ $value['meta'] = pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME]);
+ }
+
+ // Extract tag changes, these should be removed from values in doSave()
+ $value['tag-operations'] = ['add' => [], 'remove' => []];
+ $oldTags = $item->metadata[CacheItem::METADATA_TAGS] ?? [];
+ foreach (array_diff($value['tags'], $oldTags) as $addedTag) {
+ $value['tag-operations']['add'][] = $getId($tagPrefix.$addedTag);
+ }
+ foreach (array_diff($oldTags, $value['tags']) as $removedTag) {
+ $value['tag-operations']['remove'][] = $getId($tagPrefix.$removedTag);
+ }
+
+ $byLifetime[$ttl][$getId($key)] = $value;
+ $item->metadata = $item->newMetadata;
+ }
+
+ return $byLifetime;
+ },
+ null,
+ CacheItem::class
+ );
+ }
+
+ /**
+ * Persists several cache items immediately.
+ *
+ * @param array $values The values to cache, indexed by their cache identifier
+ * @param int $lifetime The lifetime of the cached values, 0 for persisting until manual cleaning
+ * @param array[] $addTagData Hash where key is tag id, and array value is list of cache id's to add to tag
+ * @param array[] $removeTagData Hash where key is tag id, and array value is list of cache id's to remove to tag
+ *
+ * @return array The identifiers that failed to be cached or a boolean stating if caching succeeded or not
+ */
+ abstract protected function doSave(array $values, int $lifetime, array $addTagData = [], array $removeTagData = []): array;
+
+ /**
+ * Removes multiple items from the pool and their corresponding tags.
+ *
+ * @param array $ids An array of identifiers that should be removed from the pool
+ *
+ * @return bool
+ */
+ abstract protected function doDelete(array $ids);
+
+ /**
+ * Removes relations between tags and deleted items.
+ *
+ * @param array $tagData Array of tag => key identifiers that should be removed from the pool
+ */
+ abstract protected function doDeleteTagRelations(array $tagData): bool;
+
+ /**
+ * Invalidates cached items using tags.
+ *
+ * @param string[] $tagIds An array of tags to invalidate, key is tag and value is tag id
+ */
+ abstract protected function doInvalidate(array $tagIds): bool;
+
+ /**
+ * Delete items and yields the tags they were bound to.
+ */
+ protected function doDeleteYieldTags(array $ids): iterable
+ {
+ foreach ($this->doFetch($ids) as $id => $value) {
+ yield $id => \is_array($value) && \is_array($value['tags'] ?? null) ? $value['tags'] : [];
+ }
+
+ $this->doDelete($ids);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function commit(): bool
+ {
+ $ok = true;
+ $byLifetime = (self::$mergeByLifetime)($this->deferred, $expiredIds, \Closure::fromCallable([$this, 'getId']), self::TAGS_PREFIX, $this->defaultLifetime);
+ $retry = $this->deferred = [];
+
+ if ($expiredIds) {
+ // Tags are not cleaned up in this case, however that is done on invalidateTags().
+ try {
+ $this->doDelete($expiredIds);
+ } catch (\Exception $e) {
+ $ok = false;
+ CacheItem::log($this->logger, 'Failed to delete expired items: '.$e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]);
+ }
+ }
+ foreach ($byLifetime as $lifetime => $values) {
+ try {
+ $values = $this->extractTagData($values, $addTagData, $removeTagData);
+ $e = $this->doSave($values, $lifetime, $addTagData, $removeTagData);
+ } catch (\Exception $e) {
+ }
+ if (true === $e || [] === $e) {
+ continue;
+ }
+ if (\is_array($e) || 1 === \count($values)) {
+ foreach (\is_array($e) ? $e : array_keys($values) as $id) {
+ $ok = false;
+ $v = $values[$id];
+ $type = get_debug_type($v);
+ $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]);
+ }
+ } else {
+ foreach ($values as $id => $v) {
+ $retry[$lifetime][] = $id;
+ }
+ }
+ }
+
+ // When bulk-save failed, retry each item individually
+ foreach ($retry as $lifetime => $ids) {
+ foreach ($ids as $id) {
+ try {
+ $v = $byLifetime[$lifetime][$id];
+ $values = $this->extractTagData([$id => $v], $addTagData, $removeTagData);
+ $e = $this->doSave($values, $lifetime, $addTagData, $removeTagData);
+ } catch (\Exception $e) {
+ }
+ if (true === $e || [] === $e) {
+ continue;
+ }
+ $ok = false;
+ $type = get_debug_type($v);
+ $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]);
+ }
+ }
+
+ return $ok;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteItems(array $keys): bool
+ {
+ if (!$keys) {
+ return true;
+ }
+
+ $ok = true;
+ $ids = [];
+ $tagData = [];
+
+ foreach ($keys as $key) {
+ $ids[$key] = $this->getId($key);
+ unset($this->deferred[$key]);
+ }
+
+ try {
+ foreach ($this->doDeleteYieldTags(array_values($ids)) as $id => $tags) {
+ foreach ($tags as $tag) {
+ $tagData[$this->getId(self::TAGS_PREFIX.$tag)][] = $id;
+ }
+ }
+ } catch (\Exception $e) {
+ $ok = false;
+ }
+
+ try {
+ if ((!$tagData || $this->doDeleteTagRelations($tagData)) && $ok) {
+ return true;
+ }
+ } catch (\Exception $e) {
+ }
+
+ // When bulk-delete failed, retry each item individually
+ foreach ($ids as $key => $id) {
+ try {
+ $e = null;
+ if ($this->doDelete([$id])) {
+ continue;
+ }
+ } catch (\Exception $e) {
+ }
+ $message = 'Failed to delete key "{key}"'.($e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
+ $ok = false;
+ }
+
+ return $ok;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function invalidateTags(array $tags)
+ {
+ if (empty($tags)) {
+ return false;
+ }
+
+ $tagIds = [];
+ foreach (array_unique($tags) as $tag) {
+ $tagIds[] = $this->getId(self::TAGS_PREFIX.$tag);
+ }
+
+ try {
+ if ($this->doInvalidate($tagIds)) {
+ return true;
+ }
+ } catch (\Exception $e) {
+ CacheItem::log($this->logger, 'Failed to invalidate tags: '.$e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]);
+ }
+
+ return false;
+ }
+
+ /**
+ * Extracts tags operation data from $values set in mergeByLifetime, and returns values without it.
+ */
+ private function extractTagData(array $values, ?array &$addTagData, ?array &$removeTagData): array
+ {
+ $addTagData = $removeTagData = [];
+ foreach ($values as $id => $value) {
+ foreach ($value['tag-operations']['add'] as $tag => $tagId) {
+ $addTagData[$tagId][] = $id;
+ }
+
+ foreach ($value['tag-operations']['remove'] as $tag => $tagId) {
+ $removeTagData[$tagId][] = $id;
+ }
+
+ unset($values[$id]['tag-operations']);
+ }
+
+ return $values;
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/AdapterInterface.php b/vendor/symfony/cache/Adapter/AdapterInterface.php
new file mode 100644
index 0000000..f8dce86
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/AdapterInterface.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\Adapter;
+
+use Psr\Cache\CacheItemPoolInterface;
+use Symfony\Component\Cache\CacheItem;
+
+// Help opcache.preload discover always-needed symbols
+class_exists(CacheItem::class);
+
+/**
+ * Interface for adapters managing instances of Symfony's CacheItem.
+ *
+ * @author Kévin Dunglas
+ */
+interface AdapterInterface extends CacheItemPoolInterface
+{
+ /**
+ * {@inheritdoc}
+ *
+ * @return CacheItem
+ */
+ public function getItem($key);
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return \Traversable
+ */
+ public function getItems(array $keys = []);
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function clear(string $prefix = '');
+}
diff --git a/vendor/symfony/cache/Adapter/ApcuAdapter.php b/vendor/symfony/cache/Adapter/ApcuAdapter.php
new file mode 100644
index 0000000..270a139
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/ApcuAdapter.php
@@ -0,0 +1,138 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\Exception\CacheException;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+
+/**
+ * @author Nicolas Grekas
+ */
+class ApcuAdapter extends AbstractAdapter
+{
+ private $marshaller;
+
+ /**
+ * @throws CacheException if APCu is not enabled
+ */
+ public function __construct(string $namespace = '', int $defaultLifetime = 0, string $version = null, MarshallerInterface $marshaller = null)
+ {
+ if (!static::isSupported()) {
+ throw new CacheException('APCu is not enabled.');
+ }
+ if ('cli' === \PHP_SAPI) {
+ ini_set('apc.use_request_time', 0);
+ }
+ parent::__construct($namespace, $defaultLifetime);
+
+ if (null !== $version) {
+ CacheItem::validateKey($version);
+
+ if (!apcu_exists($version.'@'.$namespace)) {
+ $this->doClear($namespace);
+ apcu_add($version.'@'.$namespace, null);
+ }
+ }
+
+ $this->marshaller = $marshaller;
+ }
+
+ public static function isSupported()
+ {
+ return \function_exists('apcu_fetch') && filter_var(\ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doFetch(array $ids)
+ {
+ $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
+ try {
+ $values = [];
+ $ids = array_flip($ids);
+ foreach (apcu_fetch(array_keys($ids), $ok) ?: [] as $k => $v) {
+ if (!isset($ids[$k])) {
+ // work around https://github.com/krakjoe/apcu/issues/247
+ $k = key($ids);
+ }
+ unset($ids[$k]);
+
+ if (null !== $v || $ok) {
+ $values[$k] = null !== $this->marshaller ? $this->marshaller->unmarshall($v) : $v;
+ }
+ }
+
+ return $values;
+ } catch (\Error $e) {
+ throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine());
+ } finally {
+ ini_set('unserialize_callback_func', $unserializeCallbackHandler);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doHave(string $id)
+ {
+ return apcu_exists($id);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doClear(string $namespace)
+ {
+ return isset($namespace[0]) && class_exists(\APCUIterator::class, false) && ('cli' !== \PHP_SAPI || filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN))
+ ? apcu_delete(new \APCUIterator(sprintf('/^%s/', preg_quote($namespace, '/')), \APC_ITER_KEY))
+ : apcu_clear_cache();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDelete(array $ids)
+ {
+ foreach ($ids as $id) {
+ apcu_delete($id);
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, int $lifetime)
+ {
+ if (null !== $this->marshaller && (!$values = $this->marshaller->marshall($values, $failed))) {
+ return $failed;
+ }
+
+ try {
+ if (false === $failures = apcu_store($values, null, $lifetime)) {
+ $failures = $values;
+ }
+
+ return array_keys($failures);
+ } catch (\Throwable $e) {
+ if (1 === \count($values)) {
+ // Workaround https://github.com/krakjoe/apcu/issues/170
+ apcu_delete(array_key_first($values));
+ }
+
+ throw $e;
+ }
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/ArrayAdapter.php b/vendor/symfony/cache/Adapter/ArrayAdapter.php
new file mode 100644
index 0000000..d8695b7
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/ArrayAdapter.php
@@ -0,0 +1,407 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Psr\Cache\CacheItemInterface;
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerAwareTrait;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Contracts\Cache\CacheInterface;
+
+/**
+ * An in-memory cache storage.
+ *
+ * Acts as a least-recently-used (LRU) storage when configured with a maximum number of items.
+ *
+ * @author Nicolas Grekas
+ */
+class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface
+{
+ use LoggerAwareTrait;
+
+ private $storeSerialized;
+ private $values = [];
+ private $expiries = [];
+ private $defaultLifetime;
+ private $maxLifetime;
+ private $maxItems;
+
+ private static $createCacheItem;
+
+ /**
+ * @param bool $storeSerialized Disabling serialization can lead to cache corruptions when storing mutable values but increases performance otherwise
+ */
+ public function __construct(int $defaultLifetime = 0, bool $storeSerialized = true, float $maxLifetime = 0, int $maxItems = 0)
+ {
+ if (0 > $maxLifetime) {
+ throw new InvalidArgumentException(sprintf('Argument $maxLifetime must be positive, %F passed.', $maxLifetime));
+ }
+
+ if (0 > $maxItems) {
+ throw new InvalidArgumentException(sprintf('Argument $maxItems must be a positive integer, %d passed.', $maxItems));
+ }
+
+ $this->defaultLifetime = $defaultLifetime;
+ $this->storeSerialized = $storeSerialized;
+ $this->maxLifetime = $maxLifetime;
+ $this->maxItems = $maxItems;
+ self::$createCacheItem ?? self::$createCacheItem = \Closure::bind(
+ static function ($key, $value, $isHit) {
+ $item = new CacheItem();
+ $item->key = $key;
+ $item->value = $value;
+ $item->isHit = $isHit;
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ $item = $this->getItem($key);
+ $metadata = $item->getMetadata();
+
+ // ArrayAdapter works in memory, we don't care about stampede protection
+ if (\INF === $beta || !$item->isHit()) {
+ $save = true;
+ $item->set($callback($item, $save));
+ if ($save) {
+ $this->save($item);
+ }
+ }
+
+ return $item->get();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete(string $key): bool
+ {
+ return $this->deleteItem($key);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function hasItem($key)
+ {
+ if (\is_string($key) && isset($this->expiries[$key]) && $this->expiries[$key] > microtime(true)) {
+ if ($this->maxItems) {
+ // Move the item last in the storage
+ $value = $this->values[$key];
+ unset($this->values[$key]);
+ $this->values[$key] = $value;
+ }
+
+ return true;
+ }
+ \assert('' !== CacheItem::validateKey($key));
+
+ return isset($this->expiries[$key]) && !$this->deleteItem($key);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItem($key)
+ {
+ if (!$isHit = $this->hasItem($key)) {
+ $value = null;
+
+ if (!$this->maxItems) {
+ // Track misses in non-LRU mode only
+ $this->values[$key] = null;
+ }
+ } else {
+ $value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key];
+ }
+
+ return (self::$createCacheItem)($key, $value, $isHit);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItems(array $keys = [])
+ {
+ \assert(self::validateKeys($keys));
+
+ return $this->generateItems($keys, microtime(true), self::$createCacheItem);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItem($key)
+ {
+ \assert('' !== CacheItem::validateKey($key));
+ unset($this->values[$key], $this->expiries[$key]);
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItems(array $keys)
+ {
+ foreach ($keys as $key) {
+ $this->deleteItem($key);
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function save(CacheItemInterface $item)
+ {
+ if (!$item instanceof CacheItem) {
+ return false;
+ }
+ $item = (array) $item;
+ $key = $item["\0*\0key"];
+ $value = $item["\0*\0value"];
+ $expiry = $item["\0*\0expiry"];
+
+ $now = microtime(true);
+
+ if (null !== $expiry) {
+ if (!$expiry) {
+ $expiry = \PHP_INT_MAX;
+ } elseif ($expiry <= $now) {
+ $this->deleteItem($key);
+
+ return true;
+ }
+ }
+ if ($this->storeSerialized && null === $value = $this->freeze($value, $key)) {
+ return false;
+ }
+ if (null === $expiry && 0 < $this->defaultLifetime) {
+ $expiry = $this->defaultLifetime;
+ $expiry = $now + ($expiry > ($this->maxLifetime ?: $expiry) ? $this->maxLifetime : $expiry);
+ } elseif ($this->maxLifetime && (null === $expiry || $expiry > $now + $this->maxLifetime)) {
+ $expiry = $now + $this->maxLifetime;
+ }
+
+ if ($this->maxItems) {
+ unset($this->values[$key]);
+
+ // Iterate items and vacuum expired ones while we are at it
+ foreach ($this->values as $k => $v) {
+ if ($this->expiries[$k] > $now && \count($this->values) < $this->maxItems) {
+ break;
+ }
+
+ unset($this->values[$k], $this->expiries[$k]);
+ }
+ }
+
+ $this->values[$key] = $value;
+ $this->expiries[$key] = $expiry ?? \PHP_INT_MAX;
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function saveDeferred(CacheItemInterface $item)
+ {
+ return $this->save($item);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function commit()
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function clear(string $prefix = '')
+ {
+ if ('' !== $prefix) {
+ $now = microtime(true);
+
+ foreach ($this->values as $key => $value) {
+ if (!isset($this->expiries[$key]) || $this->expiries[$key] <= $now || 0 === strpos($key, $prefix)) {
+ unset($this->values[$key], $this->expiries[$key]);
+ }
+ }
+
+ if ($this->values) {
+ return true;
+ }
+ }
+
+ $this->values = $this->expiries = [];
+
+ return true;
+ }
+
+ /**
+ * Returns all cached values, with cache miss as null.
+ *
+ * @return array
+ */
+ public function getValues()
+ {
+ if (!$this->storeSerialized) {
+ return $this->values;
+ }
+
+ $values = $this->values;
+ foreach ($values as $k => $v) {
+ if (null === $v || 'N;' === $v) {
+ continue;
+ }
+ if (!\is_string($v) || !isset($v[2]) || ':' !== $v[1]) {
+ $values[$k] = serialize($v);
+ }
+ }
+
+ return $values;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function reset()
+ {
+ $this->clear();
+ }
+
+ private function generateItems(array $keys, float $now, \Closure $f): \Generator
+ {
+ foreach ($keys as $i => $key) {
+ if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > $now || !$this->deleteItem($key))) {
+ $value = null;
+
+ if (!$this->maxItems) {
+ // Track misses in non-LRU mode only
+ $this->values[$key] = null;
+ }
+ } else {
+ if ($this->maxItems) {
+ // Move the item last in the storage
+ $value = $this->values[$key];
+ unset($this->values[$key]);
+ $this->values[$key] = $value;
+ }
+
+ $value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key];
+ }
+ unset($keys[$i]);
+
+ yield $key => $f($key, $value, $isHit);
+ }
+
+ foreach ($keys as $key) {
+ yield $key => $f($key, null, false);
+ }
+ }
+
+ private function freeze($value, string $key)
+ {
+ if (null === $value) {
+ return 'N;';
+ }
+ if (\is_string($value)) {
+ // Serialize strings if they could be confused with serialized objects or arrays
+ if ('N;' === $value || (isset($value[2]) && ':' === $value[1])) {
+ return serialize($value);
+ }
+ } elseif (!\is_scalar($value)) {
+ try {
+ $serialized = serialize($value);
+ } catch (\Exception $e) {
+ unset($this->values[$key]);
+ $type = get_debug_type($value);
+ $message = sprintf('Failed to save key "{key}" of type %s: %s', $type, $e->getMessage());
+ CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
+
+ return;
+ }
+ // Keep value serialized if it contains any objects or any internal references
+ if ('C' === $serialized[0] || 'O' === $serialized[0] || preg_match('/;[OCRr]:[1-9]/', $serialized)) {
+ return $serialized;
+ }
+ }
+
+ return $value;
+ }
+
+ private function unfreeze(string $key, bool &$isHit)
+ {
+ if ('N;' === $value = $this->values[$key]) {
+ return null;
+ }
+ if (\is_string($value) && isset($value[2]) && ':' === $value[1]) {
+ try {
+ $value = unserialize($value);
+ } catch (\Exception $e) {
+ CacheItem::log($this->logger, 'Failed to unserialize key "{key}": '.$e->getMessage(), ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
+ $value = false;
+ }
+ if (false === $value) {
+ $value = null;
+ $isHit = false;
+
+ if (!$this->maxItems) {
+ $this->values[$key] = null;
+ }
+ }
+ }
+
+ return $value;
+ }
+
+ private function validateKeys(array $keys): bool
+ {
+ foreach ($keys as $key) {
+ if (!\is_string($key) || !isset($this->expiries[$key])) {
+ CacheItem::validateKey($key);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/ChainAdapter.php b/vendor/symfony/cache/Adapter/ChainAdapter.php
new file mode 100644
index 0000000..059c0ed
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/ChainAdapter.php
@@ -0,0 +1,342 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Psr\Cache\CacheItemInterface;
+use Psr\Cache\CacheItemPoolInterface;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Component\Cache\Traits\ContractsTrait;
+use Symfony\Contracts\Cache\CacheInterface;
+use Symfony\Contracts\Service\ResetInterface;
+
+/**
+ * Chains several adapters together.
+ *
+ * Cached items are fetched from the first adapter having them in its data store.
+ * They are saved and deleted in all adapters at once.
+ *
+ * @author Kévin Dunglas
+ */
+class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface
+{
+ use ContractsTrait;
+
+ private $adapters = [];
+ private $adapterCount;
+ private $defaultLifetime;
+
+ private static $syncItem;
+
+ /**
+ * @param CacheItemPoolInterface[] $adapters The ordered list of adapters used to fetch cached items
+ * @param int $defaultLifetime The default lifetime of items propagated from lower adapters to upper ones
+ */
+ public function __construct(array $adapters, int $defaultLifetime = 0)
+ {
+ if (!$adapters) {
+ throw new InvalidArgumentException('At least one adapter must be specified.');
+ }
+
+ foreach ($adapters as $adapter) {
+ if (!$adapter instanceof CacheItemPoolInterface) {
+ throw new InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', get_debug_type($adapter), CacheItemPoolInterface::class));
+ }
+ if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && $adapter instanceof ApcuAdapter && !filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) {
+ continue; // skip putting APCu in the chain when the backend is disabled
+ }
+
+ if ($adapter instanceof AdapterInterface) {
+ $this->adapters[] = $adapter;
+ } else {
+ $this->adapters[] = new ProxyAdapter($adapter);
+ }
+ }
+ $this->adapterCount = \count($this->adapters);
+ $this->defaultLifetime = $defaultLifetime;
+
+ self::$syncItem ?? self::$syncItem = \Closure::bind(
+ static function ($sourceItem, $item, $defaultLifetime, $sourceMetadata = null) {
+ $sourceItem->isTaggable = false;
+ $sourceMetadata = $sourceMetadata ?? $sourceItem->metadata;
+ unset($sourceMetadata[CacheItem::METADATA_TAGS]);
+
+ $item->value = $sourceItem->value;
+ $item->isHit = $sourceItem->isHit;
+ $item->metadata = $item->newMetadata = $sourceItem->metadata = $sourceMetadata;
+
+ if (isset($item->metadata[CacheItem::METADATA_EXPIRY])) {
+ $item->expiresAt(\DateTime::createFromFormat('U.u', sprintf('%.6F', $item->metadata[CacheItem::METADATA_EXPIRY])));
+ } elseif (0 < $defaultLifetime) {
+ $item->expiresAfter($defaultLifetime);
+ }
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ $doSave = true;
+ $callback = static function (CacheItem $item, bool &$save) use ($callback, &$doSave) {
+ $value = $callback($item, $save);
+ $doSave = $save;
+
+ return $value;
+ };
+
+ $lastItem = null;
+ $i = 0;
+ $wrap = function (CacheItem $item = null, bool &$save = true) use ($key, $callback, $beta, &$wrap, &$i, &$doSave, &$lastItem, &$metadata) {
+ $adapter = $this->adapters[$i];
+ if (isset($this->adapters[++$i])) {
+ $callback = $wrap;
+ $beta = \INF === $beta ? \INF : 0;
+ }
+ if ($adapter instanceof CacheInterface) {
+ $value = $adapter->get($key, $callback, $beta, $metadata);
+ } else {
+ $value = $this->doGet($adapter, $key, $callback, $beta, $metadata);
+ }
+ if (null !== $item) {
+ (self::$syncItem)($lastItem = $lastItem ?? $item, $item, $this->defaultLifetime, $metadata);
+ }
+ $save = $doSave;
+
+ return $value;
+ };
+
+ return $wrap();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItem($key)
+ {
+ $syncItem = self::$syncItem;
+ $misses = [];
+
+ foreach ($this->adapters as $i => $adapter) {
+ $item = $adapter->getItem($key);
+
+ if ($item->isHit()) {
+ while (0 <= --$i) {
+ $this->adapters[$i]->save($syncItem($item, $misses[$i], $this->defaultLifetime));
+ }
+
+ return $item;
+ }
+
+ $misses[$i] = $item;
+ }
+
+ return $item;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItems(array $keys = [])
+ {
+ return $this->generateItems($this->adapters[0]->getItems($keys), 0);
+ }
+
+ private function generateItems(iterable $items, int $adapterIndex): \Generator
+ {
+ $missing = [];
+ $misses = [];
+ $nextAdapterIndex = $adapterIndex + 1;
+ $nextAdapter = $this->adapters[$nextAdapterIndex] ?? null;
+
+ foreach ($items as $k => $item) {
+ if (!$nextAdapter || $item->isHit()) {
+ yield $k => $item;
+ } else {
+ $missing[] = $k;
+ $misses[$k] = $item;
+ }
+ }
+
+ if ($missing) {
+ $syncItem = self::$syncItem;
+ $adapter = $this->adapters[$adapterIndex];
+ $items = $this->generateItems($nextAdapter->getItems($missing), $nextAdapterIndex);
+
+ foreach ($items as $k => $item) {
+ if ($item->isHit()) {
+ $adapter->save($syncItem($item, $misses[$k], $this->defaultLifetime));
+ }
+
+ yield $k => $item;
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function hasItem($key)
+ {
+ foreach ($this->adapters as $adapter) {
+ if ($adapter->hasItem($key)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function clear(string $prefix = '')
+ {
+ $cleared = true;
+ $i = $this->adapterCount;
+
+ while ($i--) {
+ if ($this->adapters[$i] instanceof AdapterInterface) {
+ $cleared = $this->adapters[$i]->clear($prefix) && $cleared;
+ } else {
+ $cleared = $this->adapters[$i]->clear() && $cleared;
+ }
+ }
+
+ return $cleared;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItem($key)
+ {
+ $deleted = true;
+ $i = $this->adapterCount;
+
+ while ($i--) {
+ $deleted = $this->adapters[$i]->deleteItem($key) && $deleted;
+ }
+
+ return $deleted;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItems(array $keys)
+ {
+ $deleted = true;
+ $i = $this->adapterCount;
+
+ while ($i--) {
+ $deleted = $this->adapters[$i]->deleteItems($keys) && $deleted;
+ }
+
+ return $deleted;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function save(CacheItemInterface $item)
+ {
+ $saved = true;
+ $i = $this->adapterCount;
+
+ while ($i--) {
+ $saved = $this->adapters[$i]->save($item) && $saved;
+ }
+
+ return $saved;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function saveDeferred(CacheItemInterface $item)
+ {
+ $saved = true;
+ $i = $this->adapterCount;
+
+ while ($i--) {
+ $saved = $this->adapters[$i]->saveDeferred($item) && $saved;
+ }
+
+ return $saved;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function commit()
+ {
+ $committed = true;
+ $i = $this->adapterCount;
+
+ while ($i--) {
+ $committed = $this->adapters[$i]->commit() && $committed;
+ }
+
+ return $committed;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function prune()
+ {
+ $pruned = true;
+
+ foreach ($this->adapters as $adapter) {
+ if ($adapter instanceof PruneableInterface) {
+ $pruned = $adapter->prune() && $pruned;
+ }
+ }
+
+ return $pruned;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function reset()
+ {
+ foreach ($this->adapters as $adapter) {
+ if ($adapter instanceof ResetInterface) {
+ $adapter->reset();
+ }
+ }
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/CouchbaseBucketAdapter.php b/vendor/symfony/cache/Adapter/CouchbaseBucketAdapter.php
new file mode 100644
index 0000000..36d5249
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/CouchbaseBucketAdapter.php
@@ -0,0 +1,252 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Symfony\Component\Cache\Exception\CacheException;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\Marshaller\DefaultMarshaller;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+
+/**
+ * @author Antonio Jose Cerezo Aranda
+ */
+class CouchbaseBucketAdapter extends AbstractAdapter
+{
+ private const THIRTY_DAYS_IN_SECONDS = 2592000;
+ private const MAX_KEY_LENGTH = 250;
+ private const KEY_NOT_FOUND = 13;
+ private const VALID_DSN_OPTIONS = [
+ 'operationTimeout',
+ 'configTimeout',
+ 'configNodeTimeout',
+ 'n1qlTimeout',
+ 'httpTimeout',
+ 'configDelay',
+ 'htconfigIdleTimeout',
+ 'durabilityInterval',
+ 'durabilityTimeout',
+ ];
+
+ private $bucket;
+ private $marshaller;
+
+ public function __construct(\CouchbaseBucket $bucket, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
+ {
+ if (!static::isSupported()) {
+ throw new CacheException('Couchbase >= 2.6.0 < 3.0.0 is required.');
+ }
+
+ $this->maxIdLength = static::MAX_KEY_LENGTH;
+
+ $this->bucket = $bucket;
+
+ parent::__construct($namespace, $defaultLifetime);
+ $this->enableVersioning();
+ $this->marshaller = $marshaller ?? new DefaultMarshaller();
+ }
+
+ /**
+ * @param array|string $servers
+ */
+ public static function createConnection($servers, array $options = []): \CouchbaseBucket
+ {
+ if (\is_string($servers)) {
+ $servers = [$servers];
+ } elseif (!\is_array($servers)) {
+ throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be array or string, "%s" given.', __METHOD__, get_debug_type($servers)));
+ }
+
+ if (!static::isSupported()) {
+ throw new CacheException('Couchbase >= 2.6.0 < 3.0.0 is required.');
+ }
+
+ set_error_handler(function ($type, $msg, $file, $line) { throw new \ErrorException($msg, 0, $type, $file, $line); });
+
+ $dsnPattern = '/^(?couchbase(?:s)?)\:\/\/(?:(?[^\:]+)\:(?[^\@]{6,})@)?'
+ .'(?[^\:]+(?:\:\d+)?)(?:\/(?[^\?]+))(?:\?(?.*))?$/i';
+
+ $newServers = [];
+ $protocol = 'couchbase';
+ try {
+ $options = self::initOptions($options);
+ $username = $options['username'];
+ $password = $options['password'];
+
+ foreach ($servers as $dsn) {
+ if (0 !== strpos($dsn, 'couchbase:')) {
+ throw new InvalidArgumentException(sprintf('Invalid Couchbase DSN: "%s" does not start with "couchbase:".', $dsn));
+ }
+
+ preg_match($dsnPattern, $dsn, $matches);
+
+ $username = $matches['username'] ?: $username;
+ $password = $matches['password'] ?: $password;
+ $protocol = $matches['protocol'] ?: $protocol;
+
+ if (isset($matches['options'])) {
+ $optionsInDsn = self::getOptions($matches['options']);
+
+ foreach ($optionsInDsn as $parameter => $value) {
+ $options[$parameter] = $value;
+ }
+ }
+
+ $newServers[] = $matches['host'];
+ }
+
+ $connectionString = $protocol.'://'.implode(',', $newServers);
+
+ $client = new \CouchbaseCluster($connectionString);
+ $client->authenticateAs($username, $password);
+
+ $bucket = $client->openBucket($matches['bucketName']);
+
+ unset($options['username'], $options['password']);
+ foreach ($options as $option => $value) {
+ if (!empty($value)) {
+ $bucket->$option = $value;
+ }
+ }
+
+ return $bucket;
+ } finally {
+ restore_error_handler();
+ }
+ }
+
+ public static function isSupported(): bool
+ {
+ return \extension_loaded('couchbase') && version_compare(phpversion('couchbase'), '2.6.0', '>=') && version_compare(phpversion('couchbase'), '3.0', '<');
+ }
+
+ private static function getOptions(string $options): array
+ {
+ $results = [];
+ $optionsInArray = explode('&', $options);
+
+ foreach ($optionsInArray as $option) {
+ [$key, $value] = explode('=', $option);
+
+ if (\in_array($key, static::VALID_DSN_OPTIONS, true)) {
+ $results[$key] = $value;
+ }
+ }
+
+ return $results;
+ }
+
+ private static function initOptions(array $options): array
+ {
+ $options['username'] = $options['username'] ?? '';
+ $options['password'] = $options['password'] ?? '';
+ $options['operationTimeout'] = $options['operationTimeout'] ?? 0;
+ $options['configTimeout'] = $options['configTimeout'] ?? 0;
+ $options['configNodeTimeout'] = $options['configNodeTimeout'] ?? 0;
+ $options['n1qlTimeout'] = $options['n1qlTimeout'] ?? 0;
+ $options['httpTimeout'] = $options['httpTimeout'] ?? 0;
+ $options['configDelay'] = $options['configDelay'] ?? 0;
+ $options['htconfigIdleTimeout'] = $options['htconfigIdleTimeout'] ?? 0;
+ $options['durabilityInterval'] = $options['durabilityInterval'] ?? 0;
+ $options['durabilityTimeout'] = $options['durabilityTimeout'] ?? 0;
+
+ return $options;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doFetch(array $ids)
+ {
+ $resultsCouchbase = $this->bucket->get($ids);
+
+ $results = [];
+ foreach ($resultsCouchbase as $key => $value) {
+ if (null !== $value->error) {
+ continue;
+ }
+ $results[$key] = $this->marshaller->unmarshall($value->value);
+ }
+
+ return $results;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doHave(string $id): bool
+ {
+ return false !== $this->bucket->get($id);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doClear(string $namespace): bool
+ {
+ if ('' === $namespace) {
+ $this->bucket->manager()->flush();
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDelete(array $ids): bool
+ {
+ $results = $this->bucket->remove(array_values($ids));
+
+ foreach ($results as $key => $result) {
+ if (null !== $result->error && static::KEY_NOT_FOUND !== $result->error->getCode()) {
+ continue;
+ }
+ unset($results[$key]);
+ }
+
+ return 0 === \count($results);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, int $lifetime)
+ {
+ if (!$values = $this->marshaller->marshall($values, $failed)) {
+ return $failed;
+ }
+
+ $lifetime = $this->normalizeExpiry($lifetime);
+
+ $ko = [];
+ foreach ($values as $key => $value) {
+ $result = $this->bucket->upsert($key, $value, ['expiry' => $lifetime]);
+
+ if (null !== $result->error) {
+ $ko[$key] = $result;
+ }
+ }
+
+ return [] === $ko ? true : $ko;
+ }
+
+ private function normalizeExpiry(int $expiry): int
+ {
+ if ($expiry && $expiry > static::THIRTY_DAYS_IN_SECONDS) {
+ $expiry += time();
+ }
+
+ return $expiry;
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/CouchbaseCollectionAdapter.php b/vendor/symfony/cache/Adapter/CouchbaseCollectionAdapter.php
new file mode 100644
index 0000000..79f6485
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/CouchbaseCollectionAdapter.php
@@ -0,0 +1,222 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Couchbase\Bucket;
+use Couchbase\Cluster;
+use Couchbase\ClusterOptions;
+use Couchbase\Collection;
+use Couchbase\DocumentNotFoundException;
+use Couchbase\UpsertOptions;
+use Symfony\Component\Cache\Exception\CacheException;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\Marshaller\DefaultMarshaller;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+
+/**
+ * @author Antonio Jose Cerezo Aranda
+ */
+class CouchbaseCollectionAdapter extends AbstractAdapter
+{
+ private const MAX_KEY_LENGTH = 250;
+
+ /** @var Collection */
+ private $connection;
+ private $marshaller;
+
+ public function __construct(Collection $connection, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
+ {
+ if (!static::isSupported()) {
+ throw new CacheException('Couchbase >= 3.0.0 < 4.0.0 is required.');
+ }
+
+ $this->maxIdLength = static::MAX_KEY_LENGTH;
+
+ $this->connection = $connection;
+
+ parent::__construct($namespace, $defaultLifetime);
+ $this->enableVersioning();
+ $this->marshaller = $marshaller ?? new DefaultMarshaller();
+ }
+
+ /**
+ * @param array|string $dsn
+ *
+ * @return Bucket|Collection
+ */
+ public static function createConnection($dsn, array $options = [])
+ {
+ if (\is_string($dsn)) {
+ $dsn = [$dsn];
+ } elseif (!\is_array($dsn)) {
+ throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be array or string, "%s" given.', __METHOD__, get_debug_type($dsn)));
+ }
+
+ if (!static::isSupported()) {
+ throw new CacheException('Couchbase >= 3.0.0 < 4.0.0 is required.');
+ }
+
+ set_error_handler(function ($type, $msg, $file, $line): bool { throw new \ErrorException($msg, 0, $type, $file, $line); });
+
+ $dsnPattern = '/^(?couchbase(?:s)?)\:\/\/(?:(?[^\:]+)\:(?[^\@]{6,})@)?'
+ .'(?[^\:]+(?:\:\d+)?)(?:\/(?[^\/\?]+))(?:(?:\/(?[^\/]+))'
+ .'(?:\/(?[^\/\?]+)))?(?:\/)?(?:\?(?.*))?$/i';
+
+ $newServers = [];
+ $protocol = 'couchbase';
+ try {
+ $username = $options['username'] ?? '';
+ $password = $options['password'] ?? '';
+
+ foreach ($dsn as $server) {
+ if (0 !== strpos($server, 'couchbase:')) {
+ throw new InvalidArgumentException(sprintf('Invalid Couchbase DSN: "%s" does not start with "couchbase:".', $server));
+ }
+
+ preg_match($dsnPattern, $server, $matches);
+
+ $username = $matches['username'] ?: $username;
+ $password = $matches['password'] ?: $password;
+ $protocol = $matches['protocol'] ?: $protocol;
+
+ if (isset($matches['options'])) {
+ $optionsInDsn = self::getOptions($matches['options']);
+
+ foreach ($optionsInDsn as $parameter => $value) {
+ $options[$parameter] = $value;
+ }
+ }
+
+ $newServers[] = $matches['host'];
+ }
+
+ $option = isset($matches['options']) ? '?'.$matches['options'] : '';
+ $connectionString = $protocol.'://'.implode(',', $newServers).$option;
+
+ $clusterOptions = new ClusterOptions();
+ $clusterOptions->credentials($username, $password);
+
+ $client = new Cluster($connectionString, $clusterOptions);
+
+ $bucket = $client->bucket($matches['bucketName']);
+ $collection = $bucket->defaultCollection();
+ if (!empty($matches['scopeName'])) {
+ $scope = $bucket->scope($matches['scopeName']);
+ $collection = $scope->collection($matches['collectionName']);
+ }
+
+ return $collection;
+ } finally {
+ restore_error_handler();
+ }
+ }
+
+ public static function isSupported(): bool
+ {
+ return \extension_loaded('couchbase') && version_compare(phpversion('couchbase'), '3.0.5', '>=') && version_compare(phpversion('couchbase'), '4.0', '<');
+ }
+
+ private static function getOptions(string $options): array
+ {
+ $results = [];
+ $optionsInArray = explode('&', $options);
+
+ foreach ($optionsInArray as $option) {
+ [$key, $value] = explode('=', $option);
+
+ $results[$key] = $value;
+ }
+
+ return $results;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doFetch(array $ids): array
+ {
+ $results = [];
+ foreach ($ids as $id) {
+ try {
+ $resultCouchbase = $this->connection->get($id);
+ } catch (DocumentNotFoundException $exception) {
+ continue;
+ }
+
+ $content = $resultCouchbase->value ?? $resultCouchbase->content();
+
+ $results[$id] = $this->marshaller->unmarshall($content);
+ }
+
+ return $results;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doHave($id): bool
+ {
+ return $this->connection->exists($id)->exists();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doClear($namespace): bool
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDelete(array $ids): bool
+ {
+ $idsErrors = [];
+ foreach ($ids as $id) {
+ try {
+ $result = $this->connection->remove($id);
+
+ if (null === $result->mutationToken()) {
+ $idsErrors[] = $id;
+ }
+ } catch (DocumentNotFoundException $exception) {
+ }
+ }
+
+ return 0 === \count($idsErrors);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, $lifetime)
+ {
+ if (!$values = $this->marshaller->marshall($values, $failed)) {
+ return $failed;
+ }
+
+ $upsertOptions = new UpsertOptions();
+ $upsertOptions->expiry($lifetime);
+
+ $ko = [];
+ foreach ($values as $key => $value) {
+ try {
+ $this->connection->upsert($key, $value, $upsertOptions);
+ } catch (\Exception $exception) {
+ $ko[$key] = '';
+ }
+ }
+
+ return [] === $ko ? true : $ko;
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/DoctrineAdapter.php b/vendor/symfony/cache/Adapter/DoctrineAdapter.php
new file mode 100644
index 0000000..efa30c8
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/DoctrineAdapter.php
@@ -0,0 +1,110 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Doctrine\Common\Cache\CacheProvider;
+use Doctrine\Common\Cache\Psr6\CacheAdapter;
+
+/**
+ * @author Nicolas Grekas
+ *
+ * @deprecated Since Symfony 5.4, use Doctrine\Common\Cache\Psr6\CacheAdapter instead
+ */
+class DoctrineAdapter extends AbstractAdapter
+{
+ private $provider;
+
+ public function __construct(CacheProvider $provider, string $namespace = '', int $defaultLifetime = 0)
+ {
+ trigger_deprecation('symfony/cache', '5.4', '"%s" is deprecated, use "%s" instead.', __CLASS__, CacheAdapter::class);
+
+ parent::__construct('', $defaultLifetime);
+ $this->provider = $provider;
+ $provider->setNamespace($namespace);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function reset()
+ {
+ parent::reset();
+ $this->provider->setNamespace($this->provider->getNamespace());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doFetch(array $ids)
+ {
+ $unserializeCallbackHandler = ini_set('unserialize_callback_func', parent::class.'::handleUnserializeCallback');
+ try {
+ return $this->provider->fetchMultiple($ids);
+ } catch (\Error $e) {
+ $trace = $e->getTrace();
+
+ if (isset($trace[0]['function']) && !isset($trace[0]['class'])) {
+ switch ($trace[0]['function']) {
+ case 'unserialize':
+ case 'apcu_fetch':
+ case 'apc_fetch':
+ throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine());
+ }
+ }
+
+ throw $e;
+ } finally {
+ ini_set('unserialize_callback_func', $unserializeCallbackHandler);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doHave(string $id)
+ {
+ return $this->provider->contains($id);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doClear(string $namespace)
+ {
+ $namespace = $this->provider->getNamespace();
+
+ return isset($namespace[0])
+ ? $this->provider->deleteAll()
+ : $this->provider->flushAll();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDelete(array $ids)
+ {
+ $ok = true;
+ foreach ($ids as $id) {
+ $ok = $this->provider->delete($id) && $ok;
+ }
+
+ return $ok;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, int $lifetime)
+ {
+ return $this->provider->saveMultiple($values, $lifetime);
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/DoctrineDbalAdapter.php b/vendor/symfony/cache/Adapter/DoctrineDbalAdapter.php
new file mode 100644
index 0000000..73f0ea6
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/DoctrineDbalAdapter.php
@@ -0,0 +1,397 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Doctrine\DBAL\Connection;
+use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
+use Doctrine\DBAL\DriverManager;
+use Doctrine\DBAL\Exception as DBALException;
+use Doctrine\DBAL\Exception\TableNotFoundException;
+use Doctrine\DBAL\ParameterType;
+use Doctrine\DBAL\Schema\Schema;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\Marshaller\DefaultMarshaller;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+use Symfony\Component\Cache\PruneableInterface;
+
+class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface
+{
+ protected $maxIdLength = 255;
+
+ private $marshaller;
+ private $conn;
+ private $platformName;
+ private $serverVersion;
+ private $table = 'cache_items';
+ private $idCol = 'item_id';
+ private $dataCol = 'item_data';
+ private $lifetimeCol = 'item_lifetime';
+ private $timeCol = 'item_time';
+ private $namespace;
+
+ /**
+ * You can either pass an existing database Doctrine DBAL Connection or
+ * a DSN string that will be used to connect to the database.
+ *
+ * The cache table is created automatically when possible.
+ * Otherwise, use the createTable() method.
+ *
+ * List of available options:
+ * * db_table: The name of the table [default: cache_items]
+ * * db_id_col: The column where to store the cache id [default: item_id]
+ * * db_data_col: The column where to store the cache data [default: item_data]
+ * * db_lifetime_col: The column where to store the lifetime [default: item_lifetime]
+ * * db_time_col: The column where to store the timestamp [default: item_time]
+ *
+ * @param Connection|string $connOrDsn
+ *
+ * @throws InvalidArgumentException When namespace contains invalid characters
+ */
+ public function __construct($connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], MarshallerInterface $marshaller = null)
+ {
+ if (isset($namespace[0]) && preg_match('#[^-+.A-Za-z0-9]#', $namespace, $match)) {
+ throw new InvalidArgumentException(sprintf('Namespace contains "%s" but only characters in [-+.A-Za-z0-9] are allowed.', $match[0]));
+ }
+
+ if ($connOrDsn instanceof Connection) {
+ $this->conn = $connOrDsn;
+ } elseif (\is_string($connOrDsn)) {
+ if (!class_exists(DriverManager::class)) {
+ throw new InvalidArgumentException(sprintf('Failed to parse the DSN "%s". Try running "composer require doctrine/dbal".', $connOrDsn));
+ }
+ $this->conn = DriverManager::getConnection(['url' => $connOrDsn]);
+ } else {
+ throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be "%s" or string, "%s" given.', __METHOD__, Connection::class, get_debug_type($connOrDsn)));
+ }
+
+ $this->table = $options['db_table'] ?? $this->table;
+ $this->idCol = $options['db_id_col'] ?? $this->idCol;
+ $this->dataCol = $options['db_data_col'] ?? $this->dataCol;
+ $this->lifetimeCol = $options['db_lifetime_col'] ?? $this->lifetimeCol;
+ $this->timeCol = $options['db_time_col'] ?? $this->timeCol;
+ $this->namespace = $namespace;
+ $this->marshaller = $marshaller ?? new DefaultMarshaller();
+
+ parent::__construct($namespace, $defaultLifetime);
+ }
+
+ /**
+ * Creates the table to store cache items which can be called once for setup.
+ *
+ * Cache ID are saved in a column of maximum length 255. Cache data is
+ * saved in a BLOB.
+ *
+ * @throws DBALException When the table already exists
+ */
+ public function createTable()
+ {
+ $schema = new Schema();
+ $this->addTableToSchema($schema);
+
+ foreach ($schema->toSql($this->conn->getDatabasePlatform()) as $sql) {
+ $this->conn->executeStatement($sql);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function configureSchema(Schema $schema, Connection $forConnection): void
+ {
+ // only update the schema for this connection
+ if ($forConnection !== $this->conn) {
+ return;
+ }
+
+ if ($schema->hasTable($this->table)) {
+ return;
+ }
+
+ $this->addTableToSchema($schema);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function prune(): bool
+ {
+ $deleteSql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= ?";
+ $params = [time()];
+ $paramTypes = [ParameterType::INTEGER];
+
+ if ('' !== $this->namespace) {
+ $deleteSql .= " AND $this->idCol LIKE ?";
+ $params[] = sprintf('%s%%', $this->namespace);
+ $paramTypes[] = ParameterType::STRING;
+ }
+
+ try {
+ $this->conn->executeStatement($deleteSql, $params, $paramTypes);
+ } catch (TableNotFoundException $e) {
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doFetch(array $ids): iterable
+ {
+ $now = time();
+ $expired = [];
+
+ $sql = "SELECT $this->idCol, CASE WHEN $this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > ? THEN $this->dataCol ELSE NULL END FROM $this->table WHERE $this->idCol IN (?)";
+ $result = $this->conn->executeQuery($sql, [
+ $now,
+ $ids,
+ ], [
+ ParameterType::INTEGER,
+ Connection::PARAM_STR_ARRAY,
+ ])->iterateNumeric();
+
+ foreach ($result as $row) {
+ if (null === $row[1]) {
+ $expired[] = $row[0];
+ } else {
+ yield $row[0] => $this->marshaller->unmarshall(\is_resource($row[1]) ? stream_get_contents($row[1]) : $row[1]);
+ }
+ }
+
+ if ($expired) {
+ $sql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= ? AND $this->idCol IN (?)";
+ $this->conn->executeStatement($sql, [
+ $now,
+ $expired,
+ ], [
+ ParameterType::INTEGER,
+ Connection::PARAM_STR_ARRAY,
+ ]);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doHave(string $id): bool
+ {
+ $sql = "SELECT 1 FROM $this->table WHERE $this->idCol = ? AND ($this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > ?)";
+ $result = $this->conn->executeQuery($sql, [
+ $id,
+ time(),
+ ], [
+ ParameterType::STRING,
+ ParameterType::INTEGER,
+ ]);
+
+ return (bool) $result->fetchOne();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doClear(string $namespace): bool
+ {
+ if ('' === $namespace) {
+ if ('sqlite' === $this->getPlatformName()) {
+ $sql = "DELETE FROM $this->table";
+ } else {
+ $sql = "TRUNCATE TABLE $this->table";
+ }
+ } else {
+ $sql = "DELETE FROM $this->table WHERE $this->idCol LIKE '$namespace%'";
+ }
+
+ try {
+ $this->conn->executeStatement($sql);
+ } catch (TableNotFoundException $e) {
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDelete(array $ids): bool
+ {
+ $sql = "DELETE FROM $this->table WHERE $this->idCol IN (?)";
+ try {
+ $this->conn->executeStatement($sql, [array_values($ids)], [Connection::PARAM_STR_ARRAY]);
+ } catch (TableNotFoundException $e) {
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, int $lifetime)
+ {
+ if (!$values = $this->marshaller->marshall($values, $failed)) {
+ return $failed;
+ }
+
+ $platformName = $this->getPlatformName();
+ $insertSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?)";
+
+ switch (true) {
+ case 'mysql' === $platformName:
+ $sql = $insertSql." ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->lifetimeCol = VALUES($this->lifetimeCol), $this->timeCol = VALUES($this->timeCol)";
+ break;
+ case 'oci' === $platformName:
+ // DUAL is Oracle specific dummy table
+ $sql = "MERGE INTO $this->table USING DUAL ON ($this->idCol = ?) ".
+ "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ".
+ "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?";
+ break;
+ case 'sqlsrv' === $platformName && version_compare($this->getServerVersion(), '10', '>='):
+ // MERGE is only available since SQL Server 2008 and must be terminated by semicolon
+ // It also requires HOLDLOCK according to http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx
+ $sql = "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = ?) ".
+ "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ".
+ "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?;";
+ break;
+ case 'sqlite' === $platformName:
+ $sql = 'INSERT OR REPLACE'.substr($insertSql, 6);
+ break;
+ case 'pgsql' === $platformName && version_compare($this->getServerVersion(), '9.5', '>='):
+ $sql = $insertSql." ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)";
+ break;
+ default:
+ $platformName = null;
+ $sql = "UPDATE $this->table SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ? WHERE $this->idCol = ?";
+ break;
+ }
+
+ $now = time();
+ $lifetime = $lifetime ?: null;
+ try {
+ $stmt = $this->conn->prepare($sql);
+ } catch (TableNotFoundException $e) {
+ if (!$this->conn->isTransactionActive() || \in_array($platformName, ['pgsql', 'sqlite', 'sqlsrv'], true)) {
+ $this->createTable();
+ }
+ $stmt = $this->conn->prepare($sql);
+ }
+
+ // $id and $data are defined later in the loop. Binding is done by reference, values are read on execution.
+ if ('sqlsrv' === $platformName || 'oci' === $platformName) {
+ $stmt->bindParam(1, $id);
+ $stmt->bindParam(2, $id);
+ $stmt->bindParam(3, $data, ParameterType::LARGE_OBJECT);
+ $stmt->bindValue(4, $lifetime, ParameterType::INTEGER);
+ $stmt->bindValue(5, $now, ParameterType::INTEGER);
+ $stmt->bindParam(6, $data, ParameterType::LARGE_OBJECT);
+ $stmt->bindValue(7, $lifetime, ParameterType::INTEGER);
+ $stmt->bindValue(8, $now, ParameterType::INTEGER);
+ } elseif (null !== $platformName) {
+ $stmt->bindParam(1, $id);
+ $stmt->bindParam(2, $data, ParameterType::LARGE_OBJECT);
+ $stmt->bindValue(3, $lifetime, ParameterType::INTEGER);
+ $stmt->bindValue(4, $now, ParameterType::INTEGER);
+ } else {
+ $stmt->bindParam(1, $data, ParameterType::LARGE_OBJECT);
+ $stmt->bindValue(2, $lifetime, ParameterType::INTEGER);
+ $stmt->bindValue(3, $now, ParameterType::INTEGER);
+ $stmt->bindParam(4, $id);
+
+ $insertStmt = $this->conn->prepare($insertSql);
+ $insertStmt->bindParam(1, $id);
+ $insertStmt->bindParam(2, $data, ParameterType::LARGE_OBJECT);
+ $insertStmt->bindValue(3, $lifetime, ParameterType::INTEGER);
+ $insertStmt->bindValue(4, $now, ParameterType::INTEGER);
+ }
+
+ foreach ($values as $id => $data) {
+ try {
+ $rowCount = $stmt->executeStatement();
+ } catch (TableNotFoundException $e) {
+ if (!$this->conn->isTransactionActive() || \in_array($platformName, ['pgsql', 'sqlite', 'sqlsrv'], true)) {
+ $this->createTable();
+ }
+ $rowCount = $stmt->executeStatement();
+ }
+ if (null === $platformName && 0 === $rowCount) {
+ try {
+ $insertStmt->executeStatement();
+ } catch (DBALException $e) {
+ // A concurrent write won, let it be
+ }
+ }
+ }
+
+ return $failed;
+ }
+
+ private function getPlatformName(): string
+ {
+ if (isset($this->platformName)) {
+ return $this->platformName;
+ }
+
+ $platform = $this->conn->getDatabasePlatform();
+
+ switch (true) {
+ case $platform instanceof \Doctrine\DBAL\Platforms\MySQLPlatform:
+ case $platform instanceof \Doctrine\DBAL\Platforms\MySQL57Platform:
+ return $this->platformName = 'mysql';
+
+ case $platform instanceof \Doctrine\DBAL\Platforms\SqlitePlatform:
+ return $this->platformName = 'sqlite';
+
+ case $platform instanceof \Doctrine\DBAL\Platforms\PostgreSQLPlatform:
+ case $platform instanceof \Doctrine\DBAL\Platforms\PostgreSQL94Platform:
+ return $this->platformName = 'pgsql';
+
+ case $platform instanceof \Doctrine\DBAL\Platforms\OraclePlatform:
+ return $this->platformName = 'oci';
+
+ case $platform instanceof \Doctrine\DBAL\Platforms\SQLServerPlatform:
+ case $platform instanceof \Doctrine\DBAL\Platforms\SQLServer2012Platform:
+ return $this->platformName = 'sqlsrv';
+
+ default:
+ return $this->platformName = \get_class($platform);
+ }
+ }
+
+ private function getServerVersion(): string
+ {
+ if (isset($this->serverVersion)) {
+ return $this->serverVersion;
+ }
+
+ $conn = $this->conn->getWrappedConnection();
+ if ($conn instanceof ServerInfoAwareConnection) {
+ return $this->serverVersion = $conn->getServerVersion();
+ }
+
+ return $this->serverVersion = '0';
+ }
+
+ private function addTableToSchema(Schema $schema): void
+ {
+ $types = [
+ 'mysql' => 'binary',
+ 'sqlite' => 'text',
+ ];
+
+ $table = $schema->createTable($this->table);
+ $table->addColumn($this->idCol, $types[$this->getPlatformName()] ?? 'string', ['length' => 255]);
+ $table->addColumn($this->dataCol, 'blob', ['length' => 16777215]);
+ $table->addColumn($this->lifetimeCol, 'integer', ['unsigned' => true, 'notnull' => false]);
+ $table->addColumn($this->timeCol, 'integer', ['unsigned' => true]);
+ $table->setPrimaryKey([$this->idCol]);
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/FilesystemAdapter.php b/vendor/symfony/cache/Adapter/FilesystemAdapter.php
new file mode 100644
index 0000000..7185dd4
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/FilesystemAdapter.php
@@ -0,0 +1,29 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Symfony\Component\Cache\Marshaller\DefaultMarshaller;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\Traits\FilesystemTrait;
+
+class FilesystemAdapter extends AbstractAdapter implements PruneableInterface
+{
+ use FilesystemTrait;
+
+ public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, MarshallerInterface $marshaller = null)
+ {
+ $this->marshaller = $marshaller ?? new DefaultMarshaller();
+ parent::__construct('', $defaultLifetime);
+ $this->init($namespace, $directory);
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php b/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php
new file mode 100644
index 0000000..afde843
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php
@@ -0,0 +1,239 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+use Symfony\Component\Cache\Marshaller\TagAwareMarshaller;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\Traits\FilesystemTrait;
+
+/**
+ * Stores tag id <> cache id relationship as a symlink, and lookup on invalidation calls.
+ *
+ * @author Nicolas Grekas
+ * @author André Rømcke
+ */
+class FilesystemTagAwareAdapter extends AbstractTagAwareAdapter implements PruneableInterface
+{
+ use FilesystemTrait {
+ doClear as private doClearCache;
+ doSave as private doSaveCache;
+ }
+
+ /**
+ * Folder used for tag symlinks.
+ */
+ private const TAG_FOLDER = 'tags';
+
+ public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, MarshallerInterface $marshaller = null)
+ {
+ $this->marshaller = new TagAwareMarshaller($marshaller);
+ parent::__construct('', $defaultLifetime);
+ $this->init($namespace, $directory);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doClear(string $namespace)
+ {
+ $ok = $this->doClearCache($namespace);
+
+ if ('' !== $namespace) {
+ return $ok;
+ }
+
+ set_error_handler(static function () {});
+ $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
+
+ try {
+ foreach ($this->scanHashDir($this->directory.self::TAG_FOLDER.\DIRECTORY_SEPARATOR) as $dir) {
+ if (rename($dir, $renamed = substr_replace($dir, bin2hex(random_bytes(4)), -8))) {
+ $dir = $renamed.\DIRECTORY_SEPARATOR;
+ } else {
+ $dir .= \DIRECTORY_SEPARATOR;
+ $renamed = null;
+ }
+
+ for ($i = 0; $i < 38; ++$i) {
+ if (!is_dir($dir.$chars[$i])) {
+ continue;
+ }
+ for ($j = 0; $j < 38; ++$j) {
+ if (!is_dir($d = $dir.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j])) {
+ continue;
+ }
+ foreach (scandir($d, \SCANDIR_SORT_NONE) ?: [] as $link) {
+ if ('.' !== $link && '..' !== $link && (null !== $renamed || !realpath($d.\DIRECTORY_SEPARATOR.$link))) {
+ unlink($d.\DIRECTORY_SEPARATOR.$link);
+ }
+ }
+ null === $renamed ?: rmdir($d);
+ }
+ null === $renamed ?: rmdir($dir.$chars[$i]);
+ }
+ null === $renamed ?: rmdir($renamed);
+ }
+ } finally {
+ restore_error_handler();
+ }
+
+ return $ok;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, int $lifetime, array $addTagData = [], array $removeTagData = []): array
+ {
+ $failed = $this->doSaveCache($values, $lifetime);
+
+ // Add Tags as symlinks
+ foreach ($addTagData as $tagId => $ids) {
+ $tagFolder = $this->getTagFolder($tagId);
+ foreach ($ids as $id) {
+ if ($failed && \in_array($id, $failed, true)) {
+ continue;
+ }
+
+ $file = $this->getFile($id);
+
+ if (!@symlink($file, $tagLink = $this->getFile($id, true, $tagFolder)) && !is_link($tagLink)) {
+ @unlink($file);
+ $failed[] = $id;
+ }
+ }
+ }
+
+ // Unlink removed Tags
+ foreach ($removeTagData as $tagId => $ids) {
+ $tagFolder = $this->getTagFolder($tagId);
+ foreach ($ids as $id) {
+ if ($failed && \in_array($id, $failed, true)) {
+ continue;
+ }
+
+ @unlink($this->getFile($id, false, $tagFolder));
+ }
+ }
+
+ return $failed;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDeleteYieldTags(array $ids): iterable
+ {
+ foreach ($ids as $id) {
+ $file = $this->getFile($id);
+ if (!is_file($file) || !$h = @fopen($file, 'r')) {
+ continue;
+ }
+
+ if ((\PHP_VERSION_ID >= 70300 || '\\' !== \DIRECTORY_SEPARATOR) && !@unlink($file)) {
+ fclose($h);
+ continue;
+ }
+
+ $meta = explode("\n", fread($h, 4096), 3)[2] ?? '';
+
+ // detect the compact format used in marshall() using magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F
+ if (13 < \strlen($meta) && "\x9D" === $meta[0] && "\0" === $meta[5] && "\x5F" === $meta[9]) {
+ $meta[9] = "\0";
+ $tagLen = unpack('Nlen', $meta, 9)['len'];
+ $meta = substr($meta, 13, $tagLen);
+
+ if (0 < $tagLen -= \strlen($meta)) {
+ $meta .= fread($h, $tagLen);
+ }
+
+ try {
+ yield $id => '' === $meta ? [] : $this->marshaller->unmarshall($meta);
+ } catch (\Exception $e) {
+ yield $id => [];
+ }
+ }
+
+ fclose($h);
+
+ if (\PHP_VERSION_ID < 70300 && '\\' === \DIRECTORY_SEPARATOR) {
+ @unlink($file);
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDeleteTagRelations(array $tagData): bool
+ {
+ foreach ($tagData as $tagId => $idList) {
+ $tagFolder = $this->getTagFolder($tagId);
+ foreach ($idList as $id) {
+ @unlink($this->getFile($id, false, $tagFolder));
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doInvalidate(array $tagIds): bool
+ {
+ foreach ($tagIds as $tagId) {
+ if (!is_dir($tagFolder = $this->getTagFolder($tagId))) {
+ continue;
+ }
+
+ set_error_handler(static function () {});
+
+ try {
+ if (rename($tagFolder, $renamed = substr_replace($tagFolder, bin2hex(random_bytes(4)), -9))) {
+ $tagFolder = $renamed.\DIRECTORY_SEPARATOR;
+ } else {
+ $renamed = null;
+ }
+
+ foreach ($this->scanHashDir($tagFolder) as $itemLink) {
+ unlink(realpath($itemLink) ?: $itemLink);
+ unlink($itemLink);
+ }
+
+ if (null === $renamed) {
+ continue;
+ }
+
+ $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
+
+ for ($i = 0; $i < 38; ++$i) {
+ for ($j = 0; $j < 38; ++$j) {
+ rmdir($tagFolder.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j]);
+ }
+ rmdir($tagFolder.$chars[$i]);
+ }
+ rmdir($renamed);
+ } finally {
+ restore_error_handler();
+ }
+ }
+
+ return true;
+ }
+
+ private function getTagFolder(string $tagId): string
+ {
+ return $this->getFile($tagId, false, $this->directory.self::TAG_FOLDER.\DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR;
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/MemcachedAdapter.php b/vendor/symfony/cache/Adapter/MemcachedAdapter.php
new file mode 100644
index 0000000..5c2933f
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/MemcachedAdapter.php
@@ -0,0 +1,353 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Symfony\Component\Cache\Exception\CacheException;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\Marshaller\DefaultMarshaller;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+
+/**
+ * @author Rob Frawley 2nd
+ * @author Nicolas Grekas
+ */
+class MemcachedAdapter extends AbstractAdapter
+{
+ /**
+ * We are replacing characters that are illegal in Memcached keys with reserved characters from
+ * {@see \Symfony\Contracts\Cache\ItemInterface::RESERVED_CHARACTERS} that are legal in Memcached.
+ * Note: don’t use {@see \Symfony\Component\Cache\Adapter\AbstractAdapter::NS_SEPARATOR}.
+ */
+ private const RESERVED_MEMCACHED = " \n\r\t\v\f\0";
+ private const RESERVED_PSR6 = '@()\{}/';
+
+ protected $maxIdLength = 250;
+
+ private const DEFAULT_CLIENT_OPTIONS = [
+ 'persistent_id' => null,
+ 'username' => null,
+ 'password' => null,
+ \Memcached::OPT_SERIALIZER => \Memcached::SERIALIZER_PHP,
+ ];
+
+ private $marshaller;
+ private $client;
+ private $lazyClient;
+
+ /**
+ * Using a MemcachedAdapter with a TagAwareAdapter for storing tags is discouraged.
+ * Using a RedisAdapter is recommended instead. If you cannot do otherwise, be aware that:
+ * - the Memcached::OPT_BINARY_PROTOCOL must be enabled
+ * (that's the default when using MemcachedAdapter::createConnection());
+ * - tags eviction by Memcached's LRU algorithm will break by-tags invalidation;
+ * your Memcached memory should be large enough to never trigger LRU.
+ *
+ * Using a MemcachedAdapter as a pure items store is fine.
+ */
+ public function __construct(\Memcached $client, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
+ {
+ if (!static::isSupported()) {
+ throw new CacheException('Memcached '.(\PHP_VERSION_ID >= 80100 ? '> 3.1.5' : '>= 2.2.0').' is required.');
+ }
+ if ('Memcached' === \get_class($client)) {
+ $opt = $client->getOption(\Memcached::OPT_SERIALIZER);
+ if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) {
+ throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".');
+ }
+ $this->maxIdLength -= \strlen($client->getOption(\Memcached::OPT_PREFIX_KEY));
+ $this->client = $client;
+ } else {
+ $this->lazyClient = $client;
+ }
+
+ parent::__construct($namespace, $defaultLifetime);
+ $this->enableVersioning();
+ $this->marshaller = $marshaller ?? new DefaultMarshaller();
+ }
+
+ public static function isSupported()
+ {
+ return \extension_loaded('memcached') && version_compare(phpversion('memcached'), \PHP_VERSION_ID >= 80100 ? '3.1.6' : '2.2.0', '>=');
+ }
+
+ /**
+ * Creates a Memcached instance.
+ *
+ * By default, the binary protocol, no block, and libketama compatible options are enabled.
+ *
+ * Examples for servers:
+ * - 'memcached://user:pass@localhost?weight=33'
+ * - [['localhost', 11211, 33]]
+ *
+ * @param array[]|string|string[] $servers An array of servers, a DSN, or an array of DSNs
+ *
+ * @return \Memcached
+ *
+ * @throws \ErrorException When invalid options or servers are provided
+ */
+ public static function createConnection($servers, array $options = [])
+ {
+ if (\is_string($servers)) {
+ $servers = [$servers];
+ } elseif (!\is_array($servers)) {
+ throw new InvalidArgumentException(sprintf('MemcachedAdapter::createClient() expects array or string as first argument, "%s" given.', get_debug_type($servers)));
+ }
+ if (!static::isSupported()) {
+ throw new CacheException('Memcached '.(\PHP_VERSION_ID >= 80100 ? '> 3.1.5' : '>= 2.2.0').' is required.');
+ }
+ set_error_handler(function ($type, $msg, $file, $line) { throw new \ErrorException($msg, 0, $type, $file, $line); });
+ try {
+ $options += static::DEFAULT_CLIENT_OPTIONS;
+ $client = new \Memcached($options['persistent_id']);
+ $username = $options['username'];
+ $password = $options['password'];
+
+ // parse any DSN in $servers
+ foreach ($servers as $i => $dsn) {
+ if (\is_array($dsn)) {
+ continue;
+ }
+ if (!str_starts_with($dsn, 'memcached:')) {
+ throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: "%s" does not start with "memcached:".', $dsn));
+ }
+ $params = preg_replace_callback('#^memcached:(//)?(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) {
+ if (!empty($m[2])) {
+ [$username, $password] = explode(':', $m[2], 2) + [1 => null];
+ }
+
+ return 'file:'.($m[1] ?? '');
+ }, $dsn);
+ if (false === $params = parse_url($params)) {
+ throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: "%s".', $dsn));
+ }
+ $query = $hosts = [];
+ if (isset($params['query'])) {
+ parse_str($params['query'], $query);
+
+ if (isset($query['host'])) {
+ if (!\is_array($hosts = $query['host'])) {
+ throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: "%s".', $dsn));
+ }
+ foreach ($hosts as $host => $weight) {
+ if (false === $port = strrpos($host, ':')) {
+ $hosts[$host] = [$host, 11211, (int) $weight];
+ } else {
+ $hosts[$host] = [substr($host, 0, $port), (int) substr($host, 1 + $port), (int) $weight];
+ }
+ }
+ $hosts = array_values($hosts);
+ unset($query['host']);
+ }
+ if ($hosts && !isset($params['host']) && !isset($params['path'])) {
+ unset($servers[$i]);
+ $servers = array_merge($servers, $hosts);
+ continue;
+ }
+ }
+ if (!isset($params['host']) && !isset($params['path'])) {
+ throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: "%s".', $dsn));
+ }
+ if (isset($params['path']) && preg_match('#/(\d+)$#', $params['path'], $m)) {
+ $params['weight'] = $m[1];
+ $params['path'] = substr($params['path'], 0, -\strlen($m[0]));
+ }
+ $params += [
+ 'host' => $params['host'] ?? $params['path'],
+ 'port' => isset($params['host']) ? 11211 : null,
+ 'weight' => 0,
+ ];
+ if ($query) {
+ $params += $query;
+ $options = $query + $options;
+ }
+
+ $servers[$i] = [$params['host'], $params['port'], $params['weight']];
+
+ if ($hosts) {
+ $servers = array_merge($servers, $hosts);
+ }
+ }
+
+ // set client's options
+ unset($options['persistent_id'], $options['username'], $options['password'], $options['weight'], $options['lazy']);
+ $options = array_change_key_case($options, \CASE_UPPER);
+ $client->setOption(\Memcached::OPT_BINARY_PROTOCOL, true);
+ $client->setOption(\Memcached::OPT_NO_BLOCK, true);
+ $client->setOption(\Memcached::OPT_TCP_NODELAY, true);
+ if (!\array_key_exists('LIBKETAMA_COMPATIBLE', $options) && !\array_key_exists(\Memcached::OPT_LIBKETAMA_COMPATIBLE, $options)) {
+ $client->setOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE, true);
+ }
+ foreach ($options as $name => $value) {
+ if (\is_int($name)) {
+ continue;
+ }
+ if ('HASH' === $name || 'SERIALIZER' === $name || 'DISTRIBUTION' === $name) {
+ $value = \constant('Memcached::'.$name.'_'.strtoupper($value));
+ }
+ unset($options[$name]);
+
+ if (\defined('Memcached::OPT_'.$name)) {
+ $options[\constant('Memcached::OPT_'.$name)] = $value;
+ }
+ }
+ $client->setOptions($options);
+
+ // set client's servers, taking care of persistent connections
+ if (!$client->isPristine()) {
+ $oldServers = [];
+ foreach ($client->getServerList() as $server) {
+ $oldServers[] = [$server['host'], $server['port']];
+ }
+
+ $newServers = [];
+ foreach ($servers as $server) {
+ if (1 < \count($server)) {
+ $server = array_values($server);
+ unset($server[2]);
+ $server[1] = (int) $server[1];
+ }
+ $newServers[] = $server;
+ }
+
+ if ($oldServers !== $newServers) {
+ $client->resetServerList();
+ $client->addServers($servers);
+ }
+ } else {
+ $client->addServers($servers);
+ }
+
+ if (null !== $username || null !== $password) {
+ if (!method_exists($client, 'setSaslAuthData')) {
+ trigger_error('Missing SASL support: the memcached extension must be compiled with --enable-memcached-sasl.');
+ }
+ $client->setSaslAuthData($username, $password);
+ }
+
+ return $client;
+ } finally {
+ restore_error_handler();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, int $lifetime)
+ {
+ if (!$values = $this->marshaller->marshall($values, $failed)) {
+ return $failed;
+ }
+
+ if ($lifetime && $lifetime > 30 * 86400) {
+ $lifetime += time();
+ }
+
+ $encodedValues = [];
+ foreach ($values as $key => $value) {
+ $encodedValues[self::encodeKey($key)] = $value;
+ }
+
+ return $this->checkResultCode($this->getClient()->setMulti($encodedValues, $lifetime)) ? $failed : false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doFetch(array $ids)
+ {
+ try {
+ $encodedIds = array_map([__CLASS__, 'encodeKey'], $ids);
+
+ $encodedResult = $this->checkResultCode($this->getClient()->getMulti($encodedIds));
+
+ $result = [];
+ foreach ($encodedResult as $key => $value) {
+ $result[self::decodeKey($key)] = $this->marshaller->unmarshall($value);
+ }
+
+ return $result;
+ } catch (\Error $e) {
+ throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine());
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doHave(string $id)
+ {
+ return false !== $this->getClient()->get(self::encodeKey($id)) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDelete(array $ids)
+ {
+ $ok = true;
+ $encodedIds = array_map([__CLASS__, 'encodeKey'], $ids);
+ foreach ($this->checkResultCode($this->getClient()->deleteMulti($encodedIds)) as $result) {
+ if (\Memcached::RES_SUCCESS !== $result && \Memcached::RES_NOTFOUND !== $result) {
+ $ok = false;
+ }
+ }
+
+ return $ok;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doClear(string $namespace)
+ {
+ return '' === $namespace && $this->getClient()->flush();
+ }
+
+ private function checkResultCode($result)
+ {
+ $code = $this->client->getResultCode();
+
+ if (\Memcached::RES_SUCCESS === $code || \Memcached::RES_NOTFOUND === $code) {
+ return $result;
+ }
+
+ throw new CacheException('MemcachedAdapter client error: '.strtolower($this->client->getResultMessage()));
+ }
+
+ private function getClient(): \Memcached
+ {
+ if ($this->client) {
+ return $this->client;
+ }
+
+ $opt = $this->lazyClient->getOption(\Memcached::OPT_SERIALIZER);
+ if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) {
+ throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".');
+ }
+ if ('' !== $prefix = (string) $this->lazyClient->getOption(\Memcached::OPT_PREFIX_KEY)) {
+ throw new CacheException(sprintf('MemcachedAdapter: "prefix_key" option must be empty when using proxified connections, "%s" given.', $prefix));
+ }
+
+ return $this->client = $this->lazyClient;
+ }
+
+ private static function encodeKey(string $key): string
+ {
+ return strtr($key, self::RESERVED_MEMCACHED, self::RESERVED_PSR6);
+ }
+
+ private static function decodeKey(string $key): string
+ {
+ return strtr($key, self::RESERVED_PSR6, self::RESERVED_MEMCACHED);
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/NullAdapter.php b/vendor/symfony/cache/Adapter/NullAdapter.php
new file mode 100644
index 0000000..15f7f8c
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/NullAdapter.php
@@ -0,0 +1,152 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Psr\Cache\CacheItemInterface;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Contracts\Cache\CacheInterface;
+
+/**
+ * @author Titouan Galopin
+ */
+class NullAdapter implements AdapterInterface, CacheInterface
+{
+ private static $createCacheItem;
+
+ public function __construct()
+ {
+ self::$createCacheItem ?? self::$createCacheItem = \Closure::bind(
+ static function ($key) {
+ $item = new CacheItem();
+ $item->key = $key;
+ $item->isHit = false;
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ $save = true;
+
+ return $callback((self::$createCacheItem)($key), $save);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItem($key)
+ {
+ return (self::$createCacheItem)($key);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItems(array $keys = [])
+ {
+ return $this->generateItems($keys);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function hasItem($key)
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function clear(string $prefix = '')
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItem($key)
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItems(array $keys)
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function save(CacheItemInterface $item)
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function saveDeferred(CacheItemInterface $item)
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function commit()
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete(string $key): bool
+ {
+ return $this->deleteItem($key);
+ }
+
+ private function generateItems(array $keys): \Generator
+ {
+ $f = self::$createCacheItem;
+
+ foreach ($keys as $key) {
+ yield $key => $f($key);
+ }
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/ParameterNormalizer.php b/vendor/symfony/cache/Adapter/ParameterNormalizer.php
new file mode 100644
index 0000000..e33ae9f
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/ParameterNormalizer.php
@@ -0,0 +1,35 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+/**
+ * @author Lars Strojny
+ */
+final class ParameterNormalizer
+{
+ public static function normalizeDuration(string $duration): int
+ {
+ if (is_numeric($duration)) {
+ return $duration;
+ }
+
+ if (false !== $time = strtotime($duration, 0)) {
+ return $time;
+ }
+
+ try {
+ return \DateTime::createFromFormat('U', 0)->add(new \DateInterval($duration))->getTimestamp();
+ } catch (\Exception $e) {
+ throw new \InvalidArgumentException(sprintf('Cannot parse date interval "%s".', $duration), 0, $e);
+ }
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/PdoAdapter.php b/vendor/symfony/cache/Adapter/PdoAdapter.php
new file mode 100644
index 0000000..5d10724
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/PdoAdapter.php
@@ -0,0 +1,583 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Doctrine\DBAL\Connection;
+use Doctrine\DBAL\Schema\Schema;
+use Psr\Cache\CacheItemInterface;
+use Psr\Log\LoggerInterface;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\Marshaller\DefaultMarshaller;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+use Symfony\Component\Cache\PruneableInterface;
+
+class PdoAdapter extends AbstractAdapter implements PruneableInterface
+{
+ protected $maxIdLength = 255;
+
+ private $marshaller;
+ private $conn;
+ private $dsn;
+ private $driver;
+ private $serverVersion;
+ private $table = 'cache_items';
+ private $idCol = 'item_id';
+ private $dataCol = 'item_data';
+ private $lifetimeCol = 'item_lifetime';
+ private $timeCol = 'item_time';
+ private $username = '';
+ private $password = '';
+ private $connectionOptions = [];
+ private $namespace;
+
+ private $dbalAdapter;
+
+ /**
+ * You can either pass an existing database connection as PDO instance or
+ * a DSN string that will be used to lazy-connect to the database when the
+ * cache is actually used.
+ *
+ * List of available options:
+ * * db_table: The name of the table [default: cache_items]
+ * * db_id_col: The column where to store the cache id [default: item_id]
+ * * db_data_col: The column where to store the cache data [default: item_data]
+ * * db_lifetime_col: The column where to store the lifetime [default: item_lifetime]
+ * * db_time_col: The column where to store the timestamp [default: item_time]
+ * * db_username: The username when lazy-connect [default: '']
+ * * db_password: The password when lazy-connect [default: '']
+ * * db_connection_options: An array of driver-specific connection options [default: []]
+ *
+ * @param \PDO|string $connOrDsn
+ *
+ * @throws InvalidArgumentException When first argument is not PDO nor Connection nor string
+ * @throws InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION
+ * @throws InvalidArgumentException When namespace contains invalid characters
+ */
+ public function __construct($connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], MarshallerInterface $marshaller = null)
+ {
+ if ($connOrDsn instanceof Connection || (\is_string($connOrDsn) && str_contains($connOrDsn, '://'))) {
+ trigger_deprecation('symfony/cache', '5.4', 'Usage of a DBAL Connection with "%s" is deprecated and will be removed in symfony 6.0. Use "%s" instead.', __CLASS__, DoctrineDbalAdapter::class);
+ $this->dbalAdapter = new DoctrineDbalAdapter($connOrDsn, $namespace, $defaultLifetime, $options, $marshaller);
+
+ return;
+ }
+
+ if (isset($namespace[0]) && preg_match('#[^-+.A-Za-z0-9]#', $namespace, $match)) {
+ throw new InvalidArgumentException(sprintf('Namespace contains "%s" but only characters in [-+.A-Za-z0-9] are allowed.', $match[0]));
+ }
+
+ if ($connOrDsn instanceof \PDO) {
+ if (\PDO::ERRMODE_EXCEPTION !== $connOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) {
+ throw new InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)).', __CLASS__));
+ }
+
+ $this->conn = $connOrDsn;
+ } elseif (\is_string($connOrDsn)) {
+ $this->dsn = $connOrDsn;
+ } else {
+ throw new InvalidArgumentException(sprintf('"%s" requires PDO or Doctrine\DBAL\Connection instance or DSN string as first argument, "%s" given.', __CLASS__, get_debug_type($connOrDsn)));
+ }
+
+ $this->table = $options['db_table'] ?? $this->table;
+ $this->idCol = $options['db_id_col'] ?? $this->idCol;
+ $this->dataCol = $options['db_data_col'] ?? $this->dataCol;
+ $this->lifetimeCol = $options['db_lifetime_col'] ?? $this->lifetimeCol;
+ $this->timeCol = $options['db_time_col'] ?? $this->timeCol;
+ $this->username = $options['db_username'] ?? $this->username;
+ $this->password = $options['db_password'] ?? $this->password;
+ $this->connectionOptions = $options['db_connection_options'] ?? $this->connectionOptions;
+ $this->namespace = $namespace;
+ $this->marshaller = $marshaller ?? new DefaultMarshaller();
+
+ parent::__construct($namespace, $defaultLifetime);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getItem($key)
+ {
+ if (isset($this->dbalAdapter)) {
+ return $this->dbalAdapter->getItem($key);
+ }
+
+ return parent::getItem($key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getItems(array $keys = [])
+ {
+ if (isset($this->dbalAdapter)) {
+ return $this->dbalAdapter->getItems($keys);
+ }
+
+ return parent::getItems($keys);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function hasItem($key)
+ {
+ if (isset($this->dbalAdapter)) {
+ return $this->dbalAdapter->hasItem($key);
+ }
+
+ return parent::hasItem($key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function deleteItem($key)
+ {
+ if (isset($this->dbalAdapter)) {
+ return $this->dbalAdapter->deleteItem($key);
+ }
+
+ return parent::deleteItem($key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function deleteItems(array $keys)
+ {
+ if (isset($this->dbalAdapter)) {
+ return $this->dbalAdapter->deleteItems($keys);
+ }
+
+ return parent::deleteItems($keys);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function clear(string $prefix = '')
+ {
+ if (isset($this->dbalAdapter)) {
+ return $this->dbalAdapter->clear($prefix);
+ }
+
+ return parent::clear($prefix);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ if (isset($this->dbalAdapter)) {
+ return $this->dbalAdapter->get($key, $callback, $beta, $metadata);
+ }
+
+ return parent::get($key, $callback, $beta, $metadata);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function delete(string $key): bool
+ {
+ if (isset($this->dbalAdapter)) {
+ return $this->dbalAdapter->delete($key);
+ }
+
+ return parent::delete($key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function save(CacheItemInterface $item)
+ {
+ if (isset($this->dbalAdapter)) {
+ return $this->dbalAdapter->save($item);
+ }
+
+ return parent::save($item);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function saveDeferred(CacheItemInterface $item)
+ {
+ if (isset($this->dbalAdapter)) {
+ return $this->dbalAdapter->saveDeferred($item);
+ }
+
+ return parent::saveDeferred($item);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function setLogger(LoggerInterface $logger): void
+ {
+ if (isset($this->dbalAdapter)) {
+ $this->dbalAdapter->setLogger($logger);
+
+ return;
+ }
+
+ parent::setLogger($logger);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function commit()
+ {
+ if (isset($this->dbalAdapter)) {
+ return $this->dbalAdapter->commit();
+ }
+
+ return parent::commit();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function reset()
+ {
+ if (isset($this->dbalAdapter)) {
+ $this->dbalAdapter->reset();
+
+ return;
+ }
+
+ parent::reset();
+ }
+
+ /**
+ * Creates the table to store cache items which can be called once for setup.
+ *
+ * Cache ID are saved in a column of maximum length 255. Cache data is
+ * saved in a BLOB.
+ *
+ * @throws \PDOException When the table already exists
+ * @throws \DomainException When an unsupported PDO driver is used
+ */
+ public function createTable()
+ {
+ if (isset($this->dbalAdapter)) {
+ $this->dbalAdapter->createTable();
+
+ return;
+ }
+
+ // connect if we are not yet
+ $conn = $this->getConnection();
+
+ switch ($this->driver) {
+ case 'mysql':
+ // We use varbinary for the ID column because it prevents unwanted conversions:
+ // - character set conversions between server and client
+ // - trailing space removal
+ // - case-insensitivity
+ // - language processing like é == e
+ $sql = "CREATE TABLE $this->table ($this->idCol VARBINARY(255) NOT NULL PRIMARY KEY, $this->dataCol MEDIUMBLOB NOT NULL, $this->lifetimeCol INTEGER UNSIGNED, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8mb4_bin, ENGINE = InnoDB";
+ break;
+ case 'sqlite':
+ $sql = "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)";
+ break;
+ case 'pgsql':
+ $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(255) NOT NULL PRIMARY KEY, $this->dataCol BYTEA NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)";
+ break;
+ case 'oci':
+ $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR2(255) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)";
+ break;
+ case 'sqlsrv':
+ $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(255) NOT NULL PRIMARY KEY, $this->dataCol VARBINARY(MAX) NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)";
+ break;
+ default:
+ throw new \DomainException(sprintf('Creating the cache table is currently not implemented for PDO driver "%s".', $this->driver));
+ }
+
+ $conn->exec($sql);
+ }
+
+ /**
+ * Adds the Table to the Schema if the adapter uses this Connection.
+ *
+ * @deprecated since symfony/cache 5.4 use DoctrineDbalAdapter instead
+ */
+ public function configureSchema(Schema $schema, Connection $forConnection): void
+ {
+ if (isset($this->dbalAdapter)) {
+ $this->dbalAdapter->configureSchema($schema, $forConnection);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function prune()
+ {
+ if (isset($this->dbalAdapter)) {
+ return $this->dbalAdapter->prune();
+ }
+
+ $deleteSql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= :time";
+
+ if ('' !== $this->namespace) {
+ $deleteSql .= " AND $this->idCol LIKE :namespace";
+ }
+
+ $connection = $this->getConnection();
+
+ try {
+ $delete = $connection->prepare($deleteSql);
+ } catch (\PDOException $e) {
+ return true;
+ }
+ $delete->bindValue(':time', time(), \PDO::PARAM_INT);
+
+ if ('' !== $this->namespace) {
+ $delete->bindValue(':namespace', sprintf('%s%%', $this->namespace), \PDO::PARAM_STR);
+ }
+ try {
+ return $delete->execute();
+ } catch (\PDOException $e) {
+ return true;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doFetch(array $ids)
+ {
+ $connection = $this->getConnection();
+
+ $now = time();
+ $expired = [];
+
+ $sql = str_pad('', (\count($ids) << 1) - 1, '?,');
+ $sql = "SELECT $this->idCol, CASE WHEN $this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > ? THEN $this->dataCol ELSE NULL END FROM $this->table WHERE $this->idCol IN ($sql)";
+ $stmt = $connection->prepare($sql);
+ $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT);
+ foreach ($ids as $id) {
+ $stmt->bindValue(++$i, $id);
+ }
+ $result = $stmt->execute();
+
+ if (\is_object($result)) {
+ $result = $result->iterateNumeric();
+ } else {
+ $stmt->setFetchMode(\PDO::FETCH_NUM);
+ $result = $stmt;
+ }
+
+ foreach ($result as $row) {
+ if (null === $row[1]) {
+ $expired[] = $row[0];
+ } else {
+ yield $row[0] => $this->marshaller->unmarshall(\is_resource($row[1]) ? stream_get_contents($row[1]) : $row[1]);
+ }
+ }
+
+ if ($expired) {
+ $sql = str_pad('', (\count($expired) << 1) - 1, '?,');
+ $sql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= ? AND $this->idCol IN ($sql)";
+ $stmt = $connection->prepare($sql);
+ $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT);
+ foreach ($expired as $id) {
+ $stmt->bindValue(++$i, $id);
+ }
+ $stmt->execute();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doHave(string $id)
+ {
+ $connection = $this->getConnection();
+
+ $sql = "SELECT 1 FROM $this->table WHERE $this->idCol = :id AND ($this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > :time)";
+ $stmt = $connection->prepare($sql);
+
+ $stmt->bindValue(':id', $id);
+ $stmt->bindValue(':time', time(), \PDO::PARAM_INT);
+ $stmt->execute();
+
+ return (bool) $stmt->fetchColumn();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doClear(string $namespace)
+ {
+ $conn = $this->getConnection();
+
+ if ('' === $namespace) {
+ if ('sqlite' === $this->driver) {
+ $sql = "DELETE FROM $this->table";
+ } else {
+ $sql = "TRUNCATE TABLE $this->table";
+ }
+ } else {
+ $sql = "DELETE FROM $this->table WHERE $this->idCol LIKE '$namespace%'";
+ }
+
+ try {
+ $conn->exec($sql);
+ } catch (\PDOException $e) {
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDelete(array $ids)
+ {
+ $sql = str_pad('', (\count($ids) << 1) - 1, '?,');
+ $sql = "DELETE FROM $this->table WHERE $this->idCol IN ($sql)";
+ try {
+ $stmt = $this->getConnection()->prepare($sql);
+ $stmt->execute(array_values($ids));
+ } catch (\PDOException $e) {
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, int $lifetime)
+ {
+ if (!$values = $this->marshaller->marshall($values, $failed)) {
+ return $failed;
+ }
+
+ $conn = $this->getConnection();
+
+ $driver = $this->driver;
+ $insertSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time)";
+
+ switch (true) {
+ case 'mysql' === $driver:
+ $sql = $insertSql." ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->lifetimeCol = VALUES($this->lifetimeCol), $this->timeCol = VALUES($this->timeCol)";
+ break;
+ case 'oci' === $driver:
+ // DUAL is Oracle specific dummy table
+ $sql = "MERGE INTO $this->table USING DUAL ON ($this->idCol = ?) ".
+ "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ".
+ "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?";
+ break;
+ case 'sqlsrv' === $driver && version_compare($this->getServerVersion(), '10', '>='):
+ // MERGE is only available since SQL Server 2008 and must be terminated by semicolon
+ // It also requires HOLDLOCK according to http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx
+ $sql = "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = ?) ".
+ "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ".
+ "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?;";
+ break;
+ case 'sqlite' === $driver:
+ $sql = 'INSERT OR REPLACE'.substr($insertSql, 6);
+ break;
+ case 'pgsql' === $driver && version_compare($this->getServerVersion(), '9.5', '>='):
+ $sql = $insertSql." ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)";
+ break;
+ default:
+ $driver = null;
+ $sql = "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :lifetime, $this->timeCol = :time WHERE $this->idCol = :id";
+ break;
+ }
+
+ $now = time();
+ $lifetime = $lifetime ?: null;
+ try {
+ $stmt = $conn->prepare($sql);
+ } catch (\PDOException $e) {
+ if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) {
+ $this->createTable();
+ }
+ $stmt = $conn->prepare($sql);
+ }
+
+ // $id and $data are defined later in the loop. Binding is done by reference, values are read on execution.
+ if ('sqlsrv' === $driver || 'oci' === $driver) {
+ $stmt->bindParam(1, $id);
+ $stmt->bindParam(2, $id);
+ $stmt->bindParam(3, $data, \PDO::PARAM_LOB);
+ $stmt->bindValue(4, $lifetime, \PDO::PARAM_INT);
+ $stmt->bindValue(5, $now, \PDO::PARAM_INT);
+ $stmt->bindParam(6, $data, \PDO::PARAM_LOB);
+ $stmt->bindValue(7, $lifetime, \PDO::PARAM_INT);
+ $stmt->bindValue(8, $now, \PDO::PARAM_INT);
+ } else {
+ $stmt->bindParam(':id', $id);
+ $stmt->bindParam(':data', $data, \PDO::PARAM_LOB);
+ $stmt->bindValue(':lifetime', $lifetime, \PDO::PARAM_INT);
+ $stmt->bindValue(':time', $now, \PDO::PARAM_INT);
+ }
+ if (null === $driver) {
+ $insertStmt = $conn->prepare($insertSql);
+
+ $insertStmt->bindParam(':id', $id);
+ $insertStmt->bindParam(':data', $data, \PDO::PARAM_LOB);
+ $insertStmt->bindValue(':lifetime', $lifetime, \PDO::PARAM_INT);
+ $insertStmt->bindValue(':time', $now, \PDO::PARAM_INT);
+ }
+
+ foreach ($values as $id => $data) {
+ try {
+ $stmt->execute();
+ } catch (\PDOException $e) {
+ if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) {
+ $this->createTable();
+ }
+ $stmt->execute();
+ }
+ if (null === $driver && !$stmt->rowCount()) {
+ try {
+ $insertStmt->execute();
+ } catch (\PDOException $e) {
+ // A concurrent write won, let it be
+ }
+ }
+ }
+
+ return $failed;
+ }
+
+ private function getConnection(): \PDO
+ {
+ if (null === $this->conn) {
+ $this->conn = new \PDO($this->dsn, $this->username, $this->password, $this->connectionOptions);
+ $this->conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
+ }
+ if (null === $this->driver) {
+ $this->driver = $this->conn->getAttribute(\PDO::ATTR_DRIVER_NAME);
+ }
+
+ return $this->conn;
+ }
+
+ private function getServerVersion(): string
+ {
+ if (null === $this->serverVersion) {
+ $this->serverVersion = $this->conn->getAttribute(\PDO::ATTR_SERVER_VERSION);
+ }
+
+ return $this->serverVersion;
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/PhpArrayAdapter.php b/vendor/symfony/cache/Adapter/PhpArrayAdapter.php
new file mode 100644
index 0000000..8c8fb91
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/PhpArrayAdapter.php
@@ -0,0 +1,435 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Psr\Cache\CacheItemInterface;
+use Psr\Cache\CacheItemPoolInterface;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Component\Cache\Traits\ContractsTrait;
+use Symfony\Component\Cache\Traits\ProxyTrait;
+use Symfony\Component\VarExporter\VarExporter;
+use Symfony\Contracts\Cache\CacheInterface;
+
+/**
+ * Caches items at warm up time using a PHP array that is stored in shared memory by OPCache since PHP 7.0.
+ * Warmed up items are read-only and run-time discovered items are cached using a fallback adapter.
+ *
+ * @author Titouan Galopin
+ * @author Nicolas Grekas
+ */
+class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface
+{
+ use ContractsTrait;
+ use ProxyTrait;
+
+ private $file;
+ private $keys;
+ private $values;
+
+ private static $createCacheItem;
+ private static $valuesCache = [];
+
+ /**
+ * @param string $file The PHP file were values are cached
+ * @param AdapterInterface $fallbackPool A pool to fallback on when an item is not hit
+ */
+ public function __construct(string $file, AdapterInterface $fallbackPool)
+ {
+ $this->file = $file;
+ $this->pool = $fallbackPool;
+ self::$createCacheItem ?? self::$createCacheItem = \Closure::bind(
+ static function ($key, $value, $isHit) {
+ $item = new CacheItem();
+ $item->key = $key;
+ $item->value = $value;
+ $item->isHit = $isHit;
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ }
+
+ /**
+ * This adapter takes advantage of how PHP stores arrays in its latest versions.
+ *
+ * @param string $file The PHP file were values are cached
+ * @param CacheItemPoolInterface $fallbackPool A pool to fallback on when an item is not hit
+ *
+ * @return CacheItemPoolInterface
+ */
+ public static function create(string $file, CacheItemPoolInterface $fallbackPool)
+ {
+ if (!$fallbackPool instanceof AdapterInterface) {
+ $fallbackPool = new ProxyAdapter($fallbackPool);
+ }
+
+ return new static($file, $fallbackPool);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ if (null === $this->values) {
+ $this->initialize();
+ }
+ if (!isset($this->keys[$key])) {
+ get_from_pool:
+ if ($this->pool instanceof CacheInterface) {
+ return $this->pool->get($key, $callback, $beta, $metadata);
+ }
+
+ return $this->doGet($this->pool, $key, $callback, $beta, $metadata);
+ }
+ $value = $this->values[$this->keys[$key]];
+
+ if ('N;' === $value) {
+ return null;
+ }
+ try {
+ if ($value instanceof \Closure) {
+ return $value();
+ }
+ } catch (\Throwable $e) {
+ unset($this->keys[$key]);
+ goto get_from_pool;
+ }
+
+ return $value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItem($key)
+ {
+ if (!\is_string($key)) {
+ throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', get_debug_type($key)));
+ }
+ if (null === $this->values) {
+ $this->initialize();
+ }
+ if (!isset($this->keys[$key])) {
+ return $this->pool->getItem($key);
+ }
+
+ $value = $this->values[$this->keys[$key]];
+ $isHit = true;
+
+ if ('N;' === $value) {
+ $value = null;
+ } elseif ($value instanceof \Closure) {
+ try {
+ $value = $value();
+ } catch (\Throwable $e) {
+ $value = null;
+ $isHit = false;
+ }
+ }
+
+ return (self::$createCacheItem)($key, $value, $isHit);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItems(array $keys = [])
+ {
+ foreach ($keys as $key) {
+ if (!\is_string($key)) {
+ throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', get_debug_type($key)));
+ }
+ }
+ if (null === $this->values) {
+ $this->initialize();
+ }
+
+ return $this->generateItems($keys);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function hasItem($key)
+ {
+ if (!\is_string($key)) {
+ throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', get_debug_type($key)));
+ }
+ if (null === $this->values) {
+ $this->initialize();
+ }
+
+ return isset($this->keys[$key]) || $this->pool->hasItem($key);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItem($key)
+ {
+ if (!\is_string($key)) {
+ throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', get_debug_type($key)));
+ }
+ if (null === $this->values) {
+ $this->initialize();
+ }
+
+ return !isset($this->keys[$key]) && $this->pool->deleteItem($key);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItems(array $keys)
+ {
+ $deleted = true;
+ $fallbackKeys = [];
+
+ foreach ($keys as $key) {
+ if (!\is_string($key)) {
+ throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', get_debug_type($key)));
+ }
+
+ if (isset($this->keys[$key])) {
+ $deleted = false;
+ } else {
+ $fallbackKeys[] = $key;
+ }
+ }
+ if (null === $this->values) {
+ $this->initialize();
+ }
+
+ if ($fallbackKeys) {
+ $deleted = $this->pool->deleteItems($fallbackKeys) && $deleted;
+ }
+
+ return $deleted;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function save(CacheItemInterface $item)
+ {
+ if (null === $this->values) {
+ $this->initialize();
+ }
+
+ return !isset($this->keys[$item->getKey()]) && $this->pool->save($item);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function saveDeferred(CacheItemInterface $item)
+ {
+ if (null === $this->values) {
+ $this->initialize();
+ }
+
+ return !isset($this->keys[$item->getKey()]) && $this->pool->saveDeferred($item);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function commit()
+ {
+ return $this->pool->commit();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function clear(string $prefix = '')
+ {
+ $this->keys = $this->values = [];
+
+ $cleared = @unlink($this->file) || !file_exists($this->file);
+ unset(self::$valuesCache[$this->file]);
+
+ if ($this->pool instanceof AdapterInterface) {
+ return $this->pool->clear($prefix) && $cleared;
+ }
+
+ return $this->pool->clear() && $cleared;
+ }
+
+ /**
+ * Store an array of cached values.
+ *
+ * @param array $values The cached values
+ *
+ * @return string[] A list of classes to preload on PHP 7.4+
+ */
+ public function warmUp(array $values)
+ {
+ if (file_exists($this->file)) {
+ if (!is_file($this->file)) {
+ throw new InvalidArgumentException(sprintf('Cache path exists and is not a file: "%s".', $this->file));
+ }
+
+ if (!is_writable($this->file)) {
+ throw new InvalidArgumentException(sprintf('Cache file is not writable: "%s".', $this->file));
+ }
+ } else {
+ $directory = \dirname($this->file);
+
+ if (!is_dir($directory) && !@mkdir($directory, 0777, true)) {
+ throw new InvalidArgumentException(sprintf('Cache directory does not exist and cannot be created: "%s".', $directory));
+ }
+
+ if (!is_writable($directory)) {
+ throw new InvalidArgumentException(sprintf('Cache directory is not writable: "%s".', $directory));
+ }
+ }
+
+ $preload = [];
+ $dumpedValues = '';
+ $dumpedMap = [];
+ $dump = <<<'EOF'
+ $value) {
+ CacheItem::validateKey(\is_int($key) ? (string) $key : $key);
+ $isStaticValue = true;
+
+ if (null === $value) {
+ $value = "'N;'";
+ } elseif (\is_object($value) || \is_array($value)) {
+ try {
+ $value = VarExporter::export($value, $isStaticValue, $preload);
+ } catch (\Exception $e) {
+ throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable "%s" value.', $key, get_debug_type($value)), 0, $e);
+ }
+ } elseif (\is_string($value)) {
+ // Wrap "N;" in a closure to not confuse it with an encoded `null`
+ if ('N;' === $value) {
+ $isStaticValue = false;
+ }
+ $value = var_export($value, true);
+ } elseif (!\is_scalar($value)) {
+ throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable "%s" value.', $key, get_debug_type($value)));
+ } else {
+ $value = var_export($value, true);
+ }
+
+ if (!$isStaticValue) {
+ $value = str_replace("\n", "\n ", $value);
+ $value = "static function () {\n return {$value};\n}";
+ }
+ $hash = hash('md5', $value);
+
+ if (null === $id = $dumpedMap[$hash] ?? null) {
+ $id = $dumpedMap[$hash] = \count($dumpedMap);
+ $dumpedValues .= "{$id} => {$value},\n";
+ }
+
+ $dump .= var_export($key, true)." => {$id},\n";
+ }
+
+ $dump .= "\n], [\n\n{$dumpedValues}\n]];\n";
+
+ $tmpFile = uniqid($this->file, true);
+
+ file_put_contents($tmpFile, $dump);
+ @chmod($tmpFile, 0666 & ~umask());
+ unset($serialized, $value, $dump);
+
+ @rename($tmpFile, $this->file);
+ unset(self::$valuesCache[$this->file]);
+
+ $this->initialize();
+
+ return $preload;
+ }
+
+ /**
+ * Load the cache file.
+ */
+ private function initialize()
+ {
+ if (isset(self::$valuesCache[$this->file])) {
+ $values = self::$valuesCache[$this->file];
+ } elseif (!is_file($this->file)) {
+ $this->keys = $this->values = [];
+
+ return;
+ } else {
+ $values = self::$valuesCache[$this->file] = (include $this->file) ?: [[], []];
+ }
+
+ if (2 !== \count($values) || !isset($values[0], $values[1])) {
+ $this->keys = $this->values = [];
+ } else {
+ [$this->keys, $this->values] = $values;
+ }
+ }
+
+ private function generateItems(array $keys): \Generator
+ {
+ $f = self::$createCacheItem;
+ $fallbackKeys = [];
+
+ foreach ($keys as $key) {
+ if (isset($this->keys[$key])) {
+ $value = $this->values[$this->keys[$key]];
+
+ if ('N;' === $value) {
+ yield $key => $f($key, null, true);
+ } elseif ($value instanceof \Closure) {
+ try {
+ yield $key => $f($key, $value(), true);
+ } catch (\Throwable $e) {
+ yield $key => $f($key, null, false);
+ }
+ } else {
+ yield $key => $f($key, $value, true);
+ }
+ } else {
+ $fallbackKeys[] = $key;
+ }
+ }
+
+ if ($fallbackKeys) {
+ yield from $this->pool->getItems($fallbackKeys);
+ }
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/PhpFilesAdapter.php b/vendor/symfony/cache/Adapter/PhpFilesAdapter.php
new file mode 100644
index 0000000..2fb0837
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/PhpFilesAdapter.php
@@ -0,0 +1,330 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Symfony\Component\Cache\Exception\CacheException;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\Traits\FilesystemCommonTrait;
+use Symfony\Component\VarExporter\VarExporter;
+
+/**
+ * @author Piotr Stankowski
+ * @author Nicolas Grekas
+ * @author Rob Frawley 2nd
+ */
+class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface
+{
+ use FilesystemCommonTrait {
+ doClear as private doCommonClear;
+ doDelete as private doCommonDelete;
+ }
+
+ private $includeHandler;
+ private $appendOnly;
+ private $values = [];
+ private $files = [];
+
+ private static $startTime;
+ private static $valuesCache = [];
+
+ /**
+ * @param $appendOnly Set to `true` to gain extra performance when the items stored in this pool never expire.
+ * Doing so is encouraged because it fits perfectly OPcache's memory model.
+ *
+ * @throws CacheException if OPcache is not enabled
+ */
+ public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, bool $appendOnly = false)
+ {
+ $this->appendOnly = $appendOnly;
+ self::$startTime = self::$startTime ?? $_SERVER['REQUEST_TIME'] ?? time();
+ parent::__construct('', $defaultLifetime);
+ $this->init($namespace, $directory);
+ $this->includeHandler = static function ($type, $msg, $file, $line) {
+ throw new \ErrorException($msg, 0, $type, $file, $line);
+ };
+ }
+
+ public static function isSupported()
+ {
+ self::$startTime = self::$startTime ?? $_SERVER['REQUEST_TIME'] ?? time();
+
+ return \function_exists('opcache_invalidate') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(\ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN));
+ }
+
+ /**
+ * @return bool
+ */
+ public function prune()
+ {
+ $time = time();
+ $pruned = true;
+ $getExpiry = true;
+
+ set_error_handler($this->includeHandler);
+ try {
+ foreach ($this->scanHashDir($this->directory) as $file) {
+ try {
+ if (\is_array($expiresAt = include $file)) {
+ $expiresAt = $expiresAt[0];
+ }
+ } catch (\ErrorException $e) {
+ $expiresAt = $time;
+ }
+
+ if ($time >= $expiresAt) {
+ $pruned = $this->doUnlink($file) && !file_exists($file) && $pruned;
+ }
+ }
+ } finally {
+ restore_error_handler();
+ }
+
+ return $pruned;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doFetch(array $ids)
+ {
+ if ($this->appendOnly) {
+ $now = 0;
+ $missingIds = [];
+ } else {
+ $now = time();
+ $missingIds = $ids;
+ $ids = [];
+ }
+ $values = [];
+
+ begin:
+ $getExpiry = false;
+
+ foreach ($ids as $id) {
+ if (null === $value = $this->values[$id] ?? null) {
+ $missingIds[] = $id;
+ } elseif ('N;' === $value) {
+ $values[$id] = null;
+ } elseif (!\is_object($value)) {
+ $values[$id] = $value;
+ } elseif (!$value instanceof LazyValue) {
+ $values[$id] = $value();
+ } elseif (false === $values[$id] = include $value->file) {
+ unset($values[$id], $this->values[$id]);
+ $missingIds[] = $id;
+ }
+ if (!$this->appendOnly) {
+ unset($this->values[$id]);
+ }
+ }
+
+ if (!$missingIds) {
+ return $values;
+ }
+
+ set_error_handler($this->includeHandler);
+ try {
+ $getExpiry = true;
+
+ foreach ($missingIds as $k => $id) {
+ try {
+ $file = $this->files[$id] ?? $this->files[$id] = $this->getFile($id);
+
+ if (isset(self::$valuesCache[$file])) {
+ [$expiresAt, $this->values[$id]] = self::$valuesCache[$file];
+ } elseif (\is_array($expiresAt = include $file)) {
+ if ($this->appendOnly) {
+ self::$valuesCache[$file] = $expiresAt;
+ }
+
+ [$expiresAt, $this->values[$id]] = $expiresAt;
+ } elseif ($now < $expiresAt) {
+ $this->values[$id] = new LazyValue($file);
+ }
+
+ if ($now >= $expiresAt) {
+ unset($this->values[$id], $missingIds[$k], self::$valuesCache[$file]);
+ }
+ } catch (\ErrorException $e) {
+ unset($missingIds[$k]);
+ }
+ }
+ } finally {
+ restore_error_handler();
+ }
+
+ $ids = $missingIds;
+ $missingIds = [];
+ goto begin;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doHave(string $id)
+ {
+ if ($this->appendOnly && isset($this->values[$id])) {
+ return true;
+ }
+
+ set_error_handler($this->includeHandler);
+ try {
+ $file = $this->files[$id] ?? $this->files[$id] = $this->getFile($id);
+ $getExpiry = true;
+
+ if (isset(self::$valuesCache[$file])) {
+ [$expiresAt, $value] = self::$valuesCache[$file];
+ } elseif (\is_array($expiresAt = include $file)) {
+ if ($this->appendOnly) {
+ self::$valuesCache[$file] = $expiresAt;
+ }
+
+ [$expiresAt, $value] = $expiresAt;
+ } elseif ($this->appendOnly) {
+ $value = new LazyValue($file);
+ }
+ } catch (\ErrorException $e) {
+ return false;
+ } finally {
+ restore_error_handler();
+ }
+ if ($this->appendOnly) {
+ $now = 0;
+ $this->values[$id] = $value;
+ } else {
+ $now = time();
+ }
+
+ return $now < $expiresAt;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, int $lifetime)
+ {
+ $ok = true;
+ $expiry = $lifetime ? time() + $lifetime : 'PHP_INT_MAX';
+ $allowCompile = self::isSupported();
+
+ foreach ($values as $key => $value) {
+ unset($this->values[$key]);
+ $isStaticValue = true;
+ if (null === $value) {
+ $value = "'N;'";
+ } elseif (\is_object($value) || \is_array($value)) {
+ try {
+ $value = VarExporter::export($value, $isStaticValue);
+ } catch (\Exception $e) {
+ throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable "%s" value.', $key, get_debug_type($value)), 0, $e);
+ }
+ } elseif (\is_string($value)) {
+ // Wrap "N;" in a closure to not confuse it with an encoded `null`
+ if ('N;' === $value) {
+ $isStaticValue = false;
+ }
+ $value = var_export($value, true);
+ } elseif (!\is_scalar($value)) {
+ throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable "%s" value.', $key, get_debug_type($value)));
+ } else {
+ $value = var_export($value, true);
+ }
+
+ $encodedKey = rawurlencode($key);
+
+ if ($isStaticValue) {
+ $value = "return [{$expiry}, {$value}];";
+ } elseif ($this->appendOnly) {
+ $value = "return [{$expiry}, static function () { return {$value}; }];";
+ } else {
+ // We cannot use a closure here because of https://bugs.php.net/76982
+ $value = str_replace('\Symfony\Component\VarExporter\Internal\\', '', $value);
+ $value = "namespace Symfony\Component\VarExporter\Internal;\n\nreturn \$getExpiry ? {$expiry} : {$value};";
+ }
+
+ $file = $this->files[$key] = $this->getFile($key, true);
+ // Since OPcache only compiles files older than the script execution start, set the file's mtime in the past
+ $ok = $this->write($file, "directory)) {
+ throw new CacheException(sprintf('Cache directory is not writable (%s).', $this->directory));
+ }
+
+ return $ok;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doClear(string $namespace)
+ {
+ $this->values = [];
+
+ return $this->doCommonClear($namespace);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDelete(array $ids)
+ {
+ foreach ($ids as $id) {
+ unset($this->values[$id]);
+ }
+
+ return $this->doCommonDelete($ids);
+ }
+
+ protected function doUnlink(string $file)
+ {
+ unset(self::$valuesCache[$file]);
+
+ if (self::isSupported()) {
+ @opcache_invalidate($file, true);
+ }
+
+ return @unlink($file);
+ }
+
+ private function getFileKey(string $file): string
+ {
+ if (!$h = @fopen($file, 'r')) {
+ return '';
+ }
+
+ $encodedKey = substr(fgets($h), 8);
+ fclose($h);
+
+ return rawurldecode(rtrim($encodedKey));
+ }
+}
+
+/**
+ * @internal
+ */
+class LazyValue
+{
+ public $file;
+
+ public function __construct(string $file)
+ {
+ $this->file = $file;
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/ProxyAdapter.php b/vendor/symfony/cache/Adapter/ProxyAdapter.php
new file mode 100644
index 0000000..c715cad
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/ProxyAdapter.php
@@ -0,0 +1,268 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Psr\Cache\CacheItemInterface;
+use Psr\Cache\CacheItemPoolInterface;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Component\Cache\Traits\ContractsTrait;
+use Symfony\Component\Cache\Traits\ProxyTrait;
+use Symfony\Contracts\Cache\CacheInterface;
+
+/**
+ * @author Nicolas Grekas
+ */
+class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface
+{
+ use ContractsTrait;
+ use ProxyTrait;
+
+ private $namespace = '';
+ private $namespaceLen;
+ private $poolHash;
+ private $defaultLifetime;
+
+ private static $createCacheItem;
+ private static $setInnerItem;
+
+ public function __construct(CacheItemPoolInterface $pool, string $namespace = '', int $defaultLifetime = 0)
+ {
+ $this->pool = $pool;
+ $this->poolHash = $poolHash = spl_object_hash($pool);
+ if ('' !== $namespace) {
+ \assert('' !== CacheItem::validateKey($namespace));
+ $this->namespace = $namespace;
+ }
+ $this->namespaceLen = \strlen($namespace);
+ $this->defaultLifetime = $defaultLifetime;
+ self::$createCacheItem ?? self::$createCacheItem = \Closure::bind(
+ static function ($key, $innerItem, $poolHash) {
+ $item = new CacheItem();
+ $item->key = $key;
+
+ if (null === $innerItem) {
+ return $item;
+ }
+
+ $item->value = $v = $innerItem->get();
+ $item->isHit = $innerItem->isHit();
+ $item->innerItem = $innerItem;
+ $item->poolHash = $poolHash;
+
+ // Detect wrapped values that encode for their expiry and creation duration
+ // For compactness, these values are packed in the key of an array using
+ // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F
+ if (\is_array($v) && 1 === \count($v) && 10 === \strlen($k = (string) array_key_first($v)) && "\x9D" === $k[0] && "\0" === $k[5] && "\x5F" === $k[9]) {
+ $item->value = $v[$k];
+ $v = unpack('Ve/Nc', substr($k, 1, -1));
+ $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET;
+ $item->metadata[CacheItem::METADATA_CTIME] = $v['c'];
+ } elseif ($innerItem instanceof CacheItem) {
+ $item->metadata = $innerItem->metadata;
+ }
+ $innerItem->set(null);
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ self::$setInnerItem ?? self::$setInnerItem = \Closure::bind(
+ /**
+ * @param array $item A CacheItem cast to (array); accessing protected properties requires adding the "\0*\0" PHP prefix
+ */
+ static function (CacheItemInterface $innerItem, array $item) {
+ // Tags are stored separately, no need to account for them when considering this item's newly set metadata
+ if (isset(($metadata = $item["\0*\0newMetadata"])[CacheItem::METADATA_TAGS])) {
+ unset($metadata[CacheItem::METADATA_TAGS]);
+ }
+ if ($metadata) {
+ // For compactness, expiry and creation duration are packed in the key of an array, using magic numbers as separators
+ $item["\0*\0value"] = ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item["\0*\0value"]];
+ }
+ $innerItem->set($item["\0*\0value"]);
+ $innerItem->expiresAt(null !== $item["\0*\0expiry"] ? \DateTime::createFromFormat('U.u', sprintf('%.6F', $item["\0*\0expiry"])) : null);
+ },
+ null,
+ CacheItem::class
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ if (!$this->pool instanceof CacheInterface) {
+ return $this->doGet($this, $key, $callback, $beta, $metadata);
+ }
+
+ return $this->pool->get($this->getId($key), function ($innerItem, bool &$save) use ($key, $callback) {
+ $item = (self::$createCacheItem)($key, $innerItem, $this->poolHash);
+ $item->set($value = $callback($item, $save));
+ (self::$setInnerItem)($innerItem, (array) $item);
+
+ return $value;
+ }, $beta, $metadata);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItem($key)
+ {
+ $item = $this->pool->getItem($this->getId($key));
+
+ return (self::$createCacheItem)($key, $item, $this->poolHash);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItems(array $keys = [])
+ {
+ if ($this->namespaceLen) {
+ foreach ($keys as $i => $key) {
+ $keys[$i] = $this->getId($key);
+ }
+ }
+
+ return $this->generateItems($this->pool->getItems($keys));
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function hasItem($key)
+ {
+ return $this->pool->hasItem($this->getId($key));
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function clear(string $prefix = '')
+ {
+ if ($this->pool instanceof AdapterInterface) {
+ return $this->pool->clear($this->namespace.$prefix);
+ }
+
+ return $this->pool->clear();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItem($key)
+ {
+ return $this->pool->deleteItem($this->getId($key));
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItems(array $keys)
+ {
+ if ($this->namespaceLen) {
+ foreach ($keys as $i => $key) {
+ $keys[$i] = $this->getId($key);
+ }
+ }
+
+ return $this->pool->deleteItems($keys);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function save(CacheItemInterface $item)
+ {
+ return $this->doSave($item, __FUNCTION__);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function saveDeferred(CacheItemInterface $item)
+ {
+ return $this->doSave($item, __FUNCTION__);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function commit()
+ {
+ return $this->pool->commit();
+ }
+
+ private function doSave(CacheItemInterface $item, string $method)
+ {
+ if (!$item instanceof CacheItem) {
+ return false;
+ }
+ $item = (array) $item;
+ if (null === $item["\0*\0expiry"] && 0 < $this->defaultLifetime) {
+ $item["\0*\0expiry"] = microtime(true) + $this->defaultLifetime;
+ }
+
+ if ($item["\0*\0poolHash"] === $this->poolHash && $item["\0*\0innerItem"]) {
+ $innerItem = $item["\0*\0innerItem"];
+ } elseif ($this->pool instanceof AdapterInterface) {
+ // this is an optimization specific for AdapterInterface implementations
+ // so we can save a round-trip to the backend by just creating a new item
+ $innerItem = (self::$createCacheItem)($this->namespace.$item["\0*\0key"], null, $this->poolHash);
+ } else {
+ $innerItem = $this->pool->getItem($this->namespace.$item["\0*\0key"]);
+ }
+
+ (self::$setInnerItem)($innerItem, $item);
+
+ return $this->pool->$method($innerItem);
+ }
+
+ private function generateItems(iterable $items): \Generator
+ {
+ $f = self::$createCacheItem;
+
+ foreach ($items as $key => $item) {
+ if ($this->namespaceLen) {
+ $key = substr($key, $this->namespaceLen);
+ }
+
+ yield $key => $f($key, $item, $this->poolHash);
+ }
+ }
+
+ private function getId($key): string
+ {
+ \assert('' !== CacheItem::validateKey($key));
+
+ return $this->namespace.$key;
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/Psr16Adapter.php b/vendor/symfony/cache/Adapter/Psr16Adapter.php
new file mode 100644
index 0000000..a56aa39
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/Psr16Adapter.php
@@ -0,0 +1,86 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Psr\SimpleCache\CacheInterface;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Component\Cache\Traits\ProxyTrait;
+
+/**
+ * Turns a PSR-16 cache into a PSR-6 one.
+ *
+ * @author Nicolas Grekas
+ */
+class Psr16Adapter extends AbstractAdapter implements PruneableInterface, ResettableInterface
+{
+ use ProxyTrait;
+
+ /**
+ * @internal
+ */
+ protected const NS_SEPARATOR = '_';
+
+ private $miss;
+
+ public function __construct(CacheInterface $pool, string $namespace = '', int $defaultLifetime = 0)
+ {
+ parent::__construct($namespace, $defaultLifetime);
+
+ $this->pool = $pool;
+ $this->miss = new \stdClass();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doFetch(array $ids)
+ {
+ foreach ($this->pool->getMultiple($ids, $this->miss) as $key => $value) {
+ if ($this->miss !== $value) {
+ yield $key => $value;
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doHave(string $id)
+ {
+ return $this->pool->has($id);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doClear(string $namespace)
+ {
+ return $this->pool->clear();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDelete(array $ids)
+ {
+ return $this->pool->deleteMultiple($ids);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, int $lifetime)
+ {
+ return $this->pool->setMultiple($values, 0 === $lifetime ? null : $lifetime);
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/RedisAdapter.php b/vendor/symfony/cache/Adapter/RedisAdapter.php
new file mode 100644
index 0000000..eb5950e
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/RedisAdapter.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\Adapter;
+
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+use Symfony\Component\Cache\Traits\RedisClusterProxy;
+use Symfony\Component\Cache\Traits\RedisProxy;
+use Symfony\Component\Cache\Traits\RedisTrait;
+
+class RedisAdapter extends AbstractAdapter
+{
+ use RedisTrait;
+
+ /**
+ * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis The redis client
+ * @param string $namespace The default namespace
+ * @param int $defaultLifetime The default lifetime
+ */
+ public function __construct($redis, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
+ {
+ $this->init($redis, $namespace, $defaultLifetime, $marshaller);
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php b/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php
new file mode 100644
index 0000000..865491e
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php
@@ -0,0 +1,325 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Predis\Connection\Aggregate\ClusterInterface;
+use Predis\Connection\Aggregate\PredisCluster;
+use Predis\Connection\Aggregate\ReplicationInterface;
+use Predis\Response\ErrorInterface;
+use Predis\Response\Status;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\Exception\LogicException;
+use Symfony\Component\Cache\Marshaller\DeflateMarshaller;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+use Symfony\Component\Cache\Marshaller\TagAwareMarshaller;
+use Symfony\Component\Cache\Traits\RedisClusterProxy;
+use Symfony\Component\Cache\Traits\RedisProxy;
+use Symfony\Component\Cache\Traits\RedisTrait;
+
+/**
+ * Stores tag id <> cache id relationship as a Redis Set.
+ *
+ * Set (tag relation info) is stored without expiry (non-volatile), while cache always gets an expiry (volatile) even
+ * if not set by caller. Thus if you configure redis with the right eviction policy you can be safe this tag <> cache
+ * relationship survives eviction (cache cleanup when Redis runs out of memory).
+ *
+ * Redis server 2.8+ with any `volatile-*` eviction policy, OR `noeviction` if you're sure memory will NEVER fill up
+ *
+ * Design limitations:
+ * - Max 4 billion cache keys per cache tag as limited by Redis Set datatype.
+ * E.g. If you use a "all" items tag for expiry instead of clear(), that limits you to 4 billion cache items also.
+ *
+ * @see https://redis.io/topics/lru-cache#eviction-policies Documentation for Redis eviction policies.
+ * @see https://redis.io/topics/data-types#sets Documentation for Redis Set datatype.
+ *
+ * @author Nicolas Grekas
+ * @author André Rømcke
+ */
+class RedisTagAwareAdapter extends AbstractTagAwareAdapter
+{
+ use RedisTrait;
+
+ /**
+ * On cache items without a lifetime set, we set it to 100 days. This is to make sure cache items are
+ * preferred to be evicted over tag Sets, if eviction policy is configured according to requirements.
+ */
+ private const DEFAULT_CACHE_TTL = 8640000;
+
+ /**
+ * @var string|null detected eviction policy used on Redis server
+ */
+ private $redisEvictionPolicy;
+ private $namespace;
+
+ /**
+ * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis The redis client
+ * @param string $namespace The default namespace
+ * @param int $defaultLifetime The default lifetime
+ */
+ public function __construct($redis, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
+ {
+ if ($redis instanceof \Predis\ClientInterface && $redis->getConnection() instanceof ClusterInterface && !$redis->getConnection() instanceof PredisCluster) {
+ throw new InvalidArgumentException(sprintf('Unsupported Predis cluster connection: only "%s" is, "%s" given.', PredisCluster::class, get_debug_type($redis->getConnection())));
+ }
+
+ if (\defined('Redis::OPT_COMPRESSION') && ($redis instanceof \Redis || $redis instanceof \RedisArray || $redis instanceof \RedisCluster)) {
+ $compression = $redis->getOption(\Redis::OPT_COMPRESSION);
+
+ foreach (\is_array($compression) ? $compression : [$compression] as $c) {
+ if (\Redis::COMPRESSION_NONE !== $c) {
+ throw new InvalidArgumentException(sprintf('phpredis compression must be disabled when using "%s", use "%s" instead.', static::class, DeflateMarshaller::class));
+ }
+ }
+ }
+
+ $this->init($redis, $namespace, $defaultLifetime, new TagAwareMarshaller($marshaller));
+ $this->namespace = $namespace;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, int $lifetime, array $addTagData = [], array $delTagData = []): array
+ {
+ $eviction = $this->getRedisEvictionPolicy();
+ if ('noeviction' !== $eviction && !str_starts_with($eviction, 'volatile-')) {
+ throw new LogicException(sprintf('Redis maxmemory-policy setting "%s" is *not* supported by RedisTagAwareAdapter, use "noeviction" or "volatile-*" eviction policies.', $eviction));
+ }
+
+ // serialize values
+ if (!$serialized = $this->marshaller->marshall($values, $failed)) {
+ return $failed;
+ }
+
+ // While pipeline isn't supported on RedisCluster, other setups will at least benefit from doing this in one op
+ $results = $this->pipeline(static function () use ($serialized, $lifetime, $addTagData, $delTagData, $failed) {
+ // Store cache items, force a ttl if none is set, as there is no MSETEX we need to set each one
+ foreach ($serialized as $id => $value) {
+ yield 'setEx' => [
+ $id,
+ 0 >= $lifetime ? self::DEFAULT_CACHE_TTL : $lifetime,
+ $value,
+ ];
+ }
+
+ // Add and Remove Tags
+ foreach ($addTagData as $tagId => $ids) {
+ if (!$failed || $ids = array_diff($ids, $failed)) {
+ yield 'sAdd' => array_merge([$tagId], $ids);
+ }
+ }
+
+ foreach ($delTagData as $tagId => $ids) {
+ if (!$failed || $ids = array_diff($ids, $failed)) {
+ yield 'sRem' => array_merge([$tagId], $ids);
+ }
+ }
+ });
+
+ foreach ($results as $id => $result) {
+ // Skip results of SADD/SREM operations, they'll be 1 or 0 depending on if set value already existed or not
+ if (is_numeric($result)) {
+ continue;
+ }
+ // setEx results
+ if (true !== $result && (!$result instanceof Status || Status::get('OK') !== $result)) {
+ $failed[] = $id;
+ }
+ }
+
+ return $failed;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDeleteYieldTags(array $ids): iterable
+ {
+ $lua = <<<'EOLUA'
+ local v = redis.call('GET', KEYS[1])
+ local e = redis.pcall('UNLINK', KEYS[1])
+
+ if type(e) ~= 'number' then
+ redis.call('DEL', KEYS[1])
+ end
+
+ if not v or v:len() <= 13 or v:byte(1) ~= 0x9D or v:byte(6) ~= 0 or v:byte(10) ~= 0x5F then
+ return ''
+ end
+
+ return v:sub(14, 13 + v:byte(13) + v:byte(12) * 256 + v:byte(11) * 65536)
+EOLUA;
+
+ $results = $this->pipeline(function () use ($ids, $lua) {
+ foreach ($ids as $id) {
+ yield 'eval' => $this->redis instanceof \Predis\ClientInterface ? [$lua, 1, $id] : [$lua, [$id], 1];
+ }
+ });
+
+ foreach ($results as $id => $result) {
+ if ($result instanceof \RedisException || $result instanceof ErrorInterface) {
+ CacheItem::log($this->logger, 'Failed to delete key "{key}": '.$result->getMessage(), ['key' => substr($id, \strlen($this->namespace)), 'exception' => $result]);
+
+ continue;
+ }
+
+ try {
+ yield $id => !\is_string($result) || '' === $result ? [] : $this->marshaller->unmarshall($result);
+ } catch (\Exception $e) {
+ yield $id => [];
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDeleteTagRelations(array $tagData): bool
+ {
+ $results = $this->pipeline(static function () use ($tagData) {
+ foreach ($tagData as $tagId => $idList) {
+ array_unshift($idList, $tagId);
+ yield 'sRem' => $idList;
+ }
+ });
+ foreach ($results as $result) {
+ // no-op
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doInvalidate(array $tagIds): bool
+ {
+ // This script scans the set of items linked to tag: it empties the set
+ // and removes the linked items. When the set is still not empty after
+ // the scan, it means we're in cluster mode and that the linked items
+ // are on other nodes: we move the links to a temporary set and we
+ // gargage collect that set from the client side.
+
+ $lua = <<<'EOLUA'
+ redis.replicate_commands()
+
+ local cursor = '0'
+ local id = KEYS[1]
+ repeat
+ local result = redis.call('SSCAN', id, cursor, 'COUNT', 5000);
+ cursor = result[1];
+ local rems = {}
+
+ for _, v in ipairs(result[2]) do
+ local ok, _ = pcall(redis.call, 'DEL', ARGV[1]..v)
+ if ok then
+ table.insert(rems, v)
+ end
+ end
+ if 0 < #rems then
+ redis.call('SREM', id, unpack(rems))
+ end
+ until '0' == cursor;
+
+ redis.call('SUNIONSTORE', '{'..id..'}'..id, id)
+ redis.call('DEL', id)
+
+ return redis.call('SSCAN', '{'..id..'}'..id, '0', 'COUNT', 5000)
+EOLUA;
+
+ $results = $this->pipeline(function () use ($tagIds, $lua) {
+ if ($this->redis instanceof \Predis\ClientInterface) {
+ $prefix = $this->redis->getOptions()->prefix ? $this->redis->getOptions()->prefix->getPrefix() : '';
+ } elseif (\is_array($prefix = $this->redis->getOption(\Redis::OPT_PREFIX) ?? '')) {
+ $prefix = current($prefix);
+ }
+
+ foreach ($tagIds as $id) {
+ yield 'eval' => $this->redis instanceof \Predis\ClientInterface ? [$lua, 1, $id, $prefix] : [$lua, [$id, $prefix], 1];
+ }
+ });
+
+ $lua = <<<'EOLUA'
+ redis.replicate_commands()
+
+ local id = KEYS[1]
+ local cursor = table.remove(ARGV)
+ redis.call('SREM', '{'..id..'}'..id, unpack(ARGV))
+
+ return redis.call('SSCAN', '{'..id..'}'..id, cursor, 'COUNT', 5000)
+EOLUA;
+
+ $success = true;
+ foreach ($results as $id => $values) {
+ if ($values instanceof \RedisException || $values instanceof ErrorInterface) {
+ CacheItem::log($this->logger, 'Failed to invalidate key "{key}": '.$values->getMessage(), ['key' => substr($id, \strlen($this->namespace)), 'exception' => $values]);
+ $success = false;
+
+ continue;
+ }
+
+ [$cursor, $ids] = $values;
+
+ while ($ids || '0' !== $cursor) {
+ $this->doDelete($ids);
+
+ $evalArgs = [$id, $cursor];
+ array_splice($evalArgs, 1, 0, $ids);
+
+ if ($this->redis instanceof \Predis\ClientInterface) {
+ array_unshift($evalArgs, $lua, 1);
+ } else {
+ $evalArgs = [$lua, $evalArgs, 1];
+ }
+
+ $results = $this->pipeline(function () use ($evalArgs) {
+ yield 'eval' => $evalArgs;
+ });
+
+ foreach ($results as [$cursor, $ids]) {
+ // no-op
+ }
+ }
+ }
+
+ return $success;
+ }
+
+ private function getRedisEvictionPolicy(): string
+ {
+ if (null !== $this->redisEvictionPolicy) {
+ return $this->redisEvictionPolicy;
+ }
+
+ $hosts = $this->getHosts();
+ $host = reset($hosts);
+ if ($host instanceof \Predis\Client && $host->getConnection() instanceof ReplicationInterface) {
+ // Predis supports info command only on the master in replication environments
+ $hosts = [$host->getClientFor('master')];
+ }
+
+ foreach ($hosts as $host) {
+ $info = $host->info('Memory');
+
+ if ($info instanceof ErrorInterface) {
+ continue;
+ }
+
+ $info = $info['Memory'] ?? $info;
+
+ return $this->redisEvictionPolicy = $info['maxmemory_policy'];
+ }
+
+ return $this->redisEvictionPolicy = '';
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/TagAwareAdapter.php b/vendor/symfony/cache/Adapter/TagAwareAdapter.php
new file mode 100644
index 0000000..ff22e5a
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/TagAwareAdapter.php
@@ -0,0 +1,428 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Psr\Cache\CacheItemInterface;
+use Psr\Cache\InvalidArgumentException;
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerAwareTrait;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Component\Cache\Traits\ContractsTrait;
+use Symfony\Component\Cache\Traits\ProxyTrait;
+use Symfony\Contracts\Cache\TagAwareCacheInterface;
+
+/**
+ * @author Nicolas Grekas
+ */
+class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface, PruneableInterface, ResettableInterface, LoggerAwareInterface
+{
+ use ContractsTrait;
+ use LoggerAwareTrait;
+ use ProxyTrait;
+
+ public const TAGS_PREFIX = "\0tags\0";
+
+ private $deferred = [];
+ private $tags;
+ private $knownTagVersions = [];
+ private $knownTagVersionsTtl;
+
+ private static $createCacheItem;
+ private static $setCacheItemTags;
+ private static $getTagsByKey;
+ private static $saveTags;
+
+ public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null, float $knownTagVersionsTtl = 0.15)
+ {
+ $this->pool = $itemsPool;
+ $this->tags = $tagsPool ?: $itemsPool;
+ $this->knownTagVersionsTtl = $knownTagVersionsTtl;
+ self::$createCacheItem ?? self::$createCacheItem = \Closure::bind(
+ static function ($key, $value, CacheItem $protoItem) {
+ $item = new CacheItem();
+ $item->key = $key;
+ $item->value = $value;
+ $item->expiry = $protoItem->expiry;
+ $item->poolHash = $protoItem->poolHash;
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ self::$setCacheItemTags ?? self::$setCacheItemTags = \Closure::bind(
+ static function (CacheItem $item, $key, array &$itemTags) {
+ $item->isTaggable = true;
+ if (!$item->isHit) {
+ return $item;
+ }
+ if (isset($itemTags[$key])) {
+ foreach ($itemTags[$key] as $tag => $version) {
+ $item->metadata[CacheItem::METADATA_TAGS][$tag] = $tag;
+ }
+ unset($itemTags[$key]);
+ } else {
+ $item->value = null;
+ $item->isHit = false;
+ }
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ self::$getTagsByKey ?? self::$getTagsByKey = \Closure::bind(
+ static function ($deferred) {
+ $tagsByKey = [];
+ foreach ($deferred as $key => $item) {
+ $tagsByKey[$key] = $item->newMetadata[CacheItem::METADATA_TAGS] ?? [];
+ $item->metadata = $item->newMetadata;
+ }
+
+ return $tagsByKey;
+ },
+ null,
+ CacheItem::class
+ );
+ self::$saveTags ?? self::$saveTags = \Closure::bind(
+ static function (AdapterInterface $tagsAdapter, array $tags) {
+ ksort($tags);
+
+ foreach ($tags as $v) {
+ $v->expiry = 0;
+ $tagsAdapter->saveDeferred($v);
+ }
+
+ return $tagsAdapter->commit();
+ },
+ null,
+ CacheItem::class
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function invalidateTags(array $tags)
+ {
+ $ids = [];
+ foreach ($tags as $tag) {
+ \assert('' !== CacheItem::validateKey($tag));
+ unset($this->knownTagVersions[$tag]);
+ $ids[] = $tag.static::TAGS_PREFIX;
+ }
+
+ return !$tags || $this->tags->deleteItems($ids);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function hasItem($key)
+ {
+ if (\is_string($key) && isset($this->deferred[$key])) {
+ $this->commit();
+ }
+
+ if (!$this->pool->hasItem($key)) {
+ return false;
+ }
+
+ $itemTags = $this->pool->getItem(static::TAGS_PREFIX.$key);
+
+ if (!$itemTags->isHit()) {
+ return false;
+ }
+
+ if (!$itemTags = $itemTags->get()) {
+ return true;
+ }
+
+ foreach ($this->getTagVersions([$itemTags]) as $tag => $version) {
+ if ($itemTags[$tag] !== $version) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItem($key)
+ {
+ foreach ($this->getItems([$key]) as $item) {
+ return $item;
+ }
+
+ return null;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItems(array $keys = [])
+ {
+ $tagKeys = [];
+ $commit = false;
+
+ foreach ($keys as $key) {
+ if ('' !== $key && \is_string($key)) {
+ $commit = $commit || isset($this->deferred[$key]);
+ $key = static::TAGS_PREFIX.$key;
+ $tagKeys[$key] = $key;
+ }
+ }
+
+ if ($commit) {
+ $this->commit();
+ }
+
+ try {
+ $items = $this->pool->getItems($tagKeys + $keys);
+ } catch (InvalidArgumentException $e) {
+ $this->pool->getItems($keys); // Should throw an exception
+
+ throw $e;
+ }
+
+ return $this->generateItems($items, $tagKeys);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function clear(string $prefix = '')
+ {
+ if ('' !== $prefix) {
+ foreach ($this->deferred as $key => $item) {
+ if (str_starts_with($key, $prefix)) {
+ unset($this->deferred[$key]);
+ }
+ }
+ } else {
+ $this->deferred = [];
+ }
+
+ if ($this->pool instanceof AdapterInterface) {
+ return $this->pool->clear($prefix);
+ }
+
+ return $this->pool->clear();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItem($key)
+ {
+ return $this->deleteItems([$key]);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItems(array $keys)
+ {
+ foreach ($keys as $key) {
+ if ('' !== $key && \is_string($key)) {
+ $keys[] = static::TAGS_PREFIX.$key;
+ }
+ }
+
+ return $this->pool->deleteItems($keys);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function save(CacheItemInterface $item)
+ {
+ if (!$item instanceof CacheItem) {
+ return false;
+ }
+ $this->deferred[$item->getKey()] = $item;
+
+ return $this->commit();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function saveDeferred(CacheItemInterface $item)
+ {
+ if (!$item instanceof CacheItem) {
+ return false;
+ }
+ $this->deferred[$item->getKey()] = $item;
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function commit()
+ {
+ if (!$this->deferred) {
+ return true;
+ }
+
+ $ok = true;
+ foreach ($this->deferred as $key => $item) {
+ if (!$this->pool->saveDeferred($item)) {
+ unset($this->deferred[$key]);
+ $ok = false;
+ }
+ }
+
+ $items = $this->deferred;
+ $tagsByKey = (self::$getTagsByKey)($items);
+ $this->deferred = [];
+
+ $tagVersions = $this->getTagVersions($tagsByKey);
+ $f = self::$createCacheItem;
+
+ foreach ($tagsByKey as $key => $tags) {
+ $this->pool->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key]));
+ }
+
+ return $this->pool->commit() && $ok;
+ }
+
+ /**
+ * @return array
+ */
+ public function __sleep()
+ {
+ throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
+ }
+
+ public function __wakeup()
+ {
+ throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
+ }
+
+ public function __destruct()
+ {
+ $this->commit();
+ }
+
+ private function generateItems(iterable $items, array $tagKeys): \Generator
+ {
+ $bufferedItems = $itemTags = [];
+ $f = self::$setCacheItemTags;
+
+ foreach ($items as $key => $item) {
+ if (!$tagKeys) {
+ yield $key => $f($item, static::TAGS_PREFIX.$key, $itemTags);
+ continue;
+ }
+ if (!isset($tagKeys[$key])) {
+ $bufferedItems[$key] = $item;
+ continue;
+ }
+
+ unset($tagKeys[$key]);
+
+ if ($item->isHit()) {
+ $itemTags[$key] = $item->get() ?: [];
+ }
+
+ if (!$tagKeys) {
+ $tagVersions = $this->getTagVersions($itemTags);
+
+ foreach ($itemTags as $key => $tags) {
+ foreach ($tags as $tag => $version) {
+ if ($tagVersions[$tag] !== $version) {
+ unset($itemTags[$key]);
+ continue 2;
+ }
+ }
+ }
+ $tagVersions = $tagKeys = null;
+
+ foreach ($bufferedItems as $key => $item) {
+ yield $key => $f($item, static::TAGS_PREFIX.$key, $itemTags);
+ }
+ $bufferedItems = null;
+ }
+ }
+ }
+
+ private function getTagVersions(array $tagsByKey)
+ {
+ $tagVersions = [];
+ $fetchTagVersions = false;
+
+ foreach ($tagsByKey as $tags) {
+ $tagVersions += $tags;
+
+ foreach ($tags as $tag => $version) {
+ if ($tagVersions[$tag] !== $version) {
+ unset($this->knownTagVersions[$tag]);
+ }
+ }
+ }
+
+ if (!$tagVersions) {
+ return [];
+ }
+
+ $now = microtime(true);
+ $tags = [];
+ foreach ($tagVersions as $tag => $version) {
+ $tags[$tag.static::TAGS_PREFIX] = $tag;
+ if ($fetchTagVersions || ($this->knownTagVersions[$tag][1] ?? null) !== $version || $now - $this->knownTagVersions[$tag][0] >= $this->knownTagVersionsTtl) {
+ // reuse previously fetched tag versions up to the ttl
+ $fetchTagVersions = true;
+ }
+ }
+
+ if (!$fetchTagVersions) {
+ return $tagVersions;
+ }
+
+ $newTags = [];
+ $newVersion = null;
+ foreach ($this->tags->getItems(array_keys($tags)) as $tag => $version) {
+ if (!$version->isHit()) {
+ $newTags[$tag] = $version->set($newVersion ?? $newVersion = random_int(\PHP_INT_MIN, \PHP_INT_MAX));
+ }
+ $tagVersions[$tag = $tags[$tag]] = $version->get();
+ $this->knownTagVersions[$tag] = [$now, $tagVersions[$tag]];
+ }
+
+ if ($newTags) {
+ (self::$saveTags)($this->tags, $newTags);
+ }
+
+ return $tagVersions;
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php b/vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php
new file mode 100644
index 0000000..afa18d3
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php
@@ -0,0 +1,33 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Psr\Cache\InvalidArgumentException;
+
+/**
+ * Interface for invalidating cached items using tags.
+ *
+ * @author Nicolas Grekas
+ */
+interface TagAwareAdapterInterface extends AdapterInterface
+{
+ /**
+ * Invalidates cached items using tags.
+ *
+ * @param string[] $tags An array of tags to invalidate
+ *
+ * @return bool
+ *
+ * @throws InvalidArgumentException When $tags is not valid
+ */
+ public function invalidateTags(array $tags);
+}
diff --git a/vendor/symfony/cache/Adapter/TraceableAdapter.php b/vendor/symfony/cache/Adapter/TraceableAdapter.php
new file mode 100644
index 0000000..4b06557
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/TraceableAdapter.php
@@ -0,0 +1,295 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Psr\Cache\CacheItemInterface;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Contracts\Cache\CacheInterface;
+use Symfony\Contracts\Service\ResetInterface;
+
+/**
+ * An adapter that collects data about all cache calls.
+ *
+ * @author Aaron Scherer
+ * @author Tobias Nyholm
+ * @author Nicolas Grekas
+ */
+class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface
+{
+ protected $pool;
+ private $calls = [];
+
+ public function __construct(AdapterInterface $pool)
+ {
+ $this->pool = $pool;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ if (!$this->pool instanceof CacheInterface) {
+ throw new \BadMethodCallException(sprintf('Cannot call "%s::get()": this class doesn\'t implement "%s".', get_debug_type($this->pool), CacheInterface::class));
+ }
+
+ $isHit = true;
+ $callback = function (CacheItem $item, bool &$save) use ($callback, &$isHit) {
+ $isHit = $item->isHit();
+
+ return $callback($item, $save);
+ };
+
+ $event = $this->start(__FUNCTION__);
+ try {
+ $value = $this->pool->get($key, $callback, $beta, $metadata);
+ $event->result[$key] = get_debug_type($value);
+ } finally {
+ $event->end = microtime(true);
+ }
+ if ($isHit) {
+ ++$event->hits;
+ } else {
+ ++$event->misses;
+ }
+
+ return $value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItem($key)
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ $item = $this->pool->getItem($key);
+ } finally {
+ $event->end = microtime(true);
+ }
+ if ($event->result[$key] = $item->isHit()) {
+ ++$event->hits;
+ } else {
+ ++$event->misses;
+ }
+
+ return $item;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function hasItem($key)
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ return $event->result[$key] = $this->pool->hasItem($key);
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItem($key)
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ return $event->result[$key] = $this->pool->deleteItem($key);
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function save(CacheItemInterface $item)
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ return $event->result[$item->getKey()] = $this->pool->save($item);
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function saveDeferred(CacheItemInterface $item)
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ return $event->result[$item->getKey()] = $this->pool->saveDeferred($item);
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItems(array $keys = [])
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ $result = $this->pool->getItems($keys);
+ } finally {
+ $event->end = microtime(true);
+ }
+ $f = function () use ($result, $event) {
+ $event->result = [];
+ foreach ($result as $key => $item) {
+ if ($event->result[$key] = $item->isHit()) {
+ ++$event->hits;
+ } else {
+ ++$event->misses;
+ }
+ yield $key => $item;
+ }
+ };
+
+ return $f();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function clear(string $prefix = '')
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ if ($this->pool instanceof AdapterInterface) {
+ return $event->result = $this->pool->clear($prefix);
+ }
+
+ return $event->result = $this->pool->clear();
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItems(array $keys)
+ {
+ $event = $this->start(__FUNCTION__);
+ $event->result['keys'] = $keys;
+ try {
+ return $event->result['result'] = $this->pool->deleteItems($keys);
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function commit()
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ return $event->result = $this->pool->commit();
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function prune()
+ {
+ if (!$this->pool instanceof PruneableInterface) {
+ return false;
+ }
+ $event = $this->start(__FUNCTION__);
+ try {
+ return $event->result = $this->pool->prune();
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function reset()
+ {
+ if ($this->pool instanceof ResetInterface) {
+ $this->pool->reset();
+ }
+
+ $this->clearCalls();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete(string $key): bool
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ return $event->result[$key] = $this->pool->deleteItem($key);
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+
+ public function getCalls()
+ {
+ return $this->calls;
+ }
+
+ public function clearCalls()
+ {
+ $this->calls = [];
+ }
+
+ protected function start(string $name)
+ {
+ $this->calls[] = $event = new TraceableAdapterEvent();
+ $event->name = $name;
+ $event->start = microtime(true);
+
+ return $event;
+ }
+}
+
+class TraceableAdapterEvent
+{
+ public $name;
+ public $start;
+ public $end;
+ public $result;
+ public $hits = 0;
+ public $misses = 0;
+}
diff --git a/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php b/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php
new file mode 100644
index 0000000..69461b8
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php
@@ -0,0 +1,38 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Symfony\Contracts\Cache\TagAwareCacheInterface;
+
+/**
+ * @author Robin Chalas
+ */
+class TraceableTagAwareAdapter extends TraceableAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface
+{
+ public function __construct(TagAwareAdapterInterface $pool)
+ {
+ parent::__construct($pool);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function invalidateTags(array $tags)
+ {
+ $event = $this->start(__FUNCTION__);
+ try {
+ return $event->result = $this->pool->invalidateTags($tags);
+ } finally {
+ $event->end = microtime(true);
+ }
+ }
+}
diff --git a/vendor/symfony/cache/CHANGELOG.md b/vendor/symfony/cache/CHANGELOG.md
new file mode 100644
index 0000000..60a8627
--- /dev/null
+++ b/vendor/symfony/cache/CHANGELOG.md
@@ -0,0 +1,108 @@
+CHANGELOG
+=========
+
+5.4
+---
+
+ * Deprecate `DoctrineProvider` and `DoctrineAdapter` because these classes have been added to the `doctrine/cache` package
+ * Add `DoctrineDbalAdapter` identical to `PdoAdapter` for `Doctrine\DBAL\Connection` or DBAL URL
+ * Deprecate usage of `PdoAdapter` with `Doctrine\DBAL\Connection` or DBAL URL
+
+5.3
+---
+
+ * added support for connecting to Redis Sentinel clusters when using the Redis PHP extension
+ * add support for a custom serializer to the `ApcuAdapter` class
+
+5.2.0
+-----
+
+ * added integration with Messenger to allow computing cached values in a worker
+ * allow ISO 8601 time intervals to specify default lifetime
+
+5.1.0
+-----
+
+ * added max-items + LRU + max-lifetime capabilities to `ArrayCache`
+ * added `CouchbaseBucketAdapter`
+ * added context `cache-adapter` to log messages
+
+5.0.0
+-----
+
+ * removed all PSR-16 implementations in the `Simple` namespace
+ * removed `SimpleCacheAdapter`
+ * removed `AbstractAdapter::unserialize()`
+ * removed `CacheItem::getPreviousTags()`
+
+4.4.0
+-----
+
+ * added support for connecting to Redis Sentinel clusters
+ * added argument `$prefix` to `AdapterInterface::clear()`
+ * improved `RedisTagAwareAdapter` to support Redis server >= 2.8 and up to 4B items per tag
+ * added `TagAwareMarshaller` for optimized data storage when using `AbstractTagAwareAdapter`
+ * added `DeflateMarshaller` to compress serialized values
+ * removed support for phpredis 4 `compression`
+ * [BC BREAK] `RedisTagAwareAdapter` is not compatible with `RedisCluster` from `Predis` anymore, use `phpredis` instead
+ * Marked the `CacheDataCollector` class as `@final`.
+ * added `SodiumMarshaller` to encrypt/decrypt values using libsodium
+
+4.3.0
+-----
+
+ * removed `psr/simple-cache` dependency, run `composer require psr/simple-cache` if you need it
+ * deprecated all PSR-16 adapters, use `Psr16Cache` or `Symfony\Contracts\Cache\CacheInterface` implementations instead
+ * deprecated `SimpleCacheAdapter`, use `Psr16Adapter` instead
+
+4.2.0
+-----
+
+ * added support for connecting to Redis clusters via DSN
+ * added support for configuring multiple Memcached servers via DSN
+ * added `MarshallerInterface` and `DefaultMarshaller` to allow changing the serializer and provide one that automatically uses igbinary when available
+ * implemented `CacheInterface`, which provides stampede protection via probabilistic early expiration and should become the preferred way to use a cache
+ * added sub-second expiry accuracy for backends that support it
+ * added support for phpredis 4 `compression` and `tcp_keepalive` options
+ * added automatic table creation when using Doctrine DBAL with PDO-based backends
+ * throw `LogicException` when `CacheItem::tag()` is called on an item coming from a non tag-aware pool
+ * deprecated `CacheItem::getPreviousTags()`, use `CacheItem::getMetadata()` instead
+ * deprecated the `AbstractAdapter::unserialize()` and `AbstractCache::unserialize()` methods
+ * added `CacheCollectorPass` (originally in `FrameworkBundle`)
+ * added `CachePoolClearerPass` (originally in `FrameworkBundle`)
+ * added `CachePoolPass` (originally in `FrameworkBundle`)
+ * added `CachePoolPrunerPass` (originally in `FrameworkBundle`)
+
+3.4.0
+-----
+
+ * added using options from Memcached DSN
+ * added PruneableInterface so PSR-6 or PSR-16 cache implementations can declare support for manual stale cache pruning
+ * added prune logic to FilesystemTrait, PhpFilesTrait, PdoTrait, TagAwareAdapter and ChainTrait
+ * now FilesystemAdapter, PhpFilesAdapter, FilesystemCache, PhpFilesCache, PdoAdapter, PdoCache, ChainAdapter, and
+ ChainCache implement PruneableInterface and support manual stale cache pruning
+
+3.3.0
+-----
+
+ * added CacheItem::getPreviousTags() to get bound tags coming from the pool storage if any
+ * added PSR-16 "Simple Cache" implementations for all existing PSR-6 adapters
+ * added Psr6Cache and SimpleCacheAdapter for bidirectional interoperability between PSR-6 and PSR-16
+ * added MemcachedAdapter (PSR-6) and MemcachedCache (PSR-16)
+ * added TraceableAdapter (PSR-6) and TraceableCache (PSR-16)
+
+3.2.0
+-----
+
+ * added TagAwareAdapter for tags-based invalidation
+ * added PdoAdapter with PDO and Doctrine DBAL support
+ * added PhpArrayAdapter and PhpFilesAdapter for OPcache-backed shared memory storage (PHP 7+ only)
+ * added NullAdapter
+
+3.1.0
+-----
+
+ * added the component with strict PSR-6 implementations
+ * added ApcuAdapter, ArrayAdapter, FilesystemAdapter and RedisAdapter
+ * added AbstractAdapter, ChainAdapter and ProxyAdapter
+ * added DoctrineAdapter and DoctrineProvider for bidirectional interoperability with Doctrine Cache
diff --git a/vendor/symfony/cache/CacheItem.php b/vendor/symfony/cache/CacheItem.php
new file mode 100644
index 0000000..091d9e9
--- /dev/null
+++ b/vendor/symfony/cache/CacheItem.php
@@ -0,0 +1,192 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache;
+
+use Psr\Log\LoggerInterface;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\Exception\LogicException;
+use Symfony\Contracts\Cache\ItemInterface;
+
+/**
+ * @author Nicolas Grekas
+ */
+final class CacheItem implements ItemInterface
+{
+ private const METADATA_EXPIRY_OFFSET = 1527506807;
+
+ protected $key;
+ protected $value;
+ protected $isHit = false;
+ protected $expiry;
+ protected $metadata = [];
+ protected $newMetadata = [];
+ protected $innerItem;
+ protected $poolHash;
+ protected $isTaggable = false;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getKey(): string
+ {
+ return $this->key;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return mixed
+ */
+ public function get()
+ {
+ return $this->value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isHit(): bool
+ {
+ return $this->isHit;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return $this
+ */
+ public function set($value): self
+ {
+ $this->value = $value;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return $this
+ */
+ public function expiresAt($expiration): self
+ {
+ if (null === $expiration) {
+ $this->expiry = null;
+ } elseif ($expiration instanceof \DateTimeInterface) {
+ $this->expiry = (float) $expiration->format('U.u');
+ } else {
+ throw new InvalidArgumentException(sprintf('Expiration date must implement DateTimeInterface or be null, "%s" given.', get_debug_type($expiration)));
+ }
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return $this
+ */
+ public function expiresAfter($time): self
+ {
+ if (null === $time) {
+ $this->expiry = null;
+ } elseif ($time instanceof \DateInterval) {
+ $this->expiry = microtime(true) + \DateTime::createFromFormat('U', 0)->add($time)->format('U.u');
+ } elseif (\is_int($time)) {
+ $this->expiry = $time + microtime(true);
+ } else {
+ throw new InvalidArgumentException(sprintf('Expiration date must be an integer, a DateInterval or null, "%s" given.', get_debug_type($time)));
+ }
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function tag($tags): ItemInterface
+ {
+ if (!$this->isTaggable) {
+ throw new LogicException(sprintf('Cache item "%s" comes from a non tag-aware pool: you cannot tag it.', $this->key));
+ }
+ if (!is_iterable($tags)) {
+ $tags = [$tags];
+ }
+ foreach ($tags as $tag) {
+ if (!\is_string($tag) && !(\is_object($tag) && method_exists($tag, '__toString'))) {
+ throw new InvalidArgumentException(sprintf('Cache tag must be string or object that implements __toString(), "%s" given.', \is_object($tag) ? \get_class($tag) : \gettype($tag)));
+ }
+ $tag = (string) $tag;
+ if (isset($this->newMetadata[self::METADATA_TAGS][$tag])) {
+ continue;
+ }
+ if ('' === $tag) {
+ throw new InvalidArgumentException('Cache tag length must be greater than zero.');
+ }
+ if (false !== strpbrk($tag, self::RESERVED_CHARACTERS)) {
+ throw new InvalidArgumentException(sprintf('Cache tag "%s" contains reserved characters "%s".', $tag, self::RESERVED_CHARACTERS));
+ }
+ $this->newMetadata[self::METADATA_TAGS][$tag] = $tag;
+ }
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMetadata(): array
+ {
+ return $this->metadata;
+ }
+
+ /**
+ * Validates a cache key according to PSR-6.
+ *
+ * @param mixed $key The key to validate
+ *
+ * @throws InvalidArgumentException When $key is not valid
+ */
+ public static function validateKey($key): string
+ {
+ if (!\is_string($key)) {
+ throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', get_debug_type($key)));
+ }
+ if ('' === $key) {
+ throw new InvalidArgumentException('Cache key length must be greater than zero.');
+ }
+ if (false !== strpbrk($key, self::RESERVED_CHARACTERS)) {
+ throw new InvalidArgumentException(sprintf('Cache key "%s" contains reserved characters "%s".', $key, self::RESERVED_CHARACTERS));
+ }
+
+ return $key;
+ }
+
+ /**
+ * Internal logging helper.
+ *
+ * @internal
+ */
+ public static function log(?LoggerInterface $logger, string $message, array $context = [])
+ {
+ if ($logger) {
+ $logger->warning($message, $context);
+ } else {
+ $replace = [];
+ foreach ($context as $k => $v) {
+ if (\is_scalar($v)) {
+ $replace['{'.$k.'}'] = $v;
+ }
+ }
+ @trigger_error(strtr($message, $replace), \E_USER_WARNING);
+ }
+ }
+}
diff --git a/vendor/symfony/cache/DataCollector/CacheDataCollector.php b/vendor/symfony/cache/DataCollector/CacheDataCollector.php
new file mode 100644
index 0000000..9590436
--- /dev/null
+++ b/vendor/symfony/cache/DataCollector/CacheDataCollector.php
@@ -0,0 +1,185 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\DataCollector;
+
+use Symfony\Component\Cache\Adapter\TraceableAdapter;
+use Symfony\Component\Cache\Adapter\TraceableAdapterEvent;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\DataCollector\DataCollector;
+use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
+
+/**
+ * @author Aaron Scherer
+ * @author Tobias Nyholm
+ *
+ * @final
+ */
+class CacheDataCollector extends DataCollector implements LateDataCollectorInterface
+{
+ /**
+ * @var TraceableAdapter[]
+ */
+ private $instances = [];
+
+ public function addInstance(string $name, TraceableAdapter $instance)
+ {
+ $this->instances[$name] = $instance;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function collect(Request $request, Response $response, \Throwable $exception = null)
+ {
+ $empty = ['calls' => [], 'config' => [], 'options' => [], 'statistics' => []];
+ $this->data = ['instances' => $empty, 'total' => $empty];
+ foreach ($this->instances as $name => $instance) {
+ $this->data['instances']['calls'][$name] = $instance->getCalls();
+ }
+
+ $this->data['instances']['statistics'] = $this->calculateStatistics();
+ $this->data['total']['statistics'] = $this->calculateTotalStatistics();
+ }
+
+ public function reset()
+ {
+ $this->data = [];
+ foreach ($this->instances as $instance) {
+ $instance->clearCalls();
+ }
+ }
+
+ public function lateCollect()
+ {
+ $this->data['instances']['calls'] = $this->cloneVar($this->data['instances']['calls']);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName(): string
+ {
+ return 'cache';
+ }
+
+ /**
+ * Method returns amount of logged Cache reads: "get" calls.
+ */
+ public function getStatistics(): array
+ {
+ return $this->data['instances']['statistics'];
+ }
+
+ /**
+ * Method returns the statistic totals.
+ */
+ public function getTotals(): array
+ {
+ return $this->data['total']['statistics'];
+ }
+
+ /**
+ * Method returns all logged Cache call objects.
+ *
+ * @return mixed
+ */
+ public function getCalls()
+ {
+ return $this->data['instances']['calls'];
+ }
+
+ private function calculateStatistics(): array
+ {
+ $statistics = [];
+ foreach ($this->data['instances']['calls'] as $name => $calls) {
+ $statistics[$name] = [
+ 'calls' => 0,
+ 'time' => 0,
+ 'reads' => 0,
+ 'writes' => 0,
+ 'deletes' => 0,
+ 'hits' => 0,
+ 'misses' => 0,
+ ];
+ /** @var TraceableAdapterEvent $call */
+ foreach ($calls as $call) {
+ ++$statistics[$name]['calls'];
+ $statistics[$name]['time'] += $call->end - $call->start;
+ if ('get' === $call->name) {
+ ++$statistics[$name]['reads'];
+ if ($call->hits) {
+ ++$statistics[$name]['hits'];
+ } else {
+ ++$statistics[$name]['misses'];
+ ++$statistics[$name]['writes'];
+ }
+ } elseif ('getItem' === $call->name) {
+ ++$statistics[$name]['reads'];
+ if ($call->hits) {
+ ++$statistics[$name]['hits'];
+ } else {
+ ++$statistics[$name]['misses'];
+ }
+ } elseif ('getItems' === $call->name) {
+ $statistics[$name]['reads'] += $call->hits + $call->misses;
+ $statistics[$name]['hits'] += $call->hits;
+ $statistics[$name]['misses'] += $call->misses;
+ } elseif ('hasItem' === $call->name) {
+ ++$statistics[$name]['reads'];
+ if (false === $call->result) {
+ ++$statistics[$name]['misses'];
+ } else {
+ ++$statistics[$name]['hits'];
+ }
+ } elseif ('save' === $call->name) {
+ ++$statistics[$name]['writes'];
+ } elseif ('deleteItem' === $call->name) {
+ ++$statistics[$name]['deletes'];
+ }
+ }
+ if ($statistics[$name]['reads']) {
+ $statistics[$name]['hit_read_ratio'] = round(100 * $statistics[$name]['hits'] / $statistics[$name]['reads'], 2);
+ } else {
+ $statistics[$name]['hit_read_ratio'] = null;
+ }
+ }
+
+ return $statistics;
+ }
+
+ private function calculateTotalStatistics(): array
+ {
+ $statistics = $this->getStatistics();
+ $totals = [
+ 'calls' => 0,
+ 'time' => 0,
+ 'reads' => 0,
+ 'writes' => 0,
+ 'deletes' => 0,
+ 'hits' => 0,
+ 'misses' => 0,
+ ];
+ foreach ($statistics as $name => $values) {
+ foreach ($totals as $key => $value) {
+ $totals[$key] += $statistics[$name][$key];
+ }
+ }
+ if ($totals['reads']) {
+ $totals['hit_read_ratio'] = round(100 * $totals['hits'] / $totals['reads'], 2);
+ } else {
+ $totals['hit_read_ratio'] = null;
+ }
+
+ return $totals;
+ }
+}
diff --git a/vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php b/vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php
new file mode 100644
index 0000000..843232e
--- /dev/null
+++ b/vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php
@@ -0,0 +1,94 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\DependencyInjection;
+
+use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface;
+use Symfony\Component\Cache\Adapter\TraceableAdapter;
+use Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Inject a data collector to all the cache services to be able to get detailed statistics.
+ *
+ * @author Tobias Nyholm
+ */
+class CacheCollectorPass implements CompilerPassInterface
+{
+ private $dataCollectorCacheId;
+ private $cachePoolTag;
+ private $cachePoolRecorderInnerSuffix;
+
+ public function __construct(string $dataCollectorCacheId = 'data_collector.cache', string $cachePoolTag = 'cache.pool', string $cachePoolRecorderInnerSuffix = '.recorder_inner')
+ {
+ if (0 < \func_num_args()) {
+ trigger_deprecation('symfony/cache', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
+ }
+
+ $this->dataCollectorCacheId = $dataCollectorCacheId;
+ $this->cachePoolTag = $cachePoolTag;
+ $this->cachePoolRecorderInnerSuffix = $cachePoolRecorderInnerSuffix;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition($this->dataCollectorCacheId)) {
+ return;
+ }
+
+ foreach ($container->findTaggedServiceIds($this->cachePoolTag) as $id => $attributes) {
+ $poolName = $attributes[0]['name'] ?? $id;
+
+ $this->addToCollector($id, $poolName, $container);
+ }
+ }
+
+ private function addToCollector(string $id, string $name, ContainerBuilder $container)
+ {
+ $definition = $container->getDefinition($id);
+ if ($definition->isAbstract()) {
+ return;
+ }
+
+ $collectorDefinition = $container->getDefinition($this->dataCollectorCacheId);
+ $recorder = new Definition(is_subclass_of($definition->getClass(), TagAwareAdapterInterface::class) ? TraceableTagAwareAdapter::class : TraceableAdapter::class);
+ $recorder->setTags($definition->getTags());
+ if (!$definition->isPublic() || !$definition->isPrivate()) {
+ $recorder->setPublic($definition->isPublic());
+ }
+ $recorder->setArguments([new Reference($innerId = $id.$this->cachePoolRecorderInnerSuffix)]);
+
+ foreach ($definition->getMethodCalls() as [$method, $args]) {
+ if ('setCallbackWrapper' !== $method || !$args[0] instanceof Definition || !($args[0]->getArguments()[2] ?? null) instanceof Definition) {
+ continue;
+ }
+ if ([new Reference($id), 'setCallbackWrapper'] == $args[0]->getArguments()[2]->getFactory()) {
+ $args[0]->getArguments()[2]->setFactory([new Reference($innerId), 'setCallbackWrapper']);
+ }
+ }
+
+ $definition->setTags([]);
+ $definition->setPublic(false);
+
+ $container->setDefinition($innerId, $definition);
+ $container->setDefinition($id, $recorder);
+
+ // Tell the collector to add the new instance
+ $collectorDefinition->addMethodCall('addInstance', [$name, new Reference($id)]);
+ $collectorDefinition->setPublic(false);
+ }
+}
diff --git a/vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php b/vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php
new file mode 100644
index 0000000..c9b04ad
--- /dev/null
+++ b/vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php
@@ -0,0 +1,52 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * @author Nicolas Grekas
+ */
+class CachePoolClearerPass implements CompilerPassInterface
+{
+ private $cachePoolClearerTag;
+
+ public function __construct(string $cachePoolClearerTag = 'cache.pool.clearer')
+ {
+ if (0 < \func_num_args()) {
+ trigger_deprecation('symfony/cache', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
+ }
+
+ $this->cachePoolClearerTag = $cachePoolClearerTag;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function process(ContainerBuilder $container)
+ {
+ $container->getParameterBag()->remove('cache.prefix.seed');
+
+ foreach ($container->findTaggedServiceIds($this->cachePoolClearerTag) as $id => $attr) {
+ $clearer = $container->getDefinition($id);
+ $pools = [];
+ foreach ($clearer->getArgument(0) as $name => $ref) {
+ if ($container->hasDefinition($ref)) {
+ $pools[$name] = new Reference($ref);
+ }
+ }
+ $clearer->replaceArgument(0, $pools);
+ }
+ }
+}
diff --git a/vendor/symfony/cache/DependencyInjection/CachePoolPass.php b/vendor/symfony/cache/DependencyInjection/CachePoolPass.php
new file mode 100644
index 0000000..14ac2bd
--- /dev/null
+++ b/vendor/symfony/cache/DependencyInjection/CachePoolPass.php
@@ -0,0 +1,274 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\DependencyInjection;
+
+use Symfony\Component\Cache\Adapter\AbstractAdapter;
+use Symfony\Component\Cache\Adapter\ArrayAdapter;
+use Symfony\Component\Cache\Adapter\ChainAdapter;
+use Symfony\Component\Cache\Adapter\NullAdapter;
+use Symfony\Component\Cache\Adapter\ParameterNormalizer;
+use Symfony\Component\Cache\Messenger\EarlyExpirationDispatcher;
+use Symfony\Component\DependencyInjection\ChildDefinition;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * @author Nicolas Grekas
+ */
+class CachePoolPass implements CompilerPassInterface
+{
+ private $cachePoolTag;
+ private $kernelResetTag;
+ private $cacheClearerId;
+ private $cachePoolClearerTag;
+ private $cacheSystemClearerId;
+ private $cacheSystemClearerTag;
+ private $reverseContainerId;
+ private $reversibleTag;
+ private $messageHandlerId;
+
+ public function __construct(string $cachePoolTag = 'cache.pool', string $kernelResetTag = 'kernel.reset', string $cacheClearerId = 'cache.global_clearer', string $cachePoolClearerTag = 'cache.pool.clearer', string $cacheSystemClearerId = 'cache.system_clearer', string $cacheSystemClearerTag = 'kernel.cache_clearer', string $reverseContainerId = 'reverse_container', string $reversibleTag = 'container.reversible', string $messageHandlerId = 'cache.early_expiration_handler')
+ {
+ if (0 < \func_num_args()) {
+ trigger_deprecation('symfony/cache', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
+ }
+
+ $this->cachePoolTag = $cachePoolTag;
+ $this->kernelResetTag = $kernelResetTag;
+ $this->cacheClearerId = $cacheClearerId;
+ $this->cachePoolClearerTag = $cachePoolClearerTag;
+ $this->cacheSystemClearerId = $cacheSystemClearerId;
+ $this->cacheSystemClearerTag = $cacheSystemClearerTag;
+ $this->reverseContainerId = $reverseContainerId;
+ $this->reversibleTag = $reversibleTag;
+ $this->messageHandlerId = $messageHandlerId;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function process(ContainerBuilder $container)
+ {
+ if ($container->hasParameter('cache.prefix.seed')) {
+ $seed = $container->getParameterBag()->resolveValue($container->getParameter('cache.prefix.seed'));
+ } else {
+ $seed = '_'.$container->getParameter('kernel.project_dir');
+ $seed .= '.'.$container->getParameter('kernel.container_class');
+ }
+
+ $needsMessageHandler = false;
+ $allPools = [];
+ $clearers = [];
+ $attributes = [
+ 'provider',
+ 'name',
+ 'namespace',
+ 'default_lifetime',
+ 'early_expiration_message_bus',
+ 'reset',
+ ];
+ foreach ($container->findTaggedServiceIds($this->cachePoolTag) as $id => $tags) {
+ $adapter = $pool = $container->getDefinition($id);
+ if ($pool->isAbstract()) {
+ continue;
+ }
+ $class = $adapter->getClass();
+ while ($adapter instanceof ChildDefinition) {
+ $adapter = $container->findDefinition($adapter->getParent());
+ $class = $class ?: $adapter->getClass();
+ if ($t = $adapter->getTag($this->cachePoolTag)) {
+ $tags[0] += $t[0];
+ }
+ }
+ $name = $tags[0]['name'] ?? $id;
+ if (!isset($tags[0]['namespace'])) {
+ $namespaceSeed = $seed;
+ if (null !== $class) {
+ $namespaceSeed .= '.'.$class;
+ }
+
+ $tags[0]['namespace'] = $this->getNamespace($namespaceSeed, $name);
+ }
+ if (isset($tags[0]['clearer'])) {
+ $clearer = $tags[0]['clearer'];
+ while ($container->hasAlias($clearer)) {
+ $clearer = (string) $container->getAlias($clearer);
+ }
+ } else {
+ $clearer = null;
+ }
+ unset($tags[0]['clearer'], $tags[0]['name']);
+
+ if (isset($tags[0]['provider'])) {
+ $tags[0]['provider'] = new Reference(static::getServiceProvider($container, $tags[0]['provider']));
+ }
+
+ if (ChainAdapter::class === $class) {
+ $adapters = [];
+ foreach ($adapter->getArgument(0) as $provider => $adapter) {
+ if ($adapter instanceof ChildDefinition) {
+ $chainedPool = $adapter;
+ } else {
+ $chainedPool = $adapter = new ChildDefinition($adapter);
+ }
+
+ $chainedTags = [\is_int($provider) ? [] : ['provider' => $provider]];
+ $chainedClass = '';
+
+ while ($adapter instanceof ChildDefinition) {
+ $adapter = $container->findDefinition($adapter->getParent());
+ $chainedClass = $chainedClass ?: $adapter->getClass();
+ if ($t = $adapter->getTag($this->cachePoolTag)) {
+ $chainedTags[0] += $t[0];
+ }
+ }
+
+ if (ChainAdapter::class === $chainedClass) {
+ throw new InvalidArgumentException(sprintf('Invalid service "%s": chain of adapters cannot reference another chain, found "%s".', $id, $chainedPool->getParent()));
+ }
+
+ $i = 0;
+
+ if (isset($chainedTags[0]['provider'])) {
+ $chainedPool->replaceArgument($i++, new Reference(static::getServiceProvider($container, $chainedTags[0]['provider'])));
+ }
+
+ if (isset($tags[0]['namespace']) && !\in_array($adapter->getClass(), [ArrayAdapter::class, NullAdapter::class], true)) {
+ $chainedPool->replaceArgument($i++, $tags[0]['namespace']);
+ }
+
+ if (isset($tags[0]['default_lifetime'])) {
+ $chainedPool->replaceArgument($i++, $tags[0]['default_lifetime']);
+ }
+
+ $adapters[] = $chainedPool;
+ }
+
+ $pool->replaceArgument(0, $adapters);
+ unset($tags[0]['provider'], $tags[0]['namespace']);
+ $i = 1;
+ } else {
+ $i = 0;
+ }
+
+ foreach ($attributes as $attr) {
+ if (!isset($tags[0][$attr])) {
+ // no-op
+ } elseif ('reset' === $attr) {
+ if ($tags[0][$attr]) {
+ $pool->addTag($this->kernelResetTag, ['method' => $tags[0][$attr]]);
+ }
+ } elseif ('early_expiration_message_bus' === $attr) {
+ $needsMessageHandler = true;
+ $pool->addMethodCall('setCallbackWrapper', [(new Definition(EarlyExpirationDispatcher::class))
+ ->addArgument(new Reference($tags[0]['early_expiration_message_bus']))
+ ->addArgument(new Reference($this->reverseContainerId))
+ ->addArgument((new Definition('callable'))
+ ->setFactory([new Reference($id), 'setCallbackWrapper'])
+ ->addArgument(null)
+ ),
+ ]);
+ $pool->addTag($this->reversibleTag);
+ } elseif ('namespace' !== $attr || !\in_array($class, [ArrayAdapter::class, NullAdapter::class], true)) {
+ $argument = $tags[0][$attr];
+
+ if ('default_lifetime' === $attr && !is_numeric($argument)) {
+ $argument = (new Definition('int', [$argument]))
+ ->setFactory([ParameterNormalizer::class, 'normalizeDuration']);
+ }
+
+ $pool->replaceArgument($i++, $argument);
+ }
+ unset($tags[0][$attr]);
+ }
+ if (!empty($tags[0])) {
+ throw new InvalidArgumentException(sprintf('Invalid "%s" tag for service "%s": accepted attributes are "clearer", "provider", "name", "namespace", "default_lifetime", "early_expiration_message_bus" and "reset", found "%s".', $this->cachePoolTag, $id, implode('", "', array_keys($tags[0]))));
+ }
+
+ if (null !== $clearer) {
+ $clearers[$clearer][$name] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE);
+ }
+
+ $allPools[$name] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE);
+ }
+
+ if (!$needsMessageHandler) {
+ $container->removeDefinition($this->messageHandlerId);
+ }
+
+ $notAliasedCacheClearerId = $this->cacheClearerId;
+ while ($container->hasAlias($this->cacheClearerId)) {
+ $this->cacheClearerId = (string) $container->getAlias($this->cacheClearerId);
+ }
+ if ($container->hasDefinition($this->cacheClearerId)) {
+ $clearers[$notAliasedCacheClearerId] = $allPools;
+ }
+
+ foreach ($clearers as $id => $pools) {
+ $clearer = $container->getDefinition($id);
+ if ($clearer instanceof ChildDefinition) {
+ $clearer->replaceArgument(0, $pools);
+ } else {
+ $clearer->setArgument(0, $pools);
+ }
+ $clearer->addTag($this->cachePoolClearerTag);
+
+ if ($this->cacheSystemClearerId === $id) {
+ $clearer->addTag($this->cacheSystemClearerTag);
+ }
+ }
+
+ $allPoolsKeys = array_keys($allPools);
+
+ if ($container->hasDefinition('console.command.cache_pool_list')) {
+ $container->getDefinition('console.command.cache_pool_list')->replaceArgument(0, $allPoolsKeys);
+ }
+
+ if ($container->hasDefinition('console.command.cache_pool_clear')) {
+ $container->getDefinition('console.command.cache_pool_clear')->addArgument($allPoolsKeys);
+ }
+
+ if ($container->hasDefinition('console.command.cache_pool_delete')) {
+ $container->getDefinition('console.command.cache_pool_delete')->addArgument($allPoolsKeys);
+ }
+ }
+
+ private function getNamespace(string $seed, string $id)
+ {
+ return substr(str_replace('/', '-', base64_encode(hash('sha256', $id.$seed, true))), 0, 10);
+ }
+
+ /**
+ * @internal
+ */
+ public static function getServiceProvider(ContainerBuilder $container, string $name)
+ {
+ $container->resolveEnvPlaceholders($name, null, $usedEnvs);
+
+ if ($usedEnvs || preg_match('#^[a-z]++:#', $name)) {
+ $dsn = $name;
+
+ if (!$container->hasDefinition($name = '.cache_connection.'.ContainerBuilder::hash($dsn))) {
+ $definition = new Definition(AbstractAdapter::class);
+ $definition->setPublic(false);
+ $definition->setFactory([AbstractAdapter::class, 'createConnection']);
+ $definition->setArguments([$dsn, ['lazy' => true]]);
+ $container->setDefinition($name, $definition);
+ }
+ }
+
+ return $name;
+ }
+}
diff --git a/vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php b/vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php
new file mode 100644
index 0000000..86a1906
--- /dev/null
+++ b/vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php
@@ -0,0 +1,64 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\DependencyInjection;
+
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * @author Rob Frawley 2nd
+ */
+class CachePoolPrunerPass implements CompilerPassInterface
+{
+ private $cacheCommandServiceId;
+ private $cachePoolTag;
+
+ public function __construct(string $cacheCommandServiceId = 'console.command.cache_pool_prune', string $cachePoolTag = 'cache.pool')
+ {
+ if (0 < \func_num_args()) {
+ trigger_deprecation('symfony/cache', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
+ }
+
+ $this->cacheCommandServiceId = $cacheCommandServiceId;
+ $this->cachePoolTag = $cachePoolTag;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition($this->cacheCommandServiceId)) {
+ return;
+ }
+
+ $services = [];
+
+ foreach ($container->findTaggedServiceIds($this->cachePoolTag) as $id => $tags) {
+ $class = $container->getParameterBag()->resolveValue($container->getDefinition($id)->getClass());
+
+ if (!$reflection = $container->getReflectionClass($class)) {
+ throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
+ }
+
+ if ($reflection->implementsInterface(PruneableInterface::class)) {
+ $services[$id] = new Reference($id);
+ }
+ }
+
+ $container->getDefinition($this->cacheCommandServiceId)->replaceArgument(0, new IteratorArgument($services));
+ }
+}
diff --git a/vendor/symfony/cache/DoctrineProvider.php b/vendor/symfony/cache/DoctrineProvider.php
new file mode 100644
index 0000000..7b55aae
--- /dev/null
+++ b/vendor/symfony/cache/DoctrineProvider.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;
+
+use Doctrine\Common\Cache\CacheProvider;
+use Psr\Cache\CacheItemPoolInterface;
+use Symfony\Contracts\Service\ResetInterface;
+
+if (!class_exists(CacheProvider::class)) {
+ return;
+}
+
+/**
+ * @author Nicolas Grekas
+ *
+ * @deprecated Use Doctrine\Common\Cache\Psr6\DoctrineProvider instead
+ */
+class DoctrineProvider extends CacheProvider implements PruneableInterface, ResettableInterface
+{
+ private $pool;
+
+ public function __construct(CacheItemPoolInterface $pool)
+ {
+ trigger_deprecation('symfony/cache', '5.4', '"%s" is deprecated, use "Doctrine\Common\Cache\Psr6\DoctrineProvider" instead.', __CLASS__);
+
+ $this->pool = $pool;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function prune()
+ {
+ return $this->pool instanceof PruneableInterface && $this->pool->prune();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function reset()
+ {
+ if ($this->pool instanceof ResetInterface) {
+ $this->pool->reset();
+ }
+ $this->setNamespace($this->getNamespace());
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return mixed
+ */
+ protected function doFetch($id)
+ {
+ $item = $this->pool->getItem(rawurlencode($id));
+
+ return $item->isHit() ? $item->get() : false;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ protected function doContains($id)
+ {
+ return $this->pool->hasItem(rawurlencode($id));
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ protected function doSave($id, $data, $lifeTime = 0)
+ {
+ $item = $this->pool->getItem(rawurlencode($id));
+
+ if (0 < $lifeTime) {
+ $item->expiresAfter($lifeTime);
+ }
+
+ return $this->pool->save($item->set($data));
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ protected function doDelete($id)
+ {
+ return $this->pool->deleteItem(rawurlencode($id));
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ protected function doFlush()
+ {
+ return $this->pool->clear();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return array|null
+ */
+ protected function doGetStats()
+ {
+ return null;
+ }
+}
diff --git a/vendor/symfony/cache/Exception/CacheException.php b/vendor/symfony/cache/Exception/CacheException.php
new file mode 100644
index 0000000..d2e975b
--- /dev/null
+++ b/vendor/symfony/cache/Exception/CacheException.php
@@ -0,0 +1,25 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Exception;
+
+use Psr\Cache\CacheException as Psr6CacheInterface;
+use Psr\SimpleCache\CacheException as SimpleCacheInterface;
+
+if (interface_exists(SimpleCacheInterface::class)) {
+ class CacheException extends \Exception implements Psr6CacheInterface, SimpleCacheInterface
+ {
+ }
+} else {
+ class CacheException extends \Exception implements Psr6CacheInterface
+ {
+ }
+}
diff --git a/vendor/symfony/cache/Exception/InvalidArgumentException.php b/vendor/symfony/cache/Exception/InvalidArgumentException.php
new file mode 100644
index 0000000..7f9584a
--- /dev/null
+++ b/vendor/symfony/cache/Exception/InvalidArgumentException.php
@@ -0,0 +1,25 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Exception;
+
+use Psr\Cache\InvalidArgumentException as Psr6CacheInterface;
+use Psr\SimpleCache\InvalidArgumentException as SimpleCacheInterface;
+
+if (interface_exists(SimpleCacheInterface::class)) {
+ class InvalidArgumentException extends \InvalidArgumentException implements Psr6CacheInterface, SimpleCacheInterface
+ {
+ }
+} else {
+ class InvalidArgumentException extends \InvalidArgumentException implements Psr6CacheInterface
+ {
+ }
+}
diff --git a/vendor/symfony/cache/Exception/LogicException.php b/vendor/symfony/cache/Exception/LogicException.php
new file mode 100644
index 0000000..9ffa7ed
--- /dev/null
+++ b/vendor/symfony/cache/Exception/LogicException.php
@@ -0,0 +1,25 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Exception;
+
+use Psr\Cache\CacheException as Psr6CacheInterface;
+use Psr\SimpleCache\CacheException as SimpleCacheInterface;
+
+if (interface_exists(SimpleCacheInterface::class)) {
+ class LogicException extends \LogicException implements Psr6CacheInterface, SimpleCacheInterface
+ {
+ }
+} else {
+ class LogicException extends \LogicException implements Psr6CacheInterface
+ {
+ }
+}
diff --git a/vendor/symfony/cache/LICENSE b/vendor/symfony/cache/LICENSE
new file mode 100644
index 0000000..7fa9539
--- /dev/null
+++ b/vendor/symfony/cache/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2016-2022 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/symfony/cache/LockRegistry.php b/vendor/symfony/cache/LockRegistry.php
new file mode 100644
index 0000000..65f20bb
--- /dev/null
+++ b/vendor/symfony/cache/LockRegistry.php
@@ -0,0 +1,165 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache;
+
+use Psr\Log\LoggerInterface;
+use Symfony\Contracts\Cache\CacheInterface;
+use Symfony\Contracts\Cache\ItemInterface;
+
+/**
+ * LockRegistry is used internally by existing adapters to protect against cache stampede.
+ *
+ * It does so by wrapping the computation of items in a pool of locks.
+ * Foreach each apps, there can be at most 20 concurrent processes that
+ * compute items at the same time and only one per cache-key.
+ *
+ * @author Nicolas Grekas
+ */
+final class LockRegistry
+{
+ private static $openedFiles = [];
+ private static $lockedFiles;
+ private static $signalingException;
+ private static $signalingCallback;
+
+ /**
+ * The number of items in this list controls the max number of concurrent processes.
+ */
+ private static $files = [
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'AbstractAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'AbstractTagAwareAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'AdapterInterface.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ApcuAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ArrayAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ChainAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'CouchbaseBucketAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'CouchbaseCollectionAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'DoctrineAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'DoctrineDbalAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'FilesystemAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'FilesystemTagAwareAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'MemcachedAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'NullAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ParameterNormalizer.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'PdoAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'PhpArrayAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'PhpFilesAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ProxyAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'Psr16Adapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'RedisAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'RedisTagAwareAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TagAwareAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TagAwareAdapterInterface.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TraceableAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TraceableTagAwareAdapter.php',
+ ];
+
+ /**
+ * Defines a set of existing files that will be used as keys to acquire locks.
+ *
+ * @return array The previously defined set of files
+ */
+ public static function setFiles(array $files): array
+ {
+ $previousFiles = self::$files;
+ self::$files = $files;
+
+ foreach (self::$openedFiles as $file) {
+ if ($file) {
+ flock($file, \LOCK_UN);
+ fclose($file);
+ }
+ }
+ self::$openedFiles = self::$lockedFiles = [];
+
+ return $previousFiles;
+ }
+
+ public static function compute(callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata = null, LoggerInterface $logger = null)
+ {
+ if ('\\' === \DIRECTORY_SEPARATOR && null === self::$lockedFiles) {
+ // disable locking on Windows by default
+ self::$files = self::$lockedFiles = [];
+ }
+
+ $key = self::$files ? abs(crc32($item->getKey())) % \count(self::$files) : -1;
+
+ if ($key < 0 || self::$lockedFiles || !$lock = self::open($key)) {
+ return $callback($item, $save);
+ }
+
+ self::$signalingException ?? self::$signalingException = unserialize("O:9:\"Exception\":1:{s:16:\"\0Exception\0trace\";a:0:{}}");
+ self::$signalingCallback ?? self::$signalingCallback = function () { throw self::$signalingException; };
+
+ while (true) {
+ try {
+ $locked = false;
+ // race to get the lock in non-blocking mode
+ $locked = flock($lock, \LOCK_EX | \LOCK_NB, $wouldBlock);
+
+ if ($locked || !$wouldBlock) {
+ $logger && $logger->info(sprintf('Lock %s, now computing item "{key}"', $locked ? 'acquired' : 'not supported'), ['key' => $item->getKey()]);
+ self::$lockedFiles[$key] = true;
+
+ $value = $callback($item, $save);
+
+ if ($save) {
+ if ($setMetadata) {
+ $setMetadata($item);
+ }
+
+ $pool->save($item->set($value));
+ $save = false;
+ }
+
+ return $value;
+ }
+ // if we failed the race, retry locking in blocking mode to wait for the winner
+ $logger && $logger->info('Item "{key}" is locked, waiting for it to be released', ['key' => $item->getKey()]);
+ flock($lock, \LOCK_SH);
+ } finally {
+ flock($lock, \LOCK_UN);
+ unset(self::$lockedFiles[$key]);
+ }
+
+ try {
+ $value = $pool->get($item->getKey(), self::$signalingCallback, 0);
+ $logger && $logger->info('Item "{key}" retrieved after lock was released', ['key' => $item->getKey()]);
+ $save = false;
+
+ return $value;
+ } catch (\Exception $e) {
+ if (self::$signalingException !== $e) {
+ throw $e;
+ }
+ $logger && $logger->info('Item "{key}" not found while lock was released, now retrying', ['key' => $item->getKey()]);
+ }
+ }
+
+ return null;
+ }
+
+ private static function open(int $key)
+ {
+ if (null !== $h = self::$openedFiles[$key] ?? null) {
+ return $h;
+ }
+ set_error_handler(function () {});
+ try {
+ $h = fopen(self::$files[$key], 'r+');
+ } finally {
+ restore_error_handler();
+ }
+
+ return self::$openedFiles[$key] = $h ?: @fopen(self::$files[$key], 'r');
+ }
+}
diff --git a/vendor/symfony/cache/Marshaller/DefaultMarshaller.php b/vendor/symfony/cache/Marshaller/DefaultMarshaller.php
new file mode 100644
index 0000000..3202dd6
--- /dev/null
+++ b/vendor/symfony/cache/Marshaller/DefaultMarshaller.php
@@ -0,0 +1,104 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Marshaller;
+
+use Symfony\Component\Cache\Exception\CacheException;
+
+/**
+ * Serializes/unserializes values using igbinary_serialize() if available, serialize() otherwise.
+ *
+ * @author Nicolas Grekas
+ */
+class DefaultMarshaller implements MarshallerInterface
+{
+ private $useIgbinarySerialize = true;
+ private $throwOnSerializationFailure;
+
+ public function __construct(bool $useIgbinarySerialize = null, bool $throwOnSerializationFailure = false)
+ {
+ if (null === $useIgbinarySerialize) {
+ $useIgbinarySerialize = \extension_loaded('igbinary') && (\PHP_VERSION_ID < 70400 || version_compare('3.1.6', phpversion('igbinary'), '<='));
+ } elseif ($useIgbinarySerialize && (!\extension_loaded('igbinary') || (\PHP_VERSION_ID >= 70400 && version_compare('3.1.6', phpversion('igbinary'), '>')))) {
+ throw new CacheException(\extension_loaded('igbinary') && \PHP_VERSION_ID >= 70400 ? 'Please upgrade the "igbinary" PHP extension to v3.1.6 or higher.' : 'The "igbinary" PHP extension is not loaded.');
+ }
+ $this->useIgbinarySerialize = $useIgbinarySerialize;
+ $this->throwOnSerializationFailure = $throwOnSerializationFailure;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function marshall(array $values, ?array &$failed): array
+ {
+ $serialized = $failed = [];
+
+ foreach ($values as $id => $value) {
+ try {
+ if ($this->useIgbinarySerialize) {
+ $serialized[$id] = igbinary_serialize($value);
+ } else {
+ $serialized[$id] = serialize($value);
+ }
+ } catch (\Exception $e) {
+ if ($this->throwOnSerializationFailure) {
+ throw new \ValueError($e->getMessage(), 0, $e);
+ }
+ $failed[] = $id;
+ }
+ }
+
+ return $serialized;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function unmarshall(string $value)
+ {
+ if ('b:0;' === $value) {
+ return false;
+ }
+ if ('N;' === $value) {
+ return null;
+ }
+ static $igbinaryNull;
+ if ($value === ($igbinaryNull ?? $igbinaryNull = \extension_loaded('igbinary') ? igbinary_serialize(null) : false)) {
+ return null;
+ }
+ $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
+ try {
+ if (':' === ($value[1] ?? ':')) {
+ if (false !== $value = unserialize($value)) {
+ return $value;
+ }
+ } elseif (false === $igbinaryNull) {
+ throw new \RuntimeException('Failed to unserialize values, did you forget to install the "igbinary" extension?');
+ } elseif (null !== $value = igbinary_unserialize($value)) {
+ return $value;
+ }
+
+ throw new \DomainException(error_get_last() ? error_get_last()['message'] : 'Failed to unserialize values.');
+ } catch (\Error $e) {
+ throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine());
+ } finally {
+ ini_set('unserialize_callback_func', $unserializeCallbackHandler);
+ }
+ }
+
+ /**
+ * @internal
+ */
+ public static function handleUnserializeCallback(string $class)
+ {
+ throw new \DomainException('Class not found: '.$class);
+ }
+}
diff --git a/vendor/symfony/cache/Marshaller/DeflateMarshaller.php b/vendor/symfony/cache/Marshaller/DeflateMarshaller.php
new file mode 100644
index 0000000..5544806
--- /dev/null
+++ b/vendor/symfony/cache/Marshaller/DeflateMarshaller.php
@@ -0,0 +1,53 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Marshaller;
+
+use Symfony\Component\Cache\Exception\CacheException;
+
+/**
+ * Compresses values using gzdeflate().
+ *
+ * @author Nicolas Grekas
+ */
+class DeflateMarshaller implements MarshallerInterface
+{
+ private $marshaller;
+
+ public function __construct(MarshallerInterface $marshaller)
+ {
+ if (!\function_exists('gzdeflate')) {
+ throw new CacheException('The "zlib" PHP extension is not loaded.');
+ }
+
+ $this->marshaller = $marshaller;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function marshall(array $values, ?array &$failed): array
+ {
+ return array_map('gzdeflate', $this->marshaller->marshall($values, $failed));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function unmarshall(string $value)
+ {
+ if (false !== $inflatedValue = @gzinflate($value)) {
+ $value = $inflatedValue;
+ }
+
+ return $this->marshaller->unmarshall($value);
+ }
+}
diff --git a/vendor/symfony/cache/Marshaller/MarshallerInterface.php b/vendor/symfony/cache/Marshaller/MarshallerInterface.php
new file mode 100644
index 0000000..cdd6c40
--- /dev/null
+++ b/vendor/symfony/cache/Marshaller/MarshallerInterface.php
@@ -0,0 +1,40 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Marshaller;
+
+/**
+ * Serializes/unserializes PHP values.
+ *
+ * Implementations of this interface MUST deal with errors carefully. They MUST
+ * also deal with forward and backward compatibility at the storage format level.
+ *
+ * @author Nicolas Grekas
+ */
+interface MarshallerInterface
+{
+ /**
+ * Serializes a list of values.
+ *
+ * When serialization fails for a specific value, no exception should be
+ * thrown. Instead, its key should be listed in $failed.
+ */
+ public function marshall(array $values, ?array &$failed): array;
+
+ /**
+ * Unserializes a single value and throws an exception if anything goes wrong.
+ *
+ * @return mixed
+ *
+ * @throws \Exception Whenever unserialization fails
+ */
+ public function unmarshall(string $value);
+}
diff --git a/vendor/symfony/cache/Marshaller/SodiumMarshaller.php b/vendor/symfony/cache/Marshaller/SodiumMarshaller.php
new file mode 100644
index 0000000..dbf486a
--- /dev/null
+++ b/vendor/symfony/cache/Marshaller/SodiumMarshaller.php
@@ -0,0 +1,80 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Marshaller;
+
+use Symfony\Component\Cache\Exception\CacheException;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+
+/**
+ * Encrypt/decrypt values using Libsodium.
+ *
+ * @author Ahmed TAILOULOUTE
+ */
+class SodiumMarshaller implements MarshallerInterface
+{
+ private $marshaller;
+ private $decryptionKeys;
+
+ /**
+ * @param string[] $decryptionKeys The key at index "0" is required and is used to decrypt and encrypt values;
+ * more rotating keys can be provided to decrypt values;
+ * each key must be generated using sodium_crypto_box_keypair()
+ */
+ public function __construct(array $decryptionKeys, MarshallerInterface $marshaller = null)
+ {
+ if (!self::isSupported()) {
+ throw new CacheException('The "sodium" PHP extension is not loaded.');
+ }
+
+ if (!isset($decryptionKeys[0])) {
+ throw new InvalidArgumentException('At least one decryption key must be provided at index "0".');
+ }
+
+ $this->marshaller = $marshaller ?? new DefaultMarshaller();
+ $this->decryptionKeys = $decryptionKeys;
+ }
+
+ public static function isSupported(): bool
+ {
+ return \function_exists('sodium_crypto_box_seal');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function marshall(array $values, ?array &$failed): array
+ {
+ $encryptionKey = sodium_crypto_box_publickey($this->decryptionKeys[0]);
+
+ $encryptedValues = [];
+ foreach ($this->marshaller->marshall($values, $failed) as $k => $v) {
+ $encryptedValues[$k] = sodium_crypto_box_seal($v, $encryptionKey);
+ }
+
+ return $encryptedValues;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function unmarshall(string $value)
+ {
+ foreach ($this->decryptionKeys as $k) {
+ if (false !== $decryptedValue = @sodium_crypto_box_seal_open($value, $k)) {
+ $value = $decryptedValue;
+ break;
+ }
+ }
+
+ return $this->marshaller->unmarshall($value);
+ }
+}
diff --git a/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php b/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php
new file mode 100644
index 0000000..5d1e303
--- /dev/null
+++ b/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php
@@ -0,0 +1,89 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Marshaller;
+
+/**
+ * A marshaller optimized for data structures generated by AbstractTagAwareAdapter.
+ *
+ * @author Nicolas Grekas
+ */
+class TagAwareMarshaller implements MarshallerInterface
+{
+ private $marshaller;
+
+ public function __construct(MarshallerInterface $marshaller = null)
+ {
+ $this->marshaller = $marshaller ?? new DefaultMarshaller();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function marshall(array $values, ?array &$failed): array
+ {
+ $failed = $notSerialized = $serialized = [];
+
+ foreach ($values as $id => $value) {
+ if (\is_array($value) && \is_array($value['tags'] ?? null) && \array_key_exists('value', $value) && \count($value) === 2 + (\is_string($value['meta'] ?? null) && 8 === \strlen($value['meta']))) {
+ // if the value is an array with keys "tags", "value" and "meta", use a compact serialization format
+ // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F allow detecting this format quickly in unmarshall()
+
+ $v = $this->marshaller->marshall($value, $f);
+
+ if ($f) {
+ $f = [];
+ $failed[] = $id;
+ } else {
+ if ([] === $value['tags']) {
+ $v['tags'] = '';
+ }
+
+ $serialized[$id] = "\x9D".($value['meta'] ?? "\0\0\0\0\0\0\0\0").pack('N', \strlen($v['tags'])).$v['tags'].$v['value'];
+ $serialized[$id][9] = "\x5F";
+ }
+ } else {
+ // other arbitratry values are serialized using the decorated marshaller below
+ $notSerialized[$id] = $value;
+ }
+ }
+
+ if ($notSerialized) {
+ $serialized += $this->marshaller->marshall($notSerialized, $f);
+ $failed = array_merge($failed, $f);
+ }
+
+ return $serialized;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function unmarshall(string $value)
+ {
+ // detect the compact format used in marshall() using magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F
+ if (13 >= \strlen($value) || "\x9D" !== $value[0] || "\0" !== $value[5] || "\x5F" !== $value[9]) {
+ return $this->marshaller->unmarshall($value);
+ }
+
+ // data consists of value, tags and metadata which we need to unpack
+ $meta = substr($value, 1, 12);
+ $meta[8] = "\0";
+ $tagLen = unpack('Nlen', $meta, 8)['len'];
+ $meta = substr($meta, 0, 8);
+
+ return [
+ 'value' => $this->marshaller->unmarshall(substr($value, 13 + $tagLen)),
+ 'tags' => $tagLen ? $this->marshaller->unmarshall(substr($value, 13, $tagLen)) : [],
+ 'meta' => "\0\0\0\0\0\0\0\0" === $meta ? null : $meta,
+ ];
+ }
+}
diff --git a/vendor/symfony/cache/Messenger/EarlyExpirationDispatcher.php b/vendor/symfony/cache/Messenger/EarlyExpirationDispatcher.php
new file mode 100644
index 0000000..6f11b8b
--- /dev/null
+++ b/vendor/symfony/cache/Messenger/EarlyExpirationDispatcher.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\Messenger;
+
+use Psr\Log\LoggerInterface;
+use Symfony\Component\Cache\Adapter\AdapterInterface;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\DependencyInjection\ReverseContainer;
+use Symfony\Component\Messenger\MessageBusInterface;
+use Symfony\Component\Messenger\Stamp\HandledStamp;
+
+/**
+ * Sends the computation of cached values to a message bus.
+ */
+class EarlyExpirationDispatcher
+{
+ private $bus;
+ private $reverseContainer;
+ private $callbackWrapper;
+
+ public function __construct(MessageBusInterface $bus, ReverseContainer $reverseContainer, callable $callbackWrapper = null)
+ {
+ $this->bus = $bus;
+ $this->reverseContainer = $reverseContainer;
+ $this->callbackWrapper = $callbackWrapper;
+ }
+
+ public function __invoke(callable $callback, CacheItem $item, bool &$save, AdapterInterface $pool, \Closure $setMetadata, LoggerInterface $logger = null)
+ {
+ if (!$item->isHit() || null === $message = EarlyExpirationMessage::create($this->reverseContainer, $callback, $item, $pool)) {
+ // The item is stale or the callback cannot be reversed: we must compute the value now
+ $logger && $logger->info('Computing item "{key}" online: '.($item->isHit() ? 'callback cannot be reversed' : 'item is stale'), ['key' => $item->getKey()]);
+
+ return null !== $this->callbackWrapper ? ($this->callbackWrapper)($callback, $item, $save, $pool, $setMetadata, $logger) : $callback($item, $save);
+ }
+
+ $envelope = $this->bus->dispatch($message);
+
+ if ($logger) {
+ if ($envelope->last(HandledStamp::class)) {
+ $logger->info('Item "{key}" was computed online', ['key' => $item->getKey()]);
+ } else {
+ $logger->info('Item "{key}" sent for recomputation', ['key' => $item->getKey()]);
+ }
+ }
+
+ // The item's value is not stale, no need to write it to the backend
+ $save = false;
+
+ return $message->getItem()->get() ?? $item->get();
+ }
+}
diff --git a/vendor/symfony/cache/Messenger/EarlyExpirationHandler.php b/vendor/symfony/cache/Messenger/EarlyExpirationHandler.php
new file mode 100644
index 0000000..1f0bd56
--- /dev/null
+++ b/vendor/symfony/cache/Messenger/EarlyExpirationHandler.php
@@ -0,0 +1,80 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Messenger;
+
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\DependencyInjection\ReverseContainer;
+use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
+
+/**
+ * Computes cached values sent to a message bus.
+ */
+class EarlyExpirationHandler implements MessageHandlerInterface
+{
+ private $reverseContainer;
+ private $processedNonces = [];
+
+ public function __construct(ReverseContainer $reverseContainer)
+ {
+ $this->reverseContainer = $reverseContainer;
+ }
+
+ public function __invoke(EarlyExpirationMessage $message)
+ {
+ $item = $message->getItem();
+ $metadata = $item->getMetadata();
+ $expiry = $metadata[CacheItem::METADATA_EXPIRY] ?? 0;
+ $ctime = $metadata[CacheItem::METADATA_CTIME] ?? 0;
+
+ if ($expiry && $ctime) {
+ // skip duplicate or expired messages
+
+ $processingNonce = [$expiry, $ctime];
+ $pool = $message->getPool();
+ $key = $item->getKey();
+
+ if (($this->processedNonces[$pool][$key] ?? null) === $processingNonce) {
+ return;
+ }
+
+ if (microtime(true) >= $expiry) {
+ return;
+ }
+
+ $this->processedNonces[$pool] = [$key => $processingNonce] + ($this->processedNonces[$pool] ?? []);
+
+ if (\count($this->processedNonces[$pool]) > 100) {
+ array_pop($this->processedNonces[$pool]);
+ }
+ }
+
+ static $setMetadata;
+
+ $setMetadata ?? $setMetadata = \Closure::bind(
+ function (CacheItem $item, float $startTime) {
+ if ($item->expiry > $endTime = microtime(true)) {
+ $item->newMetadata[CacheItem::METADATA_EXPIRY] = $item->expiry;
+ $item->newMetadata[CacheItem::METADATA_CTIME] = (int) ceil(1000 * ($endTime - $startTime));
+ }
+ },
+ null,
+ CacheItem::class
+ );
+
+ $startTime = microtime(true);
+ $pool = $message->findPool($this->reverseContainer);
+ $callback = $message->findCallback($this->reverseContainer);
+ $value = $callback($item);
+ $setMetadata($item, $startTime);
+ $pool->save($item->set($value));
+ }
+}
diff --git a/vendor/symfony/cache/Messenger/EarlyExpirationMessage.php b/vendor/symfony/cache/Messenger/EarlyExpirationMessage.php
new file mode 100644
index 0000000..e25c07e
--- /dev/null
+++ b/vendor/symfony/cache/Messenger/EarlyExpirationMessage.php
@@ -0,0 +1,97 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Messenger;
+
+use Symfony\Component\Cache\Adapter\AdapterInterface;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\DependencyInjection\ReverseContainer;
+
+/**
+ * Conveys a cached value that needs to be computed.
+ */
+final class EarlyExpirationMessage
+{
+ private $item;
+ private $pool;
+ private $callback;
+
+ public static function create(ReverseContainer $reverseContainer, callable $callback, CacheItem $item, AdapterInterface $pool): ?self
+ {
+ try {
+ $item = clone $item;
+ $item->set(null);
+ } catch (\Exception $e) {
+ return null;
+ }
+
+ $pool = $reverseContainer->getId($pool);
+
+ if (\is_object($callback)) {
+ if (null === $id = $reverseContainer->getId($callback)) {
+ return null;
+ }
+
+ $callback = '@'.$id;
+ } elseif (!\is_array($callback)) {
+ $callback = (string) $callback;
+ } elseif (!\is_object($callback[0])) {
+ $callback = [(string) $callback[0], (string) $callback[1]];
+ } else {
+ if (null === $id = $reverseContainer->getId($callback[0])) {
+ return null;
+ }
+
+ $callback = ['@'.$id, (string) $callback[1]];
+ }
+
+ return new self($item, $pool, $callback);
+ }
+
+ public function getItem(): CacheItem
+ {
+ return $this->item;
+ }
+
+ public function getPool(): string
+ {
+ return $this->pool;
+ }
+
+ public function getCallback()
+ {
+ return $this->callback;
+ }
+
+ public function findPool(ReverseContainer $reverseContainer): AdapterInterface
+ {
+ return $reverseContainer->getService($this->pool);
+ }
+
+ public function findCallback(ReverseContainer $reverseContainer): callable
+ {
+ if (\is_string($callback = $this->callback)) {
+ return '@' === $callback[0] ? $reverseContainer->getService(substr($callback, 1)) : $callback;
+ }
+ if ('@' === $callback[0][0]) {
+ $callback[0] = $reverseContainer->getService(substr($callback[0], 1));
+ }
+
+ return $callback;
+ }
+
+ private function __construct(CacheItem $item, string $pool, $callback)
+ {
+ $this->item = $item;
+ $this->pool = $pool;
+ $this->callback = $callback;
+ }
+}
diff --git a/vendor/symfony/cache/PruneableInterface.php b/vendor/symfony/cache/PruneableInterface.php
new file mode 100644
index 0000000..4261525
--- /dev/null
+++ b/vendor/symfony/cache/PruneableInterface.php
@@ -0,0 +1,23 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache;
+
+/**
+ * Interface extends psr-6 and psr-16 caches to allow for pruning (deletion) of all expired cache items.
+ */
+interface PruneableInterface
+{
+ /**
+ * @return bool
+ */
+ public function prune();
+}
diff --git a/vendor/symfony/cache/Psr16Cache.php b/vendor/symfony/cache/Psr16Cache.php
new file mode 100644
index 0000000..28c7de6
--- /dev/null
+++ b/vendor/symfony/cache/Psr16Cache.php
@@ -0,0 +1,289 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache;
+
+use Psr\Cache\CacheException as Psr6CacheException;
+use Psr\Cache\CacheItemPoolInterface;
+use Psr\SimpleCache\CacheException as SimpleCacheException;
+use Psr\SimpleCache\CacheInterface;
+use Symfony\Component\Cache\Adapter\AdapterInterface;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\Traits\ProxyTrait;
+
+if (null !== (new \ReflectionMethod(CacheInterface::class, 'get'))->getReturnType()) {
+ throw new \LogicException('psr/simple-cache 3.0+ is not compatible with this version of symfony/cache. Please upgrade symfony/cache to 6.0+ or downgrade psr/simple-cache to 1.x or 2.x.');
+}
+
+/**
+ * Turns a PSR-6 cache into a PSR-16 one.
+ *
+ * @author Nicolas Grekas
+ */
+class Psr16Cache implements CacheInterface, PruneableInterface, ResettableInterface
+{
+ use ProxyTrait;
+
+ private const METADATA_EXPIRY_OFFSET = 1527506807;
+
+ private $createCacheItem;
+ private $cacheItemPrototype;
+
+ public function __construct(CacheItemPoolInterface $pool)
+ {
+ $this->pool = $pool;
+
+ if (!$pool instanceof AdapterInterface) {
+ return;
+ }
+ $cacheItemPrototype = &$this->cacheItemPrototype;
+ $createCacheItem = \Closure::bind(
+ static function ($key, $value, $allowInt = false) use (&$cacheItemPrototype) {
+ $item = clone $cacheItemPrototype;
+ $item->poolHash = $item->innerItem = null;
+ if ($allowInt && \is_int($key)) {
+ $item->key = (string) $key;
+ } else {
+ \assert('' !== CacheItem::validateKey($key));
+ $item->key = $key;
+ }
+ $item->value = $value;
+ $item->isHit = false;
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ $this->createCacheItem = function ($key, $value, $allowInt = false) use ($createCacheItem) {
+ if (null === $this->cacheItemPrototype) {
+ $this->get($allowInt && \is_int($key) ? (string) $key : $key);
+ }
+ $this->createCacheItem = $createCacheItem;
+
+ return $createCacheItem($key, null, $allowInt)->set($value);
+ };
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return mixed
+ */
+ public function get($key, $default = null)
+ {
+ try {
+ $item = $this->pool->getItem($key);
+ } catch (SimpleCacheException $e) {
+ throw $e;
+ } catch (Psr6CacheException $e) {
+ throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
+ }
+ if (null === $this->cacheItemPrototype) {
+ $this->cacheItemPrototype = clone $item;
+ $this->cacheItemPrototype->set(null);
+ }
+
+ return $item->isHit() ? $item->get() : $default;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function set($key, $value, $ttl = null)
+ {
+ try {
+ if (null !== $f = $this->createCacheItem) {
+ $item = $f($key, $value);
+ } else {
+ $item = $this->pool->getItem($key)->set($value);
+ }
+ } catch (SimpleCacheException $e) {
+ throw $e;
+ } catch (Psr6CacheException $e) {
+ throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
+ }
+ if (null !== $ttl) {
+ $item->expiresAfter($ttl);
+ }
+
+ return $this->pool->save($item);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function delete($key)
+ {
+ try {
+ return $this->pool->deleteItem($key);
+ } catch (SimpleCacheException $e) {
+ throw $e;
+ } catch (Psr6CacheException $e) {
+ throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function clear()
+ {
+ return $this->pool->clear();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return iterable
+ */
+ public function getMultiple($keys, $default = null)
+ {
+ if ($keys instanceof \Traversable) {
+ $keys = iterator_to_array($keys, false);
+ } elseif (!\is_array($keys)) {
+ throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given.', get_debug_type($keys)));
+ }
+
+ try {
+ $items = $this->pool->getItems($keys);
+ } catch (SimpleCacheException $e) {
+ throw $e;
+ } catch (Psr6CacheException $e) {
+ throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
+ }
+ $values = [];
+
+ if (!$this->pool instanceof AdapterInterface) {
+ foreach ($items as $key => $item) {
+ $values[$key] = $item->isHit() ? $item->get() : $default;
+ }
+
+ return $values;
+ }
+
+ foreach ($items as $key => $item) {
+ if (!$item->isHit()) {
+ $values[$key] = $default;
+ continue;
+ }
+ $values[$key] = $item->get();
+
+ if (!$metadata = $item->getMetadata()) {
+ continue;
+ }
+ unset($metadata[CacheItem::METADATA_TAGS]);
+
+ if ($metadata) {
+ $values[$key] = ["\x9D".pack('VN', (int) (0.1 + $metadata[CacheItem::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[CacheItem::METADATA_CTIME])."\x5F" => $values[$key]];
+ }
+ }
+
+ return $values;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function setMultiple($values, $ttl = null)
+ {
+ $valuesIsArray = \is_array($values);
+ if (!$valuesIsArray && !$values instanceof \Traversable) {
+ throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given.', get_debug_type($values)));
+ }
+ $items = [];
+
+ try {
+ if (null !== $f = $this->createCacheItem) {
+ $valuesIsArray = false;
+ foreach ($values as $key => $value) {
+ $items[$key] = $f($key, $value, true);
+ }
+ } elseif ($valuesIsArray) {
+ $items = [];
+ foreach ($values as $key => $value) {
+ $items[] = (string) $key;
+ }
+ $items = $this->pool->getItems($items);
+ } else {
+ foreach ($values as $key => $value) {
+ if (\is_int($key)) {
+ $key = (string) $key;
+ }
+ $items[$key] = $this->pool->getItem($key)->set($value);
+ }
+ }
+ } catch (SimpleCacheException $e) {
+ throw $e;
+ } catch (Psr6CacheException $e) {
+ throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
+ }
+ $ok = true;
+
+ foreach ($items as $key => $item) {
+ if ($valuesIsArray) {
+ $item->set($values[$key]);
+ }
+ if (null !== $ttl) {
+ $item->expiresAfter($ttl);
+ }
+ $ok = $this->pool->saveDeferred($item) && $ok;
+ }
+
+ return $this->pool->commit() && $ok;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteMultiple($keys)
+ {
+ if ($keys instanceof \Traversable) {
+ $keys = iterator_to_array($keys, false);
+ } elseif (!\is_array($keys)) {
+ throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given.', get_debug_type($keys)));
+ }
+
+ try {
+ return $this->pool->deleteItems($keys);
+ } catch (SimpleCacheException $e) {
+ throw $e;
+ } catch (Psr6CacheException $e) {
+ throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function has($key)
+ {
+ try {
+ return $this->pool->hasItem($key);
+ } catch (SimpleCacheException $e) {
+ throw $e;
+ } catch (Psr6CacheException $e) {
+ throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
+ }
+ }
+}
diff --git a/vendor/symfony/cache/README.md b/vendor/symfony/cache/README.md
new file mode 100644
index 0000000..7405205
--- /dev/null
+++ b/vendor/symfony/cache/README.md
@@ -0,0 +1,19 @@
+Symfony PSR-6 implementation for caching
+========================================
+
+The Cache component provides an extended
+[PSR-6](http://www.php-fig.org/psr/psr-6/) implementation for adding cache to
+your applications. It is designed to have a low overhead so that caching is
+fastest. It ships with a few caching adapters for the most widespread and
+suited to caching backends. It also provides a `doctrine/cache` proxy adapter
+to cover more advanced caching needs and a proxy adapter for greater
+interoperability between PSR-6 implementations.
+
+Resources
+---------
+
+ * [Documentation](https://symfony.com/doc/current/components/cache.html)
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/symfony/issues) and
+ [send Pull Requests](https://github.com/symfony/symfony/pulls)
+ in the [main Symfony repository](https://github.com/symfony/symfony)
diff --git a/vendor/symfony/cache/ResettableInterface.php b/vendor/symfony/cache/ResettableInterface.php
new file mode 100644
index 0000000..7b0a853
--- /dev/null
+++ b/vendor/symfony/cache/ResettableInterface.php
@@ -0,0 +1,21 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache;
+
+use Symfony\Contracts\Service\ResetInterface;
+
+/**
+ * Resets a pool's local state.
+ */
+interface ResettableInterface extends ResetInterface
+{
+}
diff --git a/vendor/symfony/cache/Traits/AbstractAdapterTrait.php b/vendor/symfony/cache/Traits/AbstractAdapterTrait.php
new file mode 100644
index 0000000..f0173c4
--- /dev/null
+++ b/vendor/symfony/cache/Traits/AbstractAdapterTrait.php
@@ -0,0 +1,424 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Traits;
+
+use Psr\Cache\CacheItemInterface;
+use Psr\Log\LoggerAwareTrait;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+
+/**
+ * @author Nicolas Grekas
+ *
+ * @internal
+ */
+trait AbstractAdapterTrait
+{
+ use LoggerAwareTrait;
+
+ /**
+ * @var \Closure needs to be set by class, signature is function(string , mixed , bool )
+ */
+ private static $createCacheItem;
+
+ /**
+ * @var \Closure needs to be set by class, signature is function(array , string , array <&expiredIds>)
+ */
+ private static $mergeByLifetime;
+
+ private $namespace = '';
+ private $defaultLifetime;
+ private $namespaceVersion = '';
+ private $versioningIsEnabled = false;
+ private $deferred = [];
+ private $ids = [];
+
+ /**
+ * @var int|null The maximum length to enforce for identifiers or null when no limit applies
+ */
+ protected $maxIdLength;
+
+ /**
+ * Fetches several cache items.
+ *
+ * @param array $ids The cache identifiers to fetch
+ *
+ * @return array|\Traversable
+ */
+ abstract protected function doFetch(array $ids);
+
+ /**
+ * Confirms if the cache contains specified cache item.
+ *
+ * @param string $id The identifier for which to check existence
+ *
+ * @return bool
+ */
+ abstract protected function doHave(string $id);
+
+ /**
+ * Deletes all items in the pool.
+ *
+ * @param string $namespace The prefix used for all identifiers managed by this pool
+ *
+ * @return bool
+ */
+ abstract protected function doClear(string $namespace);
+
+ /**
+ * Removes multiple items from the pool.
+ *
+ * @param array $ids An array of identifiers that should be removed from the pool
+ *
+ * @return bool
+ */
+ abstract protected function doDelete(array $ids);
+
+ /**
+ * Persists several cache items immediately.
+ *
+ * @param array $values The values to cache, indexed by their cache identifier
+ * @param int $lifetime The lifetime of the cached values, 0 for persisting until manual cleaning
+ *
+ * @return array|bool The identifiers that failed to be cached or a boolean stating if caching succeeded or not
+ */
+ abstract protected function doSave(array $values, int $lifetime);
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function hasItem($key)
+ {
+ $id = $this->getId($key);
+
+ if (isset($this->deferred[$key])) {
+ $this->commit();
+ }
+
+ try {
+ return $this->doHave($id);
+ } catch (\Exception $e) {
+ CacheItem::log($this->logger, 'Failed to check if key "{key}" is cached: '.$e->getMessage(), ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
+
+ return false;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function clear(string $prefix = '')
+ {
+ $this->deferred = [];
+ if ($cleared = $this->versioningIsEnabled) {
+ if ('' === $namespaceVersionToClear = $this->namespaceVersion) {
+ foreach ($this->doFetch([static::NS_SEPARATOR.$this->namespace]) as $v) {
+ $namespaceVersionToClear = $v;
+ }
+ }
+ $namespaceToClear = $this->namespace.$namespaceVersionToClear;
+ $namespaceVersion = self::formatNamespaceVersion(mt_rand());
+ try {
+ $e = $this->doSave([static::NS_SEPARATOR.$this->namespace => $namespaceVersion], 0);
+ } catch (\Exception $e) {
+ }
+ if (true !== $e && [] !== $e) {
+ $cleared = false;
+ $message = 'Failed to save the new namespace'.($e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]);
+ } else {
+ $this->namespaceVersion = $namespaceVersion;
+ $this->ids = [];
+ }
+ } else {
+ $namespaceToClear = $this->namespace.$prefix;
+ }
+
+ try {
+ return $this->doClear($namespaceToClear) || $cleared;
+ } catch (\Exception $e) {
+ CacheItem::log($this->logger, 'Failed to clear the cache: '.$e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]);
+
+ return false;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItem($key)
+ {
+ return $this->deleteItems([$key]);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteItems(array $keys)
+ {
+ $ids = [];
+
+ foreach ($keys as $key) {
+ $ids[$key] = $this->getId($key);
+ unset($this->deferred[$key]);
+ }
+
+ try {
+ if ($this->doDelete($ids)) {
+ return true;
+ }
+ } catch (\Exception $e) {
+ }
+
+ $ok = true;
+
+ // When bulk-delete failed, retry each item individually
+ foreach ($ids as $key => $id) {
+ try {
+ $e = null;
+ if ($this->doDelete([$id])) {
+ continue;
+ }
+ } catch (\Exception $e) {
+ }
+ $message = 'Failed to delete key "{key}"'.($e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
+ $ok = false;
+ }
+
+ return $ok;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItem($key)
+ {
+ $id = $this->getId($key);
+
+ if (isset($this->deferred[$key])) {
+ $this->commit();
+ }
+
+ $isHit = false;
+ $value = null;
+
+ try {
+ foreach ($this->doFetch([$id]) as $value) {
+ $isHit = true;
+ }
+
+ return (self::$createCacheItem)($key, $value, $isHit);
+ } catch (\Exception $e) {
+ CacheItem::log($this->logger, 'Failed to fetch key "{key}": '.$e->getMessage(), ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
+ }
+
+ return (self::$createCacheItem)($key, null, false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItems(array $keys = [])
+ {
+ $ids = [];
+ $commit = false;
+
+ foreach ($keys as $key) {
+ $ids[] = $this->getId($key);
+ $commit = $commit || isset($this->deferred[$key]);
+ }
+
+ if ($commit) {
+ $this->commit();
+ }
+
+ try {
+ $items = $this->doFetch($ids);
+ } catch (\Exception $e) {
+ CacheItem::log($this->logger, 'Failed to fetch items: '.$e->getMessage(), ['keys' => $keys, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
+ $items = [];
+ }
+ $ids = array_combine($ids, $keys);
+
+ return $this->generateItems($items, $ids);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function save(CacheItemInterface $item)
+ {
+ if (!$item instanceof CacheItem) {
+ return false;
+ }
+ $this->deferred[$item->getKey()] = $item;
+
+ return $this->commit();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function saveDeferred(CacheItemInterface $item)
+ {
+ if (!$item instanceof CacheItem) {
+ return false;
+ }
+ $this->deferred[$item->getKey()] = $item;
+
+ return true;
+ }
+
+ /**
+ * Enables/disables versioning of items.
+ *
+ * When versioning is enabled, clearing the cache is atomic and doesn't require listing existing keys to proceed,
+ * but old keys may need garbage collection and extra round-trips to the back-end are required.
+ *
+ * Calling this method also clears the memoized namespace version and thus forces a resynchonization of it.
+ *
+ * @return bool the previous state of versioning
+ */
+ public function enableVersioning(bool $enable = true)
+ {
+ $wasEnabled = $this->versioningIsEnabled;
+ $this->versioningIsEnabled = $enable;
+ $this->namespaceVersion = '';
+ $this->ids = [];
+
+ return $wasEnabled;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function reset()
+ {
+ if ($this->deferred) {
+ $this->commit();
+ }
+ $this->namespaceVersion = '';
+ $this->ids = [];
+ }
+
+ /**
+ * @return array
+ */
+ public function __sleep()
+ {
+ throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
+ }
+
+ public function __wakeup()
+ {
+ throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
+ }
+
+ public function __destruct()
+ {
+ if ($this->deferred) {
+ $this->commit();
+ }
+ }
+
+ private function generateItems(iterable $items, array &$keys): \Generator
+ {
+ $f = self::$createCacheItem;
+
+ try {
+ foreach ($items as $id => $value) {
+ if (!isset($keys[$id])) {
+ throw new InvalidArgumentException(sprintf('Could not match value id "%s" to keys "%s".', $id, implode('", "', $keys)));
+ }
+ $key = $keys[$id];
+ unset($keys[$id]);
+ yield $key => $f($key, $value, true);
+ }
+ } catch (\Exception $e) {
+ CacheItem::log($this->logger, 'Failed to fetch items: '.$e->getMessage(), ['keys' => array_values($keys), 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
+ }
+
+ foreach ($keys as $key) {
+ yield $key => $f($key, null, false);
+ }
+ }
+
+ private function getId($key)
+ {
+ if ($this->versioningIsEnabled && '' === $this->namespaceVersion) {
+ $this->ids = [];
+ $this->namespaceVersion = '1'.static::NS_SEPARATOR;
+ try {
+ foreach ($this->doFetch([static::NS_SEPARATOR.$this->namespace]) as $v) {
+ $this->namespaceVersion = $v;
+ }
+ $e = true;
+ if ('1'.static::NS_SEPARATOR === $this->namespaceVersion) {
+ $this->namespaceVersion = self::formatNamespaceVersion(time());
+ $e = $this->doSave([static::NS_SEPARATOR.$this->namespace => $this->namespaceVersion], 0);
+ }
+ } catch (\Exception $e) {
+ }
+ if (true !== $e && [] !== $e) {
+ $message = 'Failed to save the new namespace'.($e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]);
+ }
+ }
+
+ if (\is_string($key) && isset($this->ids[$key])) {
+ return $this->namespace.$this->namespaceVersion.$this->ids[$key];
+ }
+ \assert('' !== CacheItem::validateKey($key));
+ $this->ids[$key] = $key;
+
+ if (\count($this->ids) > 1000) {
+ array_splice($this->ids, 0, 500); // stop memory leak if there are many keys
+ }
+
+ if (null === $this->maxIdLength) {
+ return $this->namespace.$this->namespaceVersion.$key;
+ }
+ if (\strlen($id = $this->namespace.$this->namespaceVersion.$key) > $this->maxIdLength) {
+ // Use MD5 to favor speed over security, which is not an issue here
+ $this->ids[$key] = $id = substr_replace(base64_encode(hash('md5', $key, true)), static::NS_SEPARATOR, -(\strlen($this->namespaceVersion) + 2));
+ $id = $this->namespace.$this->namespaceVersion.$id;
+ }
+
+ return $id;
+ }
+
+ /**
+ * @internal
+ */
+ public static function handleUnserializeCallback(string $class)
+ {
+ throw new \DomainException('Class not found: '.$class);
+ }
+
+ private static function formatNamespaceVersion(int $value): string
+ {
+ return strtr(substr_replace(base64_encode(pack('V', $value)), static::NS_SEPARATOR, 5), '/', '_');
+ }
+}
diff --git a/vendor/symfony/cache/Traits/ContractsTrait.php b/vendor/symfony/cache/Traits/ContractsTrait.php
new file mode 100644
index 0000000..9a491ad
--- /dev/null
+++ b/vendor/symfony/cache/Traits/ContractsTrait.php
@@ -0,0 +1,109 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Traits;
+
+use Psr\Log\LoggerInterface;
+use Symfony\Component\Cache\Adapter\AdapterInterface;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\LockRegistry;
+use Symfony\Contracts\Cache\CacheInterface;
+use Symfony\Contracts\Cache\CacheTrait;
+use Symfony\Contracts\Cache\ItemInterface;
+
+/**
+ * @author Nicolas Grekas
+ *
+ * @internal
+ */
+trait ContractsTrait
+{
+ use CacheTrait {
+ doGet as private contractsGet;
+ }
+
+ private $callbackWrapper;
+ private $computing = [];
+
+ /**
+ * Wraps the callback passed to ->get() in a callable.
+ *
+ * @return callable the previous callback wrapper
+ */
+ public function setCallbackWrapper(?callable $callbackWrapper): callable
+ {
+ if (!isset($this->callbackWrapper)) {
+ $this->callbackWrapper = \Closure::fromCallable([LockRegistry::class, 'compute']);
+
+ if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) {
+ $this->setCallbackWrapper(null);
+ }
+ }
+
+ $previousWrapper = $this->callbackWrapper;
+ $this->callbackWrapper = $callbackWrapper ?? static function (callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata, ?LoggerInterface $logger) {
+ return $callback($item, $save);
+ };
+
+ return $previousWrapper;
+ }
+
+ private function doGet(AdapterInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null)
+ {
+ if (0 > $beta = $beta ?? 1.0) {
+ throw new InvalidArgumentException(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta));
+ }
+
+ static $setMetadata;
+
+ $setMetadata ?? $setMetadata = \Closure::bind(
+ static function (CacheItem $item, float $startTime, ?array &$metadata) {
+ if ($item->expiry > $endTime = microtime(true)) {
+ $item->newMetadata[CacheItem::METADATA_EXPIRY] = $metadata[CacheItem::METADATA_EXPIRY] = $item->expiry;
+ $item->newMetadata[CacheItem::METADATA_CTIME] = $metadata[CacheItem::METADATA_CTIME] = (int) ceil(1000 * ($endTime - $startTime));
+ } else {
+ unset($metadata[CacheItem::METADATA_EXPIRY], $metadata[CacheItem::METADATA_CTIME]);
+ }
+ },
+ null,
+ CacheItem::class
+ );
+
+ return $this->contractsGet($pool, $key, function (CacheItem $item, bool &$save) use ($pool, $callback, $setMetadata, &$metadata, $key) {
+ // don't wrap nor save recursive calls
+ if (isset($this->computing[$key])) {
+ $value = $callback($item, $save);
+ $save = false;
+
+ return $value;
+ }
+
+ $this->computing[$key] = $key;
+ $startTime = microtime(true);
+
+ if (!isset($this->callbackWrapper)) {
+ $this->setCallbackWrapper($this->setCallbackWrapper(null));
+ }
+
+ try {
+ $value = ($this->callbackWrapper)($callback, $item, $save, $pool, function (CacheItem $item) use ($setMetadata, $startTime, &$metadata) {
+ $setMetadata($item, $startTime, $metadata);
+ }, $this->logger ?? null);
+ $setMetadata($item, $startTime, $metadata);
+
+ return $value;
+ } finally {
+ unset($this->computing[$key]);
+ }
+ }, $beta, $metadata, $this->logger ?? null);
+ }
+}
diff --git a/vendor/symfony/cache/Traits/FilesystemCommonTrait.php b/vendor/symfony/cache/Traits/FilesystemCommonTrait.php
new file mode 100644
index 0000000..c06cc30
--- /dev/null
+++ b/vendor/symfony/cache/Traits/FilesystemCommonTrait.php
@@ -0,0 +1,196 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Traits;
+
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+
+/**
+ * @author Nicolas Grekas
+ *
+ * @internal
+ */
+trait FilesystemCommonTrait
+{
+ private $directory;
+ private $tmp;
+
+ private function init(string $namespace, ?string $directory)
+ {
+ if (!isset($directory[0])) {
+ $directory = sys_get_temp_dir().\DIRECTORY_SEPARATOR.'symfony-cache';
+ } else {
+ $directory = realpath($directory) ?: $directory;
+ }
+ if (isset($namespace[0])) {
+ if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) {
+ throw new InvalidArgumentException(sprintf('Namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0]));
+ }
+ $directory .= \DIRECTORY_SEPARATOR.$namespace;
+ } else {
+ $directory .= \DIRECTORY_SEPARATOR.'@';
+ }
+ if (!is_dir($directory)) {
+ @mkdir($directory, 0777, true);
+ }
+ $directory .= \DIRECTORY_SEPARATOR;
+ // On Windows the whole path is limited to 258 chars
+ if ('\\' === \DIRECTORY_SEPARATOR && \strlen($directory) > 234) {
+ throw new InvalidArgumentException(sprintf('Cache directory too long (%s).', $directory));
+ }
+
+ $this->directory = $directory;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doClear(string $namespace)
+ {
+ $ok = true;
+
+ foreach ($this->scanHashDir($this->directory) as $file) {
+ if ('' !== $namespace && !str_starts_with($this->getFileKey($file), $namespace)) {
+ continue;
+ }
+
+ $ok = ($this->doUnlink($file) || !file_exists($file)) && $ok;
+ }
+
+ return $ok;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDelete(array $ids)
+ {
+ $ok = true;
+
+ foreach ($ids as $id) {
+ $file = $this->getFile($id);
+ $ok = (!is_file($file) || $this->doUnlink($file) || !file_exists($file)) && $ok;
+ }
+
+ return $ok;
+ }
+
+ protected function doUnlink(string $file)
+ {
+ return @unlink($file);
+ }
+
+ private function write(string $file, string $data, int $expiresAt = null)
+ {
+ set_error_handler(__CLASS__.'::throwError');
+ try {
+ if (null === $this->tmp) {
+ $this->tmp = $this->directory.bin2hex(random_bytes(6));
+ }
+ try {
+ $h = fopen($this->tmp, 'x');
+ } catch (\ErrorException $e) {
+ if (!str_contains($e->getMessage(), 'File exists')) {
+ throw $e;
+ }
+
+ $this->tmp = $this->directory.bin2hex(random_bytes(6));
+ $h = fopen($this->tmp, 'x');
+ }
+ fwrite($h, $data);
+ fclose($h);
+
+ if (null !== $expiresAt) {
+ touch($this->tmp, $expiresAt ?: time() + 31556952); // 1 year in seconds
+ }
+
+ return rename($this->tmp, $file);
+ } finally {
+ restore_error_handler();
+ }
+ }
+
+ private function getFile(string $id, bool $mkdir = false, string $directory = null)
+ {
+ // Use MD5 to favor speed over security, which is not an issue here
+ $hash = str_replace('/', '-', base64_encode(hash('md5', static::class.$id, true)));
+ $dir = ($directory ?? $this->directory).strtoupper($hash[0].\DIRECTORY_SEPARATOR.$hash[1].\DIRECTORY_SEPARATOR);
+
+ if ($mkdir && !is_dir($dir)) {
+ @mkdir($dir, 0777, true);
+ }
+
+ return $dir.substr($hash, 2, 20);
+ }
+
+ private function getFileKey(string $file): string
+ {
+ return '';
+ }
+
+ private function scanHashDir(string $directory): \Generator
+ {
+ if (!is_dir($directory)) {
+ return;
+ }
+
+ $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
+
+ for ($i = 0; $i < 38; ++$i) {
+ if (!is_dir($directory.$chars[$i])) {
+ continue;
+ }
+
+ for ($j = 0; $j < 38; ++$j) {
+ if (!is_dir($dir = $directory.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j])) {
+ continue;
+ }
+
+ foreach (@scandir($dir, \SCANDIR_SORT_NONE) ?: [] as $file) {
+ if ('.' !== $file && '..' !== $file) {
+ yield $dir.\DIRECTORY_SEPARATOR.$file;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @internal
+ */
+ public static function throwError(int $type, string $message, string $file, int $line)
+ {
+ throw new \ErrorException($message, 0, $type, $file, $line);
+ }
+
+ /**
+ * @return array
+ */
+ public function __sleep()
+ {
+ throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
+ }
+
+ public function __wakeup()
+ {
+ throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
+ }
+
+ public function __destruct()
+ {
+ if (method_exists(parent::class, '__destruct')) {
+ parent::__destruct();
+ }
+ if (null !== $this->tmp && is_file($this->tmp)) {
+ unlink($this->tmp);
+ }
+ }
+}
diff --git a/vendor/symfony/cache/Traits/FilesystemTrait.php b/vendor/symfony/cache/Traits/FilesystemTrait.php
new file mode 100644
index 0000000..38b741f
--- /dev/null
+++ b/vendor/symfony/cache/Traits/FilesystemTrait.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\Traits;
+
+use Symfony\Component\Cache\Exception\CacheException;
+
+/**
+ * @author Nicolas Grekas
+ * @author Rob Frawley 2nd
+ *
+ * @internal
+ */
+trait FilesystemTrait
+{
+ use FilesystemCommonTrait;
+
+ private $marshaller;
+
+ /**
+ * @return bool
+ */
+ public function prune()
+ {
+ $time = time();
+ $pruned = true;
+
+ foreach ($this->scanHashDir($this->directory) as $file) {
+ if (!$h = @fopen($file, 'r')) {
+ continue;
+ }
+
+ if (($expiresAt = (int) fgets($h)) && $time >= $expiresAt) {
+ fclose($h);
+ $pruned = @unlink($file) && !file_exists($file) && $pruned;
+ } else {
+ fclose($h);
+ }
+ }
+
+ return $pruned;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doFetch(array $ids)
+ {
+ $values = [];
+ $now = time();
+
+ foreach ($ids as $id) {
+ $file = $this->getFile($id);
+ if (!is_file($file) || !$h = @fopen($file, 'r')) {
+ continue;
+ }
+ if (($expiresAt = (int) fgets($h)) && $now >= $expiresAt) {
+ fclose($h);
+ @unlink($file);
+ } else {
+ $i = rawurldecode(rtrim(fgets($h)));
+ $value = stream_get_contents($h);
+ fclose($h);
+ if ($i === $id) {
+ $values[$id] = $this->marshaller->unmarshall($value);
+ }
+ }
+ }
+
+ return $values;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doHave(string $id)
+ {
+ $file = $this->getFile($id);
+
+ return is_file($file) && (@filemtime($file) > time() || $this->doFetch([$id]));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, int $lifetime)
+ {
+ $expiresAt = $lifetime ? (time() + $lifetime) : 0;
+ $values = $this->marshaller->marshall($values, $failed);
+
+ foreach ($values as $id => $value) {
+ if (!$this->write($this->getFile($id, true), $expiresAt."\n".rawurlencode($id)."\n".$value, $expiresAt)) {
+ $failed[] = $id;
+ }
+ }
+
+ if ($failed && !is_writable($this->directory)) {
+ throw new CacheException(sprintf('Cache directory is not writable (%s).', $this->directory));
+ }
+
+ return $failed;
+ }
+
+ private function getFileKey(string $file): string
+ {
+ if (!$h = @fopen($file, 'r')) {
+ return '';
+ }
+
+ fgets($h); // expiry
+ $encodedKey = fgets($h);
+ fclose($h);
+
+ return rawurldecode(rtrim($encodedKey));
+ }
+}
diff --git a/vendor/symfony/cache/Traits/ProxyTrait.php b/vendor/symfony/cache/Traits/ProxyTrait.php
new file mode 100644
index 0000000..c86f360
--- /dev/null
+++ b/vendor/symfony/cache/Traits/ProxyTrait.php
@@ -0,0 +1,43 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Traits;
+
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Contracts\Service\ResetInterface;
+
+/**
+ * @author Nicolas Grekas
+ *
+ * @internal
+ */
+trait ProxyTrait
+{
+ private $pool;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function prune()
+ {
+ return $this->pool instanceof PruneableInterface && $this->pool->prune();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function reset()
+ {
+ if ($this->pool instanceof ResetInterface) {
+ $this->pool->reset();
+ }
+ }
+}
diff --git a/vendor/symfony/cache/Traits/RedisClusterNodeProxy.php b/vendor/symfony/cache/Traits/RedisClusterNodeProxy.php
new file mode 100644
index 0000000..deba74f
--- /dev/null
+++ b/vendor/symfony/cache/Traits/RedisClusterNodeProxy.php
@@ -0,0 +1,53 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Traits;
+
+/**
+ * This file acts as a wrapper to the \RedisCluster implementation so it can accept the same type of calls as
+ * individual \Redis objects.
+ *
+ * Calls are made to individual nodes via: RedisCluster->{method}($host, ...args)'
+ * according to https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#directed-node-commands
+ *
+ * @author Jack Thomas
+ *
+ * @internal
+ */
+class RedisClusterNodeProxy
+{
+ private $host;
+ private $redis;
+
+ /**
+ * @param \RedisCluster|RedisClusterProxy $redis
+ */
+ public function __construct(array $host, $redis)
+ {
+ $this->host = $host;
+ $this->redis = $redis;
+ }
+
+ public function __call(string $method, array $args)
+ {
+ return $this->redis->{$method}($this->host, ...$args);
+ }
+
+ public function scan(&$iIterator, $strPattern = null, $iCount = null)
+ {
+ return $this->redis->scan($iIterator, $this->host, $strPattern, $iCount);
+ }
+
+ public function getOption($name)
+ {
+ return $this->redis->getOption($name);
+ }
+}
diff --git a/vendor/symfony/cache/Traits/RedisClusterProxy.php b/vendor/symfony/cache/Traits/RedisClusterProxy.php
new file mode 100644
index 0000000..73c6a4f
--- /dev/null
+++ b/vendor/symfony/cache/Traits/RedisClusterProxy.php
@@ -0,0 +1,63 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Traits;
+
+/**
+ * @author Alessandro Chitolina
+ *
+ * @internal
+ */
+class RedisClusterProxy
+{
+ private $redis;
+ private $initializer;
+
+ public function __construct(\Closure $initializer)
+ {
+ $this->initializer = $initializer;
+ }
+
+ public function __call(string $method, array $args)
+ {
+ $this->redis ?: $this->redis = $this->initializer->__invoke();
+
+ return $this->redis->{$method}(...$args);
+ }
+
+ public function hscan($strKey, &$iIterator, $strPattern = null, $iCount = null)
+ {
+ $this->redis ?: $this->redis = $this->initializer->__invoke();
+
+ return $this->redis->hscan($strKey, $iIterator, $strPattern, $iCount);
+ }
+
+ public function scan(&$iIterator, $strPattern = null, $iCount = null)
+ {
+ $this->redis ?: $this->redis = $this->initializer->__invoke();
+
+ return $this->redis->scan($iIterator, $strPattern, $iCount);
+ }
+
+ public function sscan($strKey, &$iIterator, $strPattern = null, $iCount = null)
+ {
+ $this->redis ?: $this->redis = $this->initializer->__invoke();
+
+ return $this->redis->sscan($strKey, $iIterator, $strPattern, $iCount);
+ }
+
+ public function zscan($strKey, &$iIterator, $strPattern = null, $iCount = null)
+ {
+ $this->redis ?: $this->redis = $this->initializer->__invoke();
+
+ return $this->redis->zscan($strKey, $iIterator, $strPattern, $iCount);
+ }
+}
diff --git a/vendor/symfony/cache/Traits/RedisProxy.php b/vendor/symfony/cache/Traits/RedisProxy.php
new file mode 100644
index 0000000..ec5cfab
--- /dev/null
+++ b/vendor/symfony/cache/Traits/RedisProxy.php
@@ -0,0 +1,65 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Traits;
+
+/**
+ * @author Nicolas Grekas
+ *
+ * @internal
+ */
+class RedisProxy
+{
+ private $redis;
+ private $initializer;
+ private $ready = false;
+
+ public function __construct(\Redis $redis, \Closure $initializer)
+ {
+ $this->redis = $redis;
+ $this->initializer = $initializer;
+ }
+
+ public function __call(string $method, array $args)
+ {
+ $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis);
+
+ return $this->redis->{$method}(...$args);
+ }
+
+ public function hscan($strKey, &$iIterator, $strPattern = null, $iCount = null)
+ {
+ $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis);
+
+ return $this->redis->hscan($strKey, $iIterator, $strPattern, $iCount);
+ }
+
+ public function scan(&$iIterator, $strPattern = null, $iCount = null)
+ {
+ $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis);
+
+ return $this->redis->scan($iIterator, $strPattern, $iCount);
+ }
+
+ public function sscan($strKey, &$iIterator, $strPattern = null, $iCount = null)
+ {
+ $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis);
+
+ return $this->redis->sscan($strKey, $iIterator, $strPattern, $iCount);
+ }
+
+ public function zscan($strKey, &$iIterator, $strPattern = null, $iCount = null)
+ {
+ $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis);
+
+ return $this->redis->zscan($strKey, $iIterator, $strPattern, $iCount);
+ }
+}
diff --git a/vendor/symfony/cache/Traits/RedisTrait.php b/vendor/symfony/cache/Traits/RedisTrait.php
new file mode 100644
index 0000000..accee44
--- /dev/null
+++ b/vendor/symfony/cache/Traits/RedisTrait.php
@@ -0,0 +1,603 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Traits;
+
+use Predis\Command\Redis\UNLINK;
+use Predis\Connection\Aggregate\ClusterInterface;
+use Predis\Connection\Aggregate\RedisCluster;
+use Predis\Connection\Aggregate\ReplicationInterface;
+use Predis\Response\ErrorInterface;
+use Predis\Response\Status;
+use Symfony\Component\Cache\Exception\CacheException;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\Marshaller\DefaultMarshaller;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+
+/**
+ * @author Aurimas Niekis
+ * @author Nicolas Grekas
+ *
+ * @internal
+ */
+trait RedisTrait
+{
+ private static $defaultConnectionOptions = [
+ 'class' => null,
+ 'persistent' => 0,
+ 'persistent_id' => null,
+ 'timeout' => 30,
+ 'read_timeout' => 0,
+ 'retry_interval' => 0,
+ 'tcp_keepalive' => 0,
+ 'lazy' => null,
+ 'redis_cluster' => false,
+ 'redis_sentinel' => null,
+ 'dbindex' => 0,
+ 'failover' => 'none',
+ 'ssl' => null, // see https://php.net/context.ssl
+ ];
+ private $redis;
+ private $marshaller;
+
+ /**
+ * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis
+ */
+ private function init($redis, string $namespace, int $defaultLifetime, ?MarshallerInterface $marshaller)
+ {
+ parent::__construct($namespace, $defaultLifetime);
+
+ if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) {
+ throw new InvalidArgumentException(sprintf('RedisAdapter namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0]));
+ }
+
+ if (!$redis instanceof \Redis && !$redis instanceof \RedisArray && !$redis instanceof \RedisCluster && !$redis instanceof \Predis\ClientInterface && !$redis instanceof RedisProxy && !$redis instanceof RedisClusterProxy) {
+ throw new InvalidArgumentException(sprintf('"%s()" expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, "%s" given.', __METHOD__, get_debug_type($redis)));
+ }
+
+ if ($redis instanceof \Predis\ClientInterface && $redis->getOptions()->exceptions) {
+ $options = clone $redis->getOptions();
+ \Closure::bind(function () { $this->options['exceptions'] = false; }, $options, $options)();
+ $redis = new $redis($redis->getConnection(), $options);
+ }
+
+ $this->redis = $redis;
+ $this->marshaller = $marshaller ?? new DefaultMarshaller();
+ }
+
+ /**
+ * Creates a Redis connection using a DSN configuration.
+ *
+ * Example DSN:
+ * - redis://localhost
+ * - redis://example.com:1234
+ * - redis://secret@example.com/13
+ * - redis:///var/run/redis.sock
+ * - redis://secret@/var/run/redis.sock/13
+ *
+ * @param array $options See self::$defaultConnectionOptions
+ *
+ * @return \Redis|\RedisArray|\RedisCluster|RedisClusterProxy|RedisProxy|\Predis\ClientInterface According to the "class" option
+ *
+ * @throws InvalidArgumentException when the DSN is invalid
+ */
+ public static function createConnection(string $dsn, array $options = [])
+ {
+ if (str_starts_with($dsn, 'redis:')) {
+ $scheme = 'redis';
+ } elseif (str_starts_with($dsn, 'rediss:')) {
+ $scheme = 'rediss';
+ } else {
+ throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s" does not start with "redis:" or "rediss".', $dsn));
+ }
+
+ if (!\extension_loaded('redis') && !class_exists(\Predis\Client::class)) {
+ throw new CacheException(sprintf('Cannot find the "redis" extension nor the "predis/predis" package: "%s".', $dsn));
+ }
+
+ $params = preg_replace_callback('#^'.$scheme.':(//)?(?:(?:[^:@]*+:)?([^@]*+)@)?#', function ($m) use (&$auth) {
+ if (isset($m[2])) {
+ $auth = $m[2];
+
+ if ('' === $auth) {
+ $auth = null;
+ }
+ }
+
+ return 'file:'.($m[1] ?? '');
+ }, $dsn);
+
+ if (false === $params = parse_url($params)) {
+ throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s".', $dsn));
+ }
+
+ $query = $hosts = [];
+
+ $tls = 'rediss' === $scheme;
+ $tcpScheme = $tls ? 'tls' : 'tcp';
+
+ if (isset($params['query'])) {
+ parse_str($params['query'], $query);
+
+ if (isset($query['host'])) {
+ if (!\is_array($hosts = $query['host'])) {
+ throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s".', $dsn));
+ }
+ foreach ($hosts as $host => $parameters) {
+ if (\is_string($parameters)) {
+ parse_str($parameters, $parameters);
+ }
+ if (false === $i = strrpos($host, ':')) {
+ $hosts[$host] = ['scheme' => $tcpScheme, 'host' => $host, 'port' => 6379] + $parameters;
+ } elseif ($port = (int) substr($host, 1 + $i)) {
+ $hosts[$host] = ['scheme' => $tcpScheme, 'host' => substr($host, 0, $i), 'port' => $port] + $parameters;
+ } else {
+ $hosts[$host] = ['scheme' => 'unix', 'path' => substr($host, 0, $i)] + $parameters;
+ }
+ }
+ $hosts = array_values($hosts);
+ }
+ }
+
+ if (isset($params['host']) || isset($params['path'])) {
+ if (!isset($params['dbindex']) && isset($params['path'])) {
+ if (preg_match('#/(\d+)$#', $params['path'], $m)) {
+ $params['dbindex'] = $m[1];
+ $params['path'] = substr($params['path'], 0, -\strlen($m[0]));
+ } elseif (isset($params['host'])) {
+ throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s", the "dbindex" parameter must be a number.', $dsn));
+ }
+ }
+
+ if (isset($params['host'])) {
+ array_unshift($hosts, ['scheme' => $tcpScheme, 'host' => $params['host'], 'port' => $params['port'] ?? 6379]);
+ } else {
+ array_unshift($hosts, ['scheme' => 'unix', 'path' => $params['path']]);
+ }
+ }
+
+ if (!$hosts) {
+ throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s".', $dsn));
+ }
+
+ $params += $query + $options + self::$defaultConnectionOptions;
+
+ if (isset($params['redis_sentinel']) && !class_exists(\Predis\Client::class) && !class_exists(\RedisSentinel::class)) {
+ throw new CacheException(sprintf('Redis Sentinel support requires the "predis/predis" package or the "redis" extension v5.2 or higher: "%s".', $dsn));
+ }
+
+ if ($params['redis_cluster'] && isset($params['redis_sentinel'])) {
+ throw new InvalidArgumentException(sprintf('Cannot use both "redis_cluster" and "redis_sentinel" at the same time: "%s".', $dsn));
+ }
+
+ if (null === $params['class'] && \extension_loaded('redis')) {
+ $class = $params['redis_cluster'] ? \RedisCluster::class : (1 < \count($hosts) && !isset($params['redis_sentinel']) ? \RedisArray::class : \Redis::class);
+ } else {
+ $class = $params['class'] ?? \Predis\Client::class;
+
+ if (isset($params['redis_sentinel']) && !is_a($class, \Predis\Client::class, true) && !class_exists(\RedisSentinel::class)) {
+ throw new CacheException(sprintf('Cannot use Redis Sentinel: class "%s" does not extend "Predis\Client" and ext-redis >= 5.2 not found: "%s".', $class, $dsn));
+ }
+ }
+
+ if (is_a($class, \Redis::class, true)) {
+ $connect = $params['persistent'] || $params['persistent_id'] ? 'pconnect' : 'connect';
+ $redis = new $class();
+
+ $initializer = static function ($redis) use ($connect, $params, $dsn, $auth, $hosts, $tls) {
+ $hostIndex = 0;
+ do {
+ $host = $hosts[$hostIndex]['host'] ?? $hosts[$hostIndex]['path'];
+ $port = $hosts[$hostIndex]['port'] ?? 0;
+ $address = false;
+
+ if (isset($hosts[$hostIndex]['host']) && $tls) {
+ $host = 'tls://'.$host;
+ }
+
+ if (!isset($params['redis_sentinel'])) {
+ break;
+ }
+
+ $sentinel = new \RedisSentinel($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout']);
+
+ if ($address = $sentinel->getMasterAddrByName($params['redis_sentinel'])) {
+ [$host, $port] = $address;
+ }
+ } while (++$hostIndex < \count($hosts) && !$address);
+
+ if (isset($params['redis_sentinel']) && !$address) {
+ throw new InvalidArgumentException(sprintf('Failed to retrieve master information from sentinel "%s" and dsn "%s".', $params['redis_sentinel'], $dsn));
+ }
+
+ try {
+ @$redis->{$connect}($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout'], ...\defined('Redis::SCAN_PREFIX') ? [['stream' => $params['ssl'] ?? null]] : []);
+
+ set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
+ try {
+ $isConnected = $redis->isConnected();
+ } finally {
+ restore_error_handler();
+ }
+ if (!$isConnected) {
+ $error = preg_match('/^Redis::p?connect\(\): (.*)/', $error, $error) ? sprintf(' (%s)', $error[1]) : '';
+ throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$error.'.');
+ }
+
+ if ((null !== $auth && !$redis->auth($auth))
+ || ($params['dbindex'] && !$redis->select($params['dbindex']))
+ ) {
+ $e = preg_replace('/^ERR /', '', $redis->getLastError());
+ throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e.'.');
+ }
+
+ if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) {
+ $redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']);
+ }
+ } catch (\RedisException $e) {
+ throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e->getMessage());
+ }
+
+ return true;
+ };
+
+ if ($params['lazy']) {
+ $redis = new RedisProxy($redis, $initializer);
+ } else {
+ $initializer($redis);
+ }
+ } elseif (is_a($class, \RedisArray::class, true)) {
+ foreach ($hosts as $i => $host) {
+ switch ($host['scheme']) {
+ case 'tcp': $hosts[$i] = $host['host'].':'.$host['port']; break;
+ case 'tls': $hosts[$i] = 'tls://'.$host['host'].':'.$host['port']; break;
+ default: $hosts[$i] = $host['path'];
+ }
+ }
+ $params['lazy_connect'] = $params['lazy'] ?? true;
+ $params['connect_timeout'] = $params['timeout'];
+
+ try {
+ $redis = new $class($hosts, $params);
+ } catch (\RedisClusterException $e) {
+ throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e->getMessage());
+ }
+
+ if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) {
+ $redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']);
+ }
+ } elseif (is_a($class, \RedisCluster::class, true)) {
+ $initializer = static function () use ($class, $params, $dsn, $hosts) {
+ foreach ($hosts as $i => $host) {
+ switch ($host['scheme']) {
+ case 'tcp': $hosts[$i] = $host['host'].':'.$host['port']; break;
+ case 'tls': $hosts[$i] = 'tls://'.$host['host'].':'.$host['port']; break;
+ default: $hosts[$i] = $host['path'];
+ }
+ }
+
+ try {
+ $redis = new $class(null, $hosts, $params['timeout'], $params['read_timeout'], (bool) $params['persistent'], $params['auth'] ?? '', ...\defined('Redis::SCAN_PREFIX') ? [$params['ssl'] ?? null] : []);
+ } catch (\RedisClusterException $e) {
+ throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e->getMessage());
+ }
+
+ if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) {
+ $redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']);
+ }
+ switch ($params['failover']) {
+ case 'error': $redis->setOption(\RedisCluster::OPT_SLAVE_FAILOVER, \RedisCluster::FAILOVER_ERROR); break;
+ case 'distribute': $redis->setOption(\RedisCluster::OPT_SLAVE_FAILOVER, \RedisCluster::FAILOVER_DISTRIBUTE); break;
+ case 'slaves': $redis->setOption(\RedisCluster::OPT_SLAVE_FAILOVER, \RedisCluster::FAILOVER_DISTRIBUTE_SLAVES); break;
+ }
+
+ return $redis;
+ };
+
+ $redis = $params['lazy'] ? new RedisClusterProxy($initializer) : $initializer();
+ } elseif (is_a($class, \Predis\ClientInterface::class, true)) {
+ if ($params['redis_cluster']) {
+ $params['cluster'] = 'redis';
+ } elseif (isset($params['redis_sentinel'])) {
+ $params['replication'] = 'sentinel';
+ $params['service'] = $params['redis_sentinel'];
+ }
+ $params += ['parameters' => []];
+ $params['parameters'] += [
+ 'persistent' => $params['persistent'],
+ 'timeout' => $params['timeout'],
+ 'read_write_timeout' => $params['read_timeout'],
+ 'tcp_nodelay' => true,
+ ];
+ if ($params['dbindex']) {
+ $params['parameters']['database'] = $params['dbindex'];
+ }
+ if (null !== $auth) {
+ $params['parameters']['password'] = $auth;
+ }
+ if (1 === \count($hosts) && !($params['redis_cluster'] || $params['redis_sentinel'])) {
+ $hosts = $hosts[0];
+ } elseif (\in_array($params['failover'], ['slaves', 'distribute'], true) && !isset($params['replication'])) {
+ $params['replication'] = true;
+ $hosts[0] += ['alias' => 'master'];
+ }
+ $params['exceptions'] = false;
+
+ $redis = new $class($hosts, array_diff_key($params, array_diff_key(self::$defaultConnectionOptions, ['ssl' => null])));
+ if (isset($params['redis_sentinel'])) {
+ $redis->getConnection()->setSentinelTimeout($params['timeout']);
+ }
+ } elseif (class_exists($class, false)) {
+ throw new InvalidArgumentException(sprintf('"%s" is not a subclass of "Redis", "RedisArray", "RedisCluster" nor "Predis\ClientInterface".', $class));
+ } else {
+ throw new InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
+ }
+
+ return $redis;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doFetch(array $ids)
+ {
+ if (!$ids) {
+ return [];
+ }
+
+ $result = [];
+
+ if ($this->redis instanceof \Predis\ClientInterface && $this->redis->getConnection() instanceof ClusterInterface) {
+ $values = $this->pipeline(function () use ($ids) {
+ foreach ($ids as $id) {
+ yield 'get' => [$id];
+ }
+ });
+ } else {
+ $values = $this->redis->mget($ids);
+
+ if (!\is_array($values) || \count($values) !== \count($ids)) {
+ return [];
+ }
+
+ $values = array_combine($ids, $values);
+ }
+
+ foreach ($values as $id => $v) {
+ if ($v) {
+ $result[$id] = $this->marshaller->unmarshall($v);
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doHave(string $id)
+ {
+ return (bool) $this->redis->exists($id);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doClear(string $namespace)
+ {
+ if ($this->redis instanceof \Predis\ClientInterface) {
+ $prefix = $this->redis->getOptions()->prefix ? $this->redis->getOptions()->prefix->getPrefix() : '';
+ $prefixLen = \strlen($prefix ?? '');
+ }
+
+ $cleared = true;
+ $hosts = $this->getHosts();
+ $host = reset($hosts);
+ if ($host instanceof \Predis\Client && $host->getConnection() instanceof ReplicationInterface) {
+ // Predis supports info command only on the master in replication environments
+ $hosts = [$host->getClientFor('master')];
+ }
+
+ foreach ($hosts as $host) {
+ if (!isset($namespace[0])) {
+ $cleared = $host->flushDb() && $cleared;
+ continue;
+ }
+
+ $info = $host->info('Server');
+ $info = !$info instanceof ErrorInterface ? $info['Server'] ?? $info : ['redis_version' => '2.0'];
+
+ if (!$host instanceof \Predis\ClientInterface) {
+ $prefix = \defined('Redis::SCAN_PREFIX') && (\Redis::SCAN_PREFIX & $host->getOption(\Redis::OPT_SCAN)) ? '' : $host->getOption(\Redis::OPT_PREFIX);
+ $prefixLen = \strlen($host->getOption(\Redis::OPT_PREFIX) ?? '');
+ }
+ $pattern = $prefix.$namespace.'*';
+
+ if (!version_compare($info['redis_version'], '2.8', '>=')) {
+ // As documented in Redis documentation (http://redis.io/commands/keys) using KEYS
+ // can hang your server when it is executed against large databases (millions of items).
+ // Whenever you hit this scale, you should really consider upgrading to Redis 2.8 or above.
+ $unlink = version_compare($info['redis_version'], '4.0', '>=') ? 'UNLINK' : 'DEL';
+ $args = $this->redis instanceof \Predis\ClientInterface ? [0, $pattern] : [[$pattern], 0];
+ $cleared = $host->eval("local keys=redis.call('KEYS',ARGV[1]) for i=1,#keys,5000 do redis.call('$unlink',unpack(keys,i,math.min(i+4999,#keys))) end return 1", $args[0], $args[1]) && $cleared;
+ continue;
+ }
+
+ $cursor = null;
+ do {
+ $keys = $host instanceof \Predis\ClientInterface ? $host->scan($cursor, 'MATCH', $pattern, 'COUNT', 1000) : $host->scan($cursor, $pattern, 1000);
+ if (isset($keys[1]) && \is_array($keys[1])) {
+ $cursor = $keys[0];
+ $keys = $keys[1];
+ }
+ if ($keys) {
+ if ($prefixLen) {
+ foreach ($keys as $i => $key) {
+ $keys[$i] = substr($key, $prefixLen);
+ }
+ }
+ $this->doDelete($keys);
+ }
+ } while ($cursor = (int) $cursor);
+ }
+
+ return $cleared;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDelete(array $ids)
+ {
+ if (!$ids) {
+ return true;
+ }
+
+ if ($this->redis instanceof \Predis\ClientInterface && $this->redis->getConnection() instanceof ClusterInterface) {
+ static $del;
+ $del = $del ?? (class_exists(UNLINK::class) ? 'unlink' : 'del');
+
+ $this->pipeline(function () use ($ids, $del) {
+ foreach ($ids as $id) {
+ yield $del => [$id];
+ }
+ })->rewind();
+ } else {
+ static $unlink = true;
+
+ if ($unlink) {
+ try {
+ $unlink = false !== $this->redis->unlink($ids);
+ } catch (\Throwable $e) {
+ $unlink = false;
+ }
+ }
+
+ if (!$unlink) {
+ $this->redis->del($ids);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, int $lifetime)
+ {
+ if (!$values = $this->marshaller->marshall($values, $failed)) {
+ return $failed;
+ }
+
+ $results = $this->pipeline(function () use ($values, $lifetime) {
+ foreach ($values as $id => $value) {
+ if (0 >= $lifetime) {
+ yield 'set' => [$id, $value];
+ } else {
+ yield 'setEx' => [$id, $lifetime, $value];
+ }
+ }
+ });
+
+ foreach ($results as $id => $result) {
+ if (true !== $result && (!$result instanceof Status || Status::get('OK') !== $result)) {
+ $failed[] = $id;
+ }
+ }
+
+ return $failed;
+ }
+
+ private function pipeline(\Closure $generator, object $redis = null): \Generator
+ {
+ $ids = [];
+ $redis = $redis ?? $this->redis;
+
+ if ($redis instanceof RedisClusterProxy || $redis instanceof \RedisCluster || ($redis instanceof \Predis\ClientInterface && $redis->getConnection() instanceof RedisCluster)) {
+ // phpredis & predis don't support pipelining with RedisCluster
+ // see https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#pipelining
+ // see https://github.com/nrk/predis/issues/267#issuecomment-123781423
+ $results = [];
+ foreach ($generator() as $command => $args) {
+ $results[] = $redis->{$command}(...$args);
+ $ids[] = 'eval' === $command ? ($redis instanceof \Predis\ClientInterface ? $args[2] : $args[1][0]) : $args[0];
+ }
+ } elseif ($redis instanceof \Predis\ClientInterface) {
+ $results = $redis->pipeline(static function ($redis) use ($generator, &$ids) {
+ foreach ($generator() as $command => $args) {
+ $redis->{$command}(...$args);
+ $ids[] = 'eval' === $command ? $args[2] : $args[0];
+ }
+ });
+ } elseif ($redis instanceof \RedisArray) {
+ $connections = $results = $ids = [];
+ foreach ($generator() as $command => $args) {
+ $id = 'eval' === $command ? $args[1][0] : $args[0];
+ if (!isset($connections[$h = $redis->_target($id)])) {
+ $connections[$h] = [$redis->_instance($h), -1];
+ $connections[$h][0]->multi(\Redis::PIPELINE);
+ }
+ $connections[$h][0]->{$command}(...$args);
+ $results[] = [$h, ++$connections[$h][1]];
+ $ids[] = $id;
+ }
+ foreach ($connections as $h => $c) {
+ $connections[$h] = $c[0]->exec();
+ }
+ foreach ($results as $k => [$h, $c]) {
+ $results[$k] = $connections[$h][$c];
+ }
+ } else {
+ $redis->multi(\Redis::PIPELINE);
+ foreach ($generator() as $command => $args) {
+ $redis->{$command}(...$args);
+ $ids[] = 'eval' === $command ? $args[1][0] : $args[0];
+ }
+ $results = $redis->exec();
+ }
+
+ if (!$redis instanceof \Predis\ClientInterface && 'eval' === $command && $redis->getLastError()) {
+ $e = new \RedisException($redis->getLastError());
+ $results = array_map(function ($v) use ($e) { return false === $v ? $e : $v; }, $results);
+ }
+
+ foreach ($ids as $k => $id) {
+ yield $id => $results[$k];
+ }
+ }
+
+ private function getHosts(): array
+ {
+ $hosts = [$this->redis];
+ if ($this->redis instanceof \Predis\ClientInterface) {
+ $connection = $this->redis->getConnection();
+ if ($connection instanceof ClusterInterface && $connection instanceof \Traversable) {
+ $hosts = [];
+ foreach ($connection as $c) {
+ $hosts[] = new \Predis\Client($c);
+ }
+ }
+ } elseif ($this->redis instanceof \RedisArray) {
+ $hosts = [];
+ foreach ($this->redis->_hosts() as $host) {
+ $hosts[] = $this->redis->_instance($host);
+ }
+ } elseif ($this->redis instanceof RedisClusterProxy || $this->redis instanceof \RedisCluster) {
+ $hosts = [];
+ foreach ($this->redis->_masters() as $host) {
+ $hosts[] = new RedisClusterNodeProxy($host, $this->redis);
+ }
+ }
+
+ return $hosts;
+ }
+}
diff --git a/vendor/symfony/cache/composer.json b/vendor/symfony/cache/composer.json
new file mode 100644
index 0000000..1ebcfc9
--- /dev/null
+++ b/vendor/symfony/cache/composer.json
@@ -0,0 +1,60 @@
+{
+ "name": "symfony/cache",
+ "type": "library",
+ "description": "Provides an extended PSR-6, PSR-16 (and tags) implementation",
+ "keywords": ["caching", "psr6"],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "provide": {
+ "psr/cache-implementation": "1.0|2.0",
+ "psr/simple-cache-implementation": "1.0|2.0",
+ "symfony/cache-implementation": "1.0|2.0"
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "psr/cache": "^1.0|^2.0",
+ "psr/log": "^1.1|^2|^3",
+ "symfony/cache-contracts": "^1.1.7|^2",
+ "symfony/deprecation-contracts": "^2.1|^3",
+ "symfony/polyfill-php73": "^1.9",
+ "symfony/polyfill-php80": "^1.16",
+ "symfony/service-contracts": "^1.1|^2|^3",
+ "symfony/var-exporter": "^4.4|^5.0|^6.0"
+ },
+ "require-dev": {
+ "cache/integration-tests": "dev-master",
+ "doctrine/cache": "^1.6|^2.0",
+ "doctrine/dbal": "^2.13.1|^3.0",
+ "predis/predis": "^1.1",
+ "psr/simple-cache": "^1.0|^2.0",
+ "symfony/config": "^4.4|^5.0|^6.0",
+ "symfony/dependency-injection": "^4.4|^5.0|^6.0",
+ "symfony/filesystem": "^4.4|^5.0|^6.0",
+ "symfony/http-kernel": "^4.4|^5.0|^6.0",
+ "symfony/messenger": "^4.4|^5.0|^6.0",
+ "symfony/var-dumper": "^4.4|^5.0|^6.0"
+ },
+ "conflict": {
+ "doctrine/dbal": "<2.13.1",
+ "symfony/dependency-injection": "<4.4",
+ "symfony/http-kernel": "<4.4",
+ "symfony/var-dumper": "<4.4"
+ },
+ "autoload": {
+ "psr-4": { "Symfony\\Component\\Cache\\": "" },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "minimum-stability": "dev"
+}
diff --git a/vendor/symfony/event-dispatcher-contracts/.gitignore b/vendor/symfony/event-dispatcher-contracts/.gitignore
new file mode 100644
index 0000000..c49a5d8
--- /dev/null
+++ b/vendor/symfony/event-dispatcher-contracts/.gitignore
@@ -0,0 +1,3 @@
+vendor/
+composer.lock
+phpunit.xml
diff --git a/vendor/symfony/event-dispatcher-contracts/CHANGELOG.md b/vendor/symfony/event-dispatcher-contracts/CHANGELOG.md
new file mode 100644
index 0000000..7932e26
--- /dev/null
+++ b/vendor/symfony/event-dispatcher-contracts/CHANGELOG.md
@@ -0,0 +1,5 @@
+CHANGELOG
+=========
+
+The changelog is maintained for all Symfony contracts at the following URL:
+https://github.com/symfony/contracts/blob/main/CHANGELOG.md
diff --git a/vendor/symfony/event-dispatcher-contracts/Event.php b/vendor/symfony/event-dispatcher-contracts/Event.php
new file mode 100644
index 0000000..46dcb2b
--- /dev/null
+++ b/vendor/symfony/event-dispatcher-contracts/Event.php
@@ -0,0 +1,54 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Contracts\EventDispatcher;
+
+use Psr\EventDispatcher\StoppableEventInterface;
+
+/**
+ * Event is the base class for classes containing event data.
+ *
+ * This class contains no event data. It is used by events that do not pass
+ * state information to an event handler when an event is raised.
+ *
+ * You can call the method stopPropagation() to abort the execution of
+ * further listeners in your event listener.
+ *
+ * @author Guilherme Blanco
+ * @author Jonathan Wage
+ * @author Roman Borschel
+ * @author Bernhard Schussek
+ * @author Nicolas Grekas
+ */
+class Event implements StoppableEventInterface
+{
+ private $propagationStopped = false;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isPropagationStopped(): bool
+ {
+ return $this->propagationStopped;
+ }
+
+ /**
+ * Stops the propagation of the event to further event listeners.
+ *
+ * If multiple event listeners are connected to the same event, no
+ * further event listener will be triggered once any trigger calls
+ * stopPropagation().
+ */
+ public function stopPropagation(): void
+ {
+ $this->propagationStopped = true;
+ }
+}
diff --git a/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php b/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php
new file mode 100644
index 0000000..351dc51
--- /dev/null
+++ b/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.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\Contracts\EventDispatcher;
+
+use Psr\EventDispatcher\EventDispatcherInterface as PsrEventDispatcherInterface;
+
+/**
+ * Allows providing hooks on domain-specific lifecycles by dispatching events.
+ */
+interface EventDispatcherInterface extends PsrEventDispatcherInterface
+{
+ /**
+ * Dispatches an event to all registered listeners.
+ *
+ * @param object $event The event to pass to the event handlers/listeners
+ * @param string|null $eventName The name of the event to dispatch. If not supplied,
+ * the class of $event should be used instead.
+ *
+ * @return object The passed $event MUST be returned
+ */
+ public function dispatch(object $event, string $eventName = null): object;
+}
diff --git a/vendor/symfony/event-dispatcher-contracts/LICENSE b/vendor/symfony/event-dispatcher-contracts/LICENSE
new file mode 100644
index 0000000..74cdc2d
--- /dev/null
+++ b/vendor/symfony/event-dispatcher-contracts/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2018-2022 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/symfony/event-dispatcher-contracts/README.md b/vendor/symfony/event-dispatcher-contracts/README.md
new file mode 100644
index 0000000..b1ab4c0
--- /dev/null
+++ b/vendor/symfony/event-dispatcher-contracts/README.md
@@ -0,0 +1,9 @@
+Symfony EventDispatcher Contracts
+=================================
+
+A set of abstractions extracted out of the Symfony components.
+
+Can be used to build on semantics that the Symfony components proved useful - and
+that already have battle tested implementations.
+
+See https://github.com/symfony/contracts/blob/main/README.md for more information.
diff --git a/vendor/symfony/event-dispatcher-contracts/composer.json b/vendor/symfony/event-dispatcher-contracts/composer.json
new file mode 100644
index 0000000..660df81
--- /dev/null
+++ b/vendor/symfony/event-dispatcher-contracts/composer.json
@@ -0,0 +1,38 @@
+{
+ "name": "symfony/event-dispatcher-contracts",
+ "type": "library",
+ "description": "Generic abstractions related to dispatching event",
+ "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=7.2.5",
+ "psr/event-dispatcher": "^1"
+ },
+ "suggest": {
+ "symfony/event-dispatcher-implementation": ""
+ },
+ "autoload": {
+ "psr-4": { "Symfony\\Contracts\\EventDispatcher\\": "" }
+ },
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.5-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ }
+}
diff --git a/vendor/symfony/event-dispatcher/Attribute/AsEventListener.php b/vendor/symfony/event-dispatcher/Attribute/AsEventListener.php
new file mode 100644
index 0000000..bb931b8
--- /dev/null
+++ b/vendor/symfony/event-dispatcher/Attribute/AsEventListener.php
@@ -0,0 +1,29 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\EventDispatcher\Attribute;
+
+/**
+ * Service tag to autoconfigure event listeners.
+ *
+ * @author Alexander M. Turek
+ */
+#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
+class AsEventListener
+{
+ public function __construct(
+ public ?string $event = null,
+ public ?string $method = null,
+ public int $priority = 0,
+ public ?string $dispatcher = null,
+ ) {
+ }
+}
diff --git a/vendor/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php b/vendor/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php
new file mode 100644
index 0000000..6e7292b
--- /dev/null
+++ b/vendor/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php
@@ -0,0 +1,46 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\EventDispatcher\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+ * This pass allows bundles to extend the list of event aliases.
+ *
+ * @author Alexander M. Turek
+ */
+class AddEventAliasesPass implements CompilerPassInterface
+{
+ private $eventAliases;
+ private $eventAliasesParameter;
+
+ public function __construct(array $eventAliases, string $eventAliasesParameter = 'event_dispatcher.event_aliases')
+ {
+ if (1 < \func_num_args()) {
+ trigger_deprecation('symfony/event-dispatcher', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
+ }
+
+ $this->eventAliases = $eventAliases;
+ $this->eventAliasesParameter = $eventAliasesParameter;
+ }
+
+ public function process(ContainerBuilder $container): void
+ {
+ $eventAliases = $container->hasParameter($this->eventAliasesParameter) ? $container->getParameter($this->eventAliasesParameter) : [];
+
+ $container->setParameter(
+ $this->eventAliasesParameter,
+ array_merge($eventAliases, $this->eventAliases)
+ );
+ }
+}
diff --git a/vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php b/vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php
new file mode 100644
index 0000000..6e17c8f
--- /dev/null
+++ b/vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.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\EventDispatcher;
+
+use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
+
+trigger_deprecation('symfony/event-dispatcher', '5.1', '%s is deprecated, use the event dispatcher without the proxy.', LegacyEventDispatcherProxy::class);
+
+/**
+ * A helper class to provide BC/FC with the legacy signature of EventDispatcherInterface::dispatch().
+ *
+ * @author Nicolas Grekas
+ *
+ * @deprecated since Symfony 5.1
+ */
+final class LegacyEventDispatcherProxy
+{
+ public static function decorate(?EventDispatcherInterface $dispatcher): ?EventDispatcherInterface
+ {
+ return $dispatcher;
+ }
+}
diff --git a/vendor/symfony/finder/Comparator/Comparator.php b/vendor/symfony/finder/Comparator/Comparator.php
index 6aee21c..3af551f 100644
--- a/vendor/symfony/finder/Comparator/Comparator.php
+++ b/vendor/symfony/finder/Comparator/Comparator.php
@@ -12,8 +12,6 @@
namespace Symfony\Component\Finder\Comparator;
/**
- * Comparator.
- *
* @author Fabien Potencier
*/
class Comparator
@@ -21,30 +19,44 @@ class Comparator
private $target;
private $operator = '==';
+ public function __construct(string $target = null, string $operator = '==')
+ {
+ if (null === $target) {
+ trigger_deprecation('symfony/finder', '5.4', 'Constructing a "%s" without setting "$target" is deprecated.', __CLASS__);
+ }
+
+ $this->target = $target;
+ $this->doSetOperator($operator);
+ }
+
/**
* Gets the target value.
*
- * @return string The target value
+ * @return string
*/
public function getTarget()
{
+ if (null === $this->target) {
+ trigger_deprecation('symfony/finder', '5.4', 'Calling "%s" without initializing the target is deprecated.', __METHOD__);
+ }
+
return $this->target;
}
/**
- * Sets the target value.
- *
- * @param string $target The target value
+ * @deprecated set the target via the constructor instead
*/
- public function setTarget($target)
+ public function setTarget(string $target)
{
+ trigger_deprecation('symfony/finder', '5.4', '"%s" is deprecated. Set the target via the constructor instead.', __METHOD__);
+
$this->target = $target;
}
/**
* Gets the comparison operator.
*
- * @return string The operator
+ * @return string
*/
public function getOperator()
{
@@ -54,21 +66,15 @@ class Comparator
/**
* Sets the comparison operator.
*
- * @param string $operator A valid operator
- *
* @throws \InvalidArgumentException
+ *
+ * @deprecated set the operator via the constructor instead
*/
- public function setOperator($operator)
+ public function setOperator(string $operator)
{
- if (!$operator) {
- $operator = '==';
- }
+ trigger_deprecation('symfony/finder', '5.4', '"%s" is deprecated. Set the operator via the constructor instead.', __METHOD__);
- if (!\in_array($operator, ['>', '<', '>=', '<=', '==', '!='])) {
- throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
- }
-
- $this->operator = $operator;
+ $this->doSetOperator('' === $operator ? '==' : $operator);
}
/**
@@ -80,6 +86,10 @@ class Comparator
*/
public function test($test)
{
+ if (null === $this->target) {
+ trigger_deprecation('symfony/finder', '5.4', 'Calling "%s" without initializing the target is deprecated.', __METHOD__);
+ }
+
switch ($this->operator) {
case '>':
return $test > $this->target;
@@ -95,4 +105,13 @@ class Comparator
return $test == $this->target;
}
+
+ private function doSetOperator(string $operator): void
+ {
+ if (!\in_array($operator, ['>', '<', '>=', '<=', '==', '!='])) {
+ throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
+ }
+
+ $this->operator = $operator;
+ }
}
diff --git a/vendor/symfony/finder/Comparator/DateComparator.php b/vendor/symfony/finder/Comparator/DateComparator.php
index d17c77a..8f651e1 100644
--- a/vendor/symfony/finder/Comparator/DateComparator.php
+++ b/vendor/symfony/finder/Comparator/DateComparator.php
@@ -36,7 +36,7 @@ class DateComparator extends Comparator
throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
}
- $operator = isset($matches[1]) ? $matches[1] : '==';
+ $operator = $matches[1] ?? '==';
if ('since' === $operator || 'after' === $operator) {
$operator = '>';
}
@@ -45,7 +45,6 @@ class DateComparator extends Comparator
$operator = '<';
}
- $this->setOperator($operator);
- $this->setTarget($target);
+ parent::__construct($target, $operator);
}
}
diff --git a/vendor/symfony/finder/Comparator/NumberComparator.php b/vendor/symfony/finder/Comparator/NumberComparator.php
index 80667c9..ff85d96 100644
--- a/vendor/symfony/finder/Comparator/NumberComparator.php
+++ b/vendor/symfony/finder/Comparator/NumberComparator.php
@@ -41,8 +41,8 @@ class NumberComparator extends Comparator
*/
public function __construct(?string $test)
{
- if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
- throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
+ if (null === $test || !preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
+ throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test ?? 'null'));
}
$target = $matches[2];
@@ -73,7 +73,6 @@ class NumberComparator extends Comparator
}
}
- $this->setTarget($target);
- $this->setOperator(isset($matches[1]) ? $matches[1] : '==');
+ parent::__construct($target, $matches[1] ?: '==');
}
}
diff --git a/vendor/symfony/finder/Iterator/LazyIterator.php b/vendor/symfony/finder/Iterator/LazyIterator.php
new file mode 100644
index 0000000..32cc37f
--- /dev/null
+++ b/vendor/symfony/finder/Iterator/LazyIterator.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\Finder\Iterator;
+
+/**
+ * @author Jérémy Derussé
+ *
+ * @internal
+ */
+class LazyIterator implements \IteratorAggregate
+{
+ private $iteratorFactory;
+
+ public function __construct(callable $iteratorFactory)
+ {
+ $this->iteratorFactory = $iteratorFactory;
+ }
+
+ public function getIterator(): \Traversable
+ {
+ yield from ($this->iteratorFactory)();
+ }
+}
diff --git a/vendor/symfony/finder/Iterator/VcsIgnoredFilterIterator.php b/vendor/symfony/finder/Iterator/VcsIgnoredFilterIterator.php
new file mode 100644
index 0000000..e27158c
--- /dev/null
+++ b/vendor/symfony/finder/Iterator/VcsIgnoredFilterIterator.php
@@ -0,0 +1,151 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+use Symfony\Component\Finder\Gitignore;
+
+final class VcsIgnoredFilterIterator extends \FilterIterator
+{
+ /**
+ * @var string
+ */
+ private $baseDir;
+
+ /**
+ * @var array
+ */
+ private $gitignoreFilesCache = [];
+
+ /**
+ * @var array
+ */
+ private $ignoredPathsCache = [];
+
+ public function __construct(\Iterator $iterator, string $baseDir)
+ {
+ $this->baseDir = $this->normalizePath($baseDir);
+
+ parent::__construct($iterator);
+ }
+
+ public function accept(): bool
+ {
+ $file = $this->current();
+
+ $fileRealPath = $this->normalizePath($file->getRealPath());
+
+ return !$this->isIgnored($fileRealPath);
+ }
+
+ private function isIgnored(string $fileRealPath): bool
+ {
+ if (is_dir($fileRealPath) && !str_ends_with($fileRealPath, '/')) {
+ $fileRealPath .= '/';
+ }
+
+ if (isset($this->ignoredPathsCache[$fileRealPath])) {
+ return $this->ignoredPathsCache[$fileRealPath];
+ }
+
+ $ignored = false;
+
+ foreach ($this->parentsDirectoryDownward($fileRealPath) as $parentDirectory) {
+ if ($this->isIgnored($parentDirectory)) {
+ // rules in ignored directories are ignored, no need to check further.
+ break;
+ }
+
+ $fileRelativePath = substr($fileRealPath, \strlen($parentDirectory) + 1);
+
+ if (null === $regexps = $this->readGitignoreFile("{$parentDirectory}/.gitignore")) {
+ continue;
+ }
+
+ [$exclusionRegex, $inclusionRegex] = $regexps;
+
+ if (preg_match($exclusionRegex, $fileRelativePath)) {
+ $ignored = true;
+
+ continue;
+ }
+
+ if (preg_match($inclusionRegex, $fileRelativePath)) {
+ $ignored = false;
+ }
+ }
+
+ return $this->ignoredPathsCache[$fileRealPath] = $ignored;
+ }
+
+ /**
+ * @return list
+ */
+ private function parentsDirectoryDownward(string $fileRealPath): array
+ {
+ $parentDirectories = [];
+
+ $parentDirectory = $fileRealPath;
+
+ while (true) {
+ $newParentDirectory = \dirname($parentDirectory);
+
+ // dirname('/') = '/'
+ if ($newParentDirectory === $parentDirectory) {
+ break;
+ }
+
+ $parentDirectory = $newParentDirectory;
+
+ if (0 !== strpos($parentDirectory, $this->baseDir)) {
+ break;
+ }
+
+ $parentDirectories[] = $parentDirectory;
+ }
+
+ return array_reverse($parentDirectories);
+ }
+
+ /**
+ * @return array{0: string, 1: string}|null
+ */
+ private function readGitignoreFile(string $path): ?array
+ {
+ if (\array_key_exists($path, $this->gitignoreFilesCache)) {
+ return $this->gitignoreFilesCache[$path];
+ }
+
+ if (!file_exists($path)) {
+ return $this->gitignoreFilesCache[$path] = null;
+ }
+
+ if (!is_file($path) || !is_readable($path)) {
+ throw new \RuntimeException("The \"ignoreVCSIgnored\" option cannot be used by the Finder as the \"{$path}\" file is not readable.");
+ }
+
+ $gitignoreFileContent = file_get_contents($path);
+
+ return $this->gitignoreFilesCache[$path] = [
+ Gitignore::toRegex($gitignoreFileContent),
+ Gitignore::toRegexMatchingNegatedPatterns($gitignoreFileContent),
+ ];
+ }
+
+ private function normalizePath(string $path): string
+ {
+ if ('\\' === \DIRECTORY_SEPARATOR) {
+ return str_replace('\\', '/', $path);
+ }
+
+ return $path;
+ }
+}
diff --git a/vendor/symfony/http-client/Internal/CurlClientState.php b/vendor/symfony/http-client/Internal/CurlClientState.php
index 7d51c15..80473fe 100644
--- a/vendor/symfony/http-client/Internal/CurlClientState.php
+++ b/vendor/symfony/http-client/Internal/CurlClientState.php
@@ -36,6 +36,7 @@ final class CurlClientState extends ClientState
public $execCounter = \PHP_INT_MIN;
/** @var LoggerInterface|null */
public $logger;
+ public $performing = false;
public static $curlVersion;
diff --git a/vendor/symfony/http-client/Internal/HttplugWaitLoop.php b/vendor/symfony/http-client/Internal/HttplugWaitLoop.php
index 9f5658f..c61be22 100644
--- a/vendor/symfony/http-client/Internal/HttplugWaitLoop.php
+++ b/vendor/symfony/http-client/Internal/HttplugWaitLoop.php
@@ -120,7 +120,11 @@ final class HttplugWaitLoop
foreach ($response->getHeaders(false) as $name => $values) {
foreach ($values as $value) {
- $psrResponse = $psrResponse->withAddedHeader($name, $value);
+ try {
+ $psrResponse = $psrResponse->withAddedHeader($name, $value);
+ } catch (\InvalidArgumentException $e) {
+ // ignore invalid header
+ }
}
}
diff --git a/vendor/symfony/http-client/Response/AmpResponse.php b/vendor/symfony/http-client/Response/AmpResponse.php
index 6d0ce6e..900c70d 100644
--- a/vendor/symfony/http-client/Response/AmpResponse.php
+++ b/vendor/symfony/http-client/Response/AmpResponse.php
@@ -47,7 +47,6 @@ final class AmpResponse implements ResponseInterface, StreamableInterface
private $multi;
private $options;
- private $canceller;
private $onProgress;
private static $delay;
@@ -73,7 +72,7 @@ final class AmpResponse implements ResponseInterface, StreamableInterface
$info = &$this->info;
$headers = &$this->headers;
- $canceller = $this->canceller = new CancellationTokenSource();
+ $canceller = new CancellationTokenSource();
$handle = &$this->handle;
$info['url'] = (string) $request->getUri();
@@ -358,7 +357,7 @@ final class AmpResponse implements ResponseInterface, StreamableInterface
}
foreach ($originRequest->getRawHeaders() as [$name, $value]) {
- $request->setHeader($name, $value);
+ $request->addHeader($name, $value);
}
if ($request->getUri()->getAuthority() !== $originRequest->getUri()->getAuthority()) {
diff --git a/vendor/symfony/http-client/Response/CurlResponse.php b/vendor/symfony/http-client/Response/CurlResponse.php
index b03a49a..2418203 100644
--- a/vendor/symfony/http-client/Response/CurlResponse.php
+++ b/vendor/symfony/http-client/Response/CurlResponse.php
@@ -32,7 +32,6 @@ final class CurlResponse implements ResponseInterface, StreamableInterface
}
use TransportResponseTrait;
- private static $performing = false;
private $multi;
private $debugBuffer;
@@ -77,17 +76,7 @@ final class CurlResponse implements ResponseInterface, StreamableInterface
}
curl_setopt($ch, \CURLOPT_HEADERFUNCTION, static function ($ch, string $data) use (&$info, &$headers, $options, $multi, $id, &$location, $resolveRedirect, $logger): int {
- if (0 !== substr_compare($data, "\r\n", -2)) {
- return 0;
- }
-
- $len = 0;
-
- foreach (explode("\r\n", substr($data, 0, -2)) as $data) {
- $len += 2 + self::parseHeaderLine($ch, $data, $info, $headers, $options, $multi, $id, $location, $resolveRedirect, $logger);
- }
-
- return $len;
+ return self::parseHeaderLine($ch, $data, $info, $headers, $options, $multi, $id, $location, $resolveRedirect, $logger);
});
if (null === $options) {
@@ -179,7 +168,7 @@ final class CurlResponse implements ResponseInterface, StreamableInterface
unset($multi->pauseExpiries[$id], $multi->openHandles[$id], $multi->handlesActivity[$id]);
curl_setopt($ch, \CURLOPT_PRIVATE, '_0');
- if (self::$performing) {
+ if ($multi->performing) {
return;
}
@@ -237,13 +226,13 @@ final class CurlResponse implements ResponseInterface, StreamableInterface
*/
public function getContent(bool $throw = true): string
{
- $performing = self::$performing;
- self::$performing = $performing || '_0' === curl_getinfo($this->handle, \CURLINFO_PRIVATE);
+ $performing = $this->multi->performing;
+ $this->multi->performing = $performing || '_0' === curl_getinfo($this->handle, \CURLINFO_PRIVATE);
try {
return $this->doGetContent($throw);
} finally {
- self::$performing = $performing;
+ $this->multi->performing = $performing;
}
}
@@ -287,7 +276,7 @@ final class CurlResponse implements ResponseInterface, StreamableInterface
*/
private static function perform(ClientState $multi, array &$responses = null): void
{
- if (self::$performing) {
+ if ($multi->performing) {
if ($responses) {
$response = current($responses);
$multi->handlesActivity[(int) $response->handle][] = null;
@@ -298,7 +287,7 @@ final class CurlResponse implements ResponseInterface, StreamableInterface
}
try {
- self::$performing = true;
+ $multi->performing = true;
++$multi->execCounter;
$active = 0;
while (\CURLM_CALL_MULTI_PERFORM === ($err = curl_multi_exec($multi->handle, $active))) {
@@ -335,7 +324,7 @@ final class CurlResponse implements ResponseInterface, StreamableInterface
$multi->handlesActivity[$id][] = \in_array($result, [\CURLE_OK, \CURLE_TOO_MANY_REDIRECTS], true) || '_0' === $waitFor || curl_getinfo($ch, \CURLINFO_SIZE_DOWNLOAD) === curl_getinfo($ch, \CURLINFO_CONTENT_LENGTH_DOWNLOAD) ? null : new TransportException(ucfirst(curl_error($ch) ?: curl_strerror($result)).sprintf(' for "%s".', curl_getinfo($ch, \CURLINFO_EFFECTIVE_URL)));
}
} finally {
- self::$performing = false;
+ $multi->performing = false;
}
}
@@ -382,19 +371,29 @@ final class CurlResponse implements ResponseInterface, StreamableInterface
*/
private static function parseHeaderLine($ch, string $data, array &$info, array &$headers, ?array $options, CurlClientState $multi, int $id, ?string &$location, ?callable $resolveRedirect, ?LoggerInterface $logger): int
{
+ if (!str_ends_with($data, "\r\n")) {
+ return 0;
+ }
+
$waitFor = @curl_getinfo($ch, \CURLINFO_PRIVATE) ?: '_0';
if ('H' !== $waitFor[0]) {
return \strlen($data); // Ignore HTTP trailers
}
- if ('' !== $data) {
+ $statusCode = curl_getinfo($ch, \CURLINFO_RESPONSE_CODE);
+
+ if ($statusCode !== $info['http_code'] && !preg_match("#^HTTP/\d+(?:\.\d+)? {$statusCode}(?: |\r\n$)#", $data)) {
+ return \strlen($data); // Ignore headers from responses to CONNECT requests
+ }
+
+ if ("\r\n" !== $data) {
// Regular header line: add it to the list
- self::addResponseHeaders([$data], $info, $headers);
+ self::addResponseHeaders([substr($data, 0, -2)], $info, $headers);
if (!str_starts_with($data, 'HTTP/')) {
if (0 === stripos($data, 'Location:')) {
- $location = trim(substr($data, 9));
+ $location = trim(substr($data, 9, -2));
}
return \strlen($data);
@@ -417,7 +416,7 @@ final class CurlResponse implements ResponseInterface, StreamableInterface
// End of headers: handle informational responses, redirects, etc.
- if (200 > $statusCode = curl_getinfo($ch, \CURLINFO_RESPONSE_CODE)) {
+ if (200 > $statusCode) {
$multi->handlesActivity[$id][] = new InformationalChunk($statusCode, $headers);
$location = null;
diff --git a/vendor/symfony/http-client/Response/MockResponse.php b/vendor/symfony/http-client/Response/MockResponse.php
index 6420aa0..2c00108 100644
--- a/vendor/symfony/http-client/Response/MockResponse.php
+++ b/vendor/symfony/http-client/Response/MockResponse.php
@@ -110,6 +110,10 @@ class MockResponse implements ResponseInterface, StreamableInterface
} catch (TransportException $e) {
// ignore errors when canceling
}
+
+ $onProgress = $this->requestOptions['on_progress'] ?? static function () {};
+ $dlSize = isset($this->headers['content-encoding']) || 'HEAD' === ($this->info['http_method'] ?? null) || \in_array($this->info['http_code'], [204, 304], true) ? 0 : (int) ($this->headers['content-length'][0] ?? 0);
+ $onProgress($this->offset, $dlSize, $this->info);
}
/**
diff --git a/vendor/symfony/http-client/Retry/GenericRetryStrategy.php b/vendor/symfony/http-client/Retry/GenericRetryStrategy.php
index ebe10a2..3241a5e 100644
--- a/vendor/symfony/http-client/Retry/GenericRetryStrategy.php
+++ b/vendor/symfony/http-client/Retry/GenericRetryStrategy.php
@@ -102,7 +102,7 @@ class GenericRetryStrategy implements RetryStrategyInterface
$delay = $this->delayMs * $this->multiplier ** $context->getInfo('retry_count');
if ($this->jitter > 0) {
- $randomness = $delay * $this->jitter;
+ $randomness = (int) ($delay * $this->jitter);
$delay = $delay + random_int(-$randomness, +$randomness);
}
diff --git a/vendor/symfony/http-foundation/Exception/BadRequestException.php b/vendor/symfony/http-foundation/Exception/BadRequestException.php
new file mode 100644
index 0000000..e4bb309
--- /dev/null
+++ b/vendor/symfony/http-foundation/Exception/BadRequestException.php
@@ -0,0 +1,19 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\Exception;
+
+/**
+ * Raised when a user sends a malformed request.
+ */
+class BadRequestException extends \UnexpectedValueException implements RequestExceptionInterface
+{
+}
diff --git a/vendor/symfony/http-foundation/Exception/JsonException.php b/vendor/symfony/http-foundation/Exception/JsonException.php
new file mode 100644
index 0000000..5990e76
--- /dev/null
+++ b/vendor/symfony/http-foundation/Exception/JsonException.php
@@ -0,0 +1,21 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\Exception;
+
+/**
+ * Thrown by Request::toArray() when the content cannot be JSON-decoded.
+ *
+ * @author Tobias Nyholm
+ */
+final class JsonException extends \UnexpectedValueException implements RequestExceptionInterface
+{
+}
diff --git a/vendor/symfony/http-foundation/Exception/SessionNotFoundException.php b/vendor/symfony/http-foundation/Exception/SessionNotFoundException.php
new file mode 100644
index 0000000..9c719aa
--- /dev/null
+++ b/vendor/symfony/http-foundation/Exception/SessionNotFoundException.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\HttpFoundation\Exception;
+
+/**
+ * Raised when a session does not exists. This happens in the following cases:
+ * - the session is not enabled
+ * - attempt to read a session outside a request context (ie. cli script).
+ *
+ * @author Jérémy Derussé
+ */
+class SessionNotFoundException extends \LogicException implements RequestExceptionInterface
+{
+ public function __construct(string $message = 'There is currently no session available.', int $code = 0, \Throwable $previous = null)
+ {
+ parent::__construct($message, $code, $previous);
+ }
+}
diff --git a/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php b/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php
index 3b8e41d..136d2a9 100644
--- a/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php
+++ b/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php
@@ -18,10 +18,7 @@ namespace Symfony\Component\HttpFoundation\File\Exception;
*/
class AccessDeniedException extends FileException
{
- /**
- * @param string $path The path to the accessed file
- */
- public function __construct($path)
+ public function __construct(string $path)
{
parent::__construct(sprintf('The file %s could not be accessed', $path));
}
diff --git a/vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php b/vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php
new file mode 100644
index 0000000..c49f53a
--- /dev/null
+++ b/vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php
@@ -0,0 +1,21 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\File\Exception;
+
+/**
+ * Thrown when an UPLOAD_ERR_CANT_WRITE error occurred with UploadedFile.
+ *
+ * @author Florent Mata
+ */
+class CannotWriteFileException extends FileException
+{
+}
diff --git a/vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php b/vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php
new file mode 100644
index 0000000..ed83499
--- /dev/null
+++ b/vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php
@@ -0,0 +1,21 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\File\Exception;
+
+/**
+ * Thrown when an UPLOAD_ERR_EXTENSION error occurred with UploadedFile.
+ *
+ * @author Florent Mata
+ */
+class ExtensionFileException extends FileException
+{
+}
diff --git a/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php b/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php
index bfcc37e..31bdf68 100644
--- a/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php
+++ b/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php
@@ -18,10 +18,7 @@ namespace Symfony\Component\HttpFoundation\File\Exception;
*/
class FileNotFoundException extends FileException
{
- /**
- * @param string $path The path to the file that was not found
- */
- public function __construct($path)
+ public function __construct(string $path)
{
parent::__construct(sprintf('The file "%s" does not exist', $path));
}
diff --git a/vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php b/vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php
new file mode 100644
index 0000000..8741be0
--- /dev/null
+++ b/vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php
@@ -0,0 +1,21 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\File\Exception;
+
+/**
+ * Thrown when an UPLOAD_ERR_FORM_SIZE error occurred with UploadedFile.
+ *
+ * @author Florent Mata
+ */
+class FormSizeFileException extends FileException
+{
+}
diff --git a/vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php b/vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php
new file mode 100644
index 0000000..c8fde61
--- /dev/null
+++ b/vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php
@@ -0,0 +1,21 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\File\Exception;
+
+/**
+ * Thrown when an UPLOAD_ERR_INI_SIZE error occurred with UploadedFile.
+ *
+ * @author Florent Mata
+ */
+class IniSizeFileException extends FileException
+{
+}
diff --git a/vendor/symfony/http-foundation/File/Exception/NoFileException.php b/vendor/symfony/http-foundation/File/Exception/NoFileException.php
new file mode 100644
index 0000000..4b48cc7
--- /dev/null
+++ b/vendor/symfony/http-foundation/File/Exception/NoFileException.php
@@ -0,0 +1,21 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\File\Exception;
+
+/**
+ * Thrown when an UPLOAD_ERR_NO_FILE error occurred with UploadedFile.
+ *
+ * @author Florent Mata
+ */
+class NoFileException extends FileException
+{
+}
diff --git a/vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php b/vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php
new file mode 100644
index 0000000..bdead2d
--- /dev/null
+++ b/vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php
@@ -0,0 +1,21 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\File\Exception;
+
+/**
+ * Thrown when an UPLOAD_ERR_NO_TMP_DIR error occurred with UploadedFile.
+ *
+ * @author Florent Mata
+ */
+class NoTmpDirFileException extends FileException
+{
+}
diff --git a/vendor/symfony/http-foundation/File/Exception/PartialFileException.php b/vendor/symfony/http-foundation/File/Exception/PartialFileException.php
new file mode 100644
index 0000000..4641efb
--- /dev/null
+++ b/vendor/symfony/http-foundation/File/Exception/PartialFileException.php
@@ -0,0 +1,21 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\File\Exception;
+
+/**
+ * Thrown when an UPLOAD_ERR_PARTIAL error occurred with UploadedFile.
+ *
+ * @author Florent Mata
+ */
+class PartialFileException extends FileException
+{
+}
diff --git a/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php b/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php
index 62005d3..8533f99 100644
--- a/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php
+++ b/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php
@@ -13,8 +13,8 @@ namespace Symfony\Component\HttpFoundation\File\Exception;
class UnexpectedTypeException extends FileException
{
- public function __construct($value, $expectedType)
+ public function __construct($value, string $expectedType)
{
- parent::__construct(sprintf('Expected argument of type %s, %s given', $expectedType, \is_object($value) ? \get_class($value) : \gettype($value)));
+ parent::__construct(sprintf('Expected argument of type %s, %s given', $expectedType, get_debug_type($value)));
}
}
diff --git a/vendor/symfony/http-foundation/File/File.php b/vendor/symfony/http-foundation/File/File.php
index 3422058..d941577 100644
--- a/vendor/symfony/http-foundation/File/File.php
+++ b/vendor/symfony/http-foundation/File/File.php
@@ -13,8 +13,7 @@ namespace Symfony\Component\HttpFoundation\File;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
-use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser;
-use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser;
+use Symfony\Component\Mime\MimeTypes;
/**
* A file in the file system.
@@ -31,7 +30,7 @@ class File extends \SplFileInfo
*
* @throws FileNotFoundException If the given path is not a file
*/
- public function __construct($path, $checkPath = true)
+ public function __construct(string $path, bool $checkPath = true)
{
if ($checkPath && !is_file($path)) {
throw new FileNotFoundException($path);
@@ -48,56 +47,59 @@ class File extends \SplFileInfo
* This method uses the mime type as guessed by getMimeType()
* to guess the file extension.
*
- * @return string|null The guessed extension or null if it cannot be guessed
+ * @return string|null
*
- * @see ExtensionGuesser
+ * @see MimeTypes
* @see getMimeType()
*/
public function guessExtension()
{
- $type = $this->getMimeType();
- $guesser = ExtensionGuesser::getInstance();
+ if (!class_exists(MimeTypes::class)) {
+ throw new \LogicException('You cannot guess the extension as the Mime component is not installed. Try running "composer require symfony/mime".');
+ }
- return $guesser->guess($type);
+ return MimeTypes::getDefault()->getExtensions($this->getMimeType())[0] ?? null;
}
/**
* Returns the mime type of the file.
*
- * The mime type is guessed using a MimeTypeGuesser instance, which uses finfo(),
- * mime_content_type() and the system binary "file" (in this order), depending on
- * which of those are available.
+ * The mime type is guessed using a MimeTypeGuesserInterface instance,
+ * which uses finfo_file() then the "file" system binary,
+ * depending on which of those are available.
*
- * @return string|null The guessed mime type (e.g. "application/pdf")
+ * @return string|null
*
- * @see MimeTypeGuesser
+ * @see MimeTypes
*/
public function getMimeType()
{
- $guesser = MimeTypeGuesser::getInstance();
+ if (!class_exists(MimeTypes::class)) {
+ throw new \LogicException('You cannot guess the mime type as the Mime component is not installed. Try running "composer require symfony/mime".');
+ }
- return $guesser->guess($this->getPathname());
+ return MimeTypes::getDefault()->guessMimeType($this->getPathname());
}
/**
* Moves the file to a new location.
*
- * @param string $directory The destination folder
- * @param string $name The new file name
- *
- * @return self A File object representing the new file
+ * @return self
*
* @throws FileException if the target file could not be created
*/
- public function move($directory, $name = null)
+ public function move(string $directory, string $name = null)
{
$target = $this->getTargetFile($directory, $name);
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
- $renamed = rename($this->getPathname(), $target);
- restore_error_handler();
+ try {
+ $renamed = rename($this->getPathname(), $target);
+ } finally {
+ restore_error_handler();
+ }
if (!$renamed) {
- throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error)));
+ throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, strip_tags($error)));
}
@chmod($target, 0666 & ~umask());
@@ -105,14 +107,28 @@ class File extends \SplFileInfo
return $target;
}
- protected function getTargetFile($directory, $name = null)
+ public function getContent(): string
+ {
+ $content = file_get_contents($this->getPathname());
+
+ if (false === $content) {
+ throw new FileException(sprintf('Could not get the content of the file "%s".', $this->getPathname()));
+ }
+
+ return $content;
+ }
+
+ /**
+ * @return self
+ */
+ protected function getTargetFile(string $directory, string $name = null)
{
if (!is_dir($directory)) {
if (false === @mkdir($directory, 0777, true) && !is_dir($directory)) {
- throw new FileException(sprintf('Unable to create the "%s" directory', $directory));
+ throw new FileException(sprintf('Unable to create the "%s" directory.', $directory));
}
} elseif (!is_writable($directory)) {
- throw new FileException(sprintf('Unable to write in the "%s" directory', $directory));
+ throw new FileException(sprintf('Unable to write in the "%s" directory.', $directory));
}
$target = rtrim($directory, '/\\').\DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : $this->getName($name));
@@ -123,11 +139,9 @@ class File extends \SplFileInfo
/**
* Returns locale independent base name of the given path.
*
- * @param string $name The new file name
- *
- * @return string containing
+ * @return string
*/
- protected function getName($name)
+ protected function getName(string $name)
{
$originalName = str_replace('\\', '/', $name);
$pos = strrpos($originalName, '/');
diff --git a/vendor/symfony/http-foundation/File/Stream.php b/vendor/symfony/http-foundation/File/Stream.php
index 69ae74c..cef3e03 100644
--- a/vendor/symfony/http-foundation/File/Stream.php
+++ b/vendor/symfony/http-foundation/File/Stream.php
@@ -20,7 +20,10 @@ class Stream extends File
{
/**
* {@inheritdoc}
+ *
+ * @return int|false
*/
+ #[\ReturnTypeWillChange]
public function getSize()
{
return false;
diff --git a/vendor/symfony/http-foundation/File/UploadedFile.php b/vendor/symfony/http-foundation/File/UploadedFile.php
index 86153ed..fcc6299 100644
--- a/vendor/symfony/http-foundation/File/UploadedFile.php
+++ b/vendor/symfony/http-foundation/File/UploadedFile.php
@@ -11,9 +11,16 @@
namespace Symfony\Component\HttpFoundation\File;
+use Symfony\Component\HttpFoundation\File\Exception\CannotWriteFileException;
+use Symfony\Component\HttpFoundation\File\Exception\ExtensionFileException;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
-use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser;
+use Symfony\Component\HttpFoundation\File\Exception\FormSizeFileException;
+use Symfony\Component\HttpFoundation\File\Exception\IniSizeFileException;
+use Symfony\Component\HttpFoundation\File\Exception\NoFileException;
+use Symfony\Component\HttpFoundation\File\Exception\NoTmpDirFileException;
+use Symfony\Component\HttpFoundation\File\Exception\PartialFileException;
+use Symfony\Component\Mime\MimeTypes;
/**
* A file uploaded through a form.
@@ -24,10 +31,9 @@ use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser;
*/
class UploadedFile extends File
{
- private $test = false;
+ private $test;
private $originalName;
private $mimeType;
- private $size;
private $error;
/**
@@ -47,7 +53,6 @@ class UploadedFile extends File
* @param string $path The full temporary path to the file
* @param string $originalName The original file name of the uploaded file
* @param string|null $mimeType The type of the file as provided by PHP; null defaults to application/octet-stream
- * @param int|null $size The file size provided by the uploader
* @param int|null $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants); null defaults to UPLOAD_ERR_OK
* @param bool $test Whether the test mode is active
* Local files are used in test mode hence the code should not enforce HTTP uploads
@@ -55,15 +60,14 @@ class UploadedFile extends File
* @throws FileException If file_uploads is disabled
* @throws FileNotFoundException If the file does not exist
*/
- public function __construct($path, $originalName, $mimeType = null, $size = null, $error = null, $test = false)
+ public function __construct(string $path, string $originalName, string $mimeType = null, int $error = null, bool $test = false)
{
$this->originalName = $this->getName($originalName);
$this->mimeType = $mimeType ?: 'application/octet-stream';
- $this->size = $size;
- $this->error = $error ?: UPLOAD_ERR_OK;
- $this->test = (bool) $test;
+ $this->error = $error ?: \UPLOAD_ERR_OK;
+ $this->test = $test;
- parent::__construct($path, UPLOAD_ERR_OK === $this->error);
+ parent::__construct($path, \UPLOAD_ERR_OK === $this->error);
}
/**
@@ -72,7 +76,7 @@ class UploadedFile extends File
* It is extracted from the request from which the file has been uploaded.
* Then it should not be considered as a safe value.
*
- * @return string|null The original name
+ * @return string
*/
public function getClientOriginalName()
{
@@ -85,11 +89,11 @@ class UploadedFile extends File
* It is extracted from the original file name that was uploaded.
* Then it should not be considered as a safe value.
*
- * @return string The extension
+ * @return string
*/
public function getClientOriginalExtension()
{
- return pathinfo($this->originalName, PATHINFO_EXTENSION);
+ return pathinfo($this->originalName, \PATHINFO_EXTENSION);
}
/**
@@ -101,7 +105,7 @@ class UploadedFile extends File
* For a trusted mime type, use getMimeType() instead (which guesses the mime
* type based on the file content).
*
- * @return string|null The mime type
+ * @return string
*
* @see getMimeType()
*/
@@ -122,30 +126,18 @@ class UploadedFile extends File
* For a trusted extension, use guessExtension() instead (which guesses
* the extension based on the guessed mime type for the file).
*
- * @return string|null The guessed extension or null if it cannot be guessed
+ * @return string|null
*
* @see guessExtension()
* @see getClientMimeType()
*/
public function guessClientExtension()
{
- $type = $this->getClientMimeType();
- $guesser = ExtensionGuesser::getInstance();
+ if (!class_exists(MimeTypes::class)) {
+ throw new \LogicException('You cannot guess the extension as the Mime component is not installed. Try running "composer require symfony/mime".');
+ }
- return $guesser->guess($type);
- }
-
- /**
- * Returns the file size.
- *
- * It is extracted from the request from which the file has been uploaded.
- * Then it should not be considered as a safe value.
- *
- * @return int|null The file size
- */
- public function getClientSize()
- {
- return $this->size;
+ return MimeTypes::getDefault()->getExtensions($this->getClientMimeType())[0] ?? null;
}
/**
@@ -154,7 +146,7 @@ class UploadedFile extends File
* If the upload was successful, the constant UPLOAD_ERR_OK is returned.
* Otherwise one of the other UPLOAD_ERR_XXX constants is returned.
*
- * @return int The upload error
+ * @return int
*/
public function getError()
{
@@ -162,13 +154,13 @@ class UploadedFile extends File
}
/**
- * Returns whether the file was uploaded successfully.
+ * Returns whether the file has been uploaded with HTTP and no error occurred.
*
- * @return bool True if the file has been uploaded with HTTP and no error occurred
+ * @return bool
*/
public function isValid()
{
- $isOk = UPLOAD_ERR_OK === $this->error;
+ $isOk = \UPLOAD_ERR_OK === $this->error;
return $this->test ? $isOk : $isOk && is_uploaded_file($this->getPathname());
}
@@ -176,14 +168,11 @@ class UploadedFile extends File
/**
* Moves the file to a new location.
*
- * @param string $directory The destination folder
- * @param string $name The new file name
- *
- * @return File A File object representing the new file
+ * @return File
*
* @throws FileException if, for any reason, the file could not have been moved
*/
- public function move($directory, $name = null)
+ public function move(string $directory, string $name = null)
{
if ($this->isValid()) {
if ($this->test) {
@@ -193,10 +182,13 @@ class UploadedFile extends File
$target = $this->getTargetFile($directory, $name);
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
- $moved = move_uploaded_file($this->getPathname(), $target);
- restore_error_handler();
+ try {
+ $moved = move_uploaded_file($this->getPathname(), $target);
+ } finally {
+ restore_error_handler();
+ }
if (!$moved) {
- throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error)));
+ throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, strip_tags($error)));
}
@chmod($target, 0666 & ~umask());
@@ -204,28 +196,45 @@ class UploadedFile extends File
return $target;
}
+ switch ($this->error) {
+ case \UPLOAD_ERR_INI_SIZE:
+ throw new IniSizeFileException($this->getErrorMessage());
+ case \UPLOAD_ERR_FORM_SIZE:
+ throw new FormSizeFileException($this->getErrorMessage());
+ case \UPLOAD_ERR_PARTIAL:
+ throw new PartialFileException($this->getErrorMessage());
+ case \UPLOAD_ERR_NO_FILE:
+ throw new NoFileException($this->getErrorMessage());
+ case \UPLOAD_ERR_CANT_WRITE:
+ throw new CannotWriteFileException($this->getErrorMessage());
+ case \UPLOAD_ERR_NO_TMP_DIR:
+ throw new NoTmpDirFileException($this->getErrorMessage());
+ case \UPLOAD_ERR_EXTENSION:
+ throw new ExtensionFileException($this->getErrorMessage());
+ }
+
throw new FileException($this->getErrorMessage());
}
/**
* Returns the maximum size of an uploaded file as configured in php.ini.
*
- * @return int The maximum size of an uploaded file in bytes
+ * @return int|float The maximum size of an uploaded file in bytes (returns float if size > PHP_INT_MAX)
*/
public static function getMaxFilesize()
{
- $sizePostMax = self::parseFilesize(ini_get('post_max_size'));
- $sizeUploadMax = self::parseFilesize(ini_get('upload_max_filesize'));
+ $sizePostMax = self::parseFilesize(\ini_get('post_max_size'));
+ $sizeUploadMax = self::parseFilesize(\ini_get('upload_max_filesize'));
- return min($sizePostMax ?: PHP_INT_MAX, $sizeUploadMax ?: PHP_INT_MAX);
+ return min($sizePostMax ?: \PHP_INT_MAX, $sizeUploadMax ?: \PHP_INT_MAX);
}
/**
* Returns the given size from an ini value in bytes.
*
- * @return int The given size in bytes
+ * @return int|float Returns float if size > PHP_INT_MAX
*/
- private static function parseFilesize($size)
+ private static function parseFilesize(string $size)
{
if ('' === $size) {
return 0;
@@ -234,9 +243,9 @@ class UploadedFile extends File
$size = strtolower($size);
$max = ltrim($size, '+');
- if (0 === strpos($max, '0x')) {
+ if (str_starts_with($max, '0x')) {
$max = \intval($max, 16);
- } elseif (0 === strpos($max, '0')) {
+ } elseif (str_starts_with($max, '0')) {
$max = \intval($max, 8);
} else {
$max = (int) $max;
@@ -244,11 +253,11 @@ class UploadedFile extends File
switch (substr($size, -1)) {
case 't': $max *= 1024;
- // no break
+ // no break
case 'g': $max *= 1024;
- // no break
+ // no break
case 'm': $max *= 1024;
- // no break
+ // no break
case 'k': $max *= 1024;
}
@@ -258,23 +267,23 @@ class UploadedFile extends File
/**
* Returns an informative upload error message.
*
- * @return string The error message regarding the specified error code
+ * @return string
*/
public function getErrorMessage()
{
static $errors = [
- UPLOAD_ERR_INI_SIZE => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d KiB).',
- UPLOAD_ERR_FORM_SIZE => 'The file "%s" exceeds the upload limit defined in your form.',
- UPLOAD_ERR_PARTIAL => 'The file "%s" was only partially uploaded.',
- UPLOAD_ERR_NO_FILE => 'No file was uploaded.',
- UPLOAD_ERR_CANT_WRITE => 'The file "%s" could not be written on disk.',
- UPLOAD_ERR_NO_TMP_DIR => 'File could not be uploaded: missing temporary directory.',
- UPLOAD_ERR_EXTENSION => 'File upload was stopped by a PHP extension.',
+ \UPLOAD_ERR_INI_SIZE => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d KiB).',
+ \UPLOAD_ERR_FORM_SIZE => 'The file "%s" exceeds the upload limit defined in your form.',
+ \UPLOAD_ERR_PARTIAL => 'The file "%s" was only partially uploaded.',
+ \UPLOAD_ERR_NO_FILE => 'No file was uploaded.',
+ \UPLOAD_ERR_CANT_WRITE => 'The file "%s" could not be written on disk.',
+ \UPLOAD_ERR_NO_TMP_DIR => 'File could not be uploaded: missing temporary directory.',
+ \UPLOAD_ERR_EXTENSION => 'File upload was stopped by a PHP extension.',
];
$errorCode = $this->error;
- $maxFilesize = UPLOAD_ERR_INI_SIZE === $errorCode ? self::getMaxFilesize() / 1024 : 0;
- $message = isset($errors[$errorCode]) ? $errors[$errorCode] : 'The file "%s" was not uploaded due to an unknown error.';
+ $maxFilesize = \UPLOAD_ERR_INI_SIZE === $errorCode ? self::getMaxFilesize() / 1024 : 0;
+ $message = $errors[$errorCode] ?? 'The file "%s" was not uploaded due to an unknown error.';
return sprintf($message, $this->getClientOriginalName(), $maxFilesize);
}
diff --git a/vendor/symfony/http-foundation/HeaderUtils.php b/vendor/symfony/http-foundation/HeaderUtils.php
new file mode 100644
index 0000000..1d56be0
--- /dev/null
+++ b/vendor/symfony/http-foundation/HeaderUtils.php
@@ -0,0 +1,293 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation;
+
+/**
+ * HTTP header utility functions.
+ *
+ * @author Christian Schmidt
+ */
+class HeaderUtils
+{
+ public const DISPOSITION_ATTACHMENT = 'attachment';
+ public const DISPOSITION_INLINE = 'inline';
+
+ /**
+ * This class should not be instantiated.
+ */
+ private function __construct()
+ {
+ }
+
+ /**
+ * Splits an HTTP header by one or more separators.
+ *
+ * Example:
+ *
+ * HeaderUtils::split("da, en-gb;q=0.8", ",;")
+ * // => ['da'], ['en-gb', 'q=0.8']]
+ *
+ * @param string $separators List of characters to split on, ordered by
+ * precedence, e.g. ",", ";=", or ",;="
+ *
+ * @return array Nested array with as many levels as there are characters in
+ * $separators
+ */
+ public static function split(string $header, string $separators): array
+ {
+ $quotedSeparators = preg_quote($separators, '/');
+
+ preg_match_all('
+ /
+ (?!\s)
+ (?:
+ # quoted-string
+ "(?:[^"\\\\]|\\\\.)*(?:"|\\\\|$)
+ |
+ # token
+ [^"'.$quotedSeparators.']+
+ )+
+ (?['.$quotedSeparators.'])
+ \s*
+ /x', trim($header), $matches, \PREG_SET_ORDER);
+
+ return self::groupParts($matches, $separators);
+ }
+
+ /**
+ * Combines an array of arrays into one associative array.
+ *
+ * Each of the nested arrays should have one or two elements. The first
+ * value will be used as the keys in the associative array, and the second
+ * will be used as the values, or true if the nested array only contains one
+ * element. Array keys are lowercased.
+ *
+ * Example:
+ *
+ * HeaderUtils::combine([["foo", "abc"], ["bar"]])
+ * // => ["foo" => "abc", "bar" => true]
+ */
+ public static function combine(array $parts): array
+ {
+ $assoc = [];
+ foreach ($parts as $part) {
+ $name = strtolower($part[0]);
+ $value = $part[1] ?? true;
+ $assoc[$name] = $value;
+ }
+
+ return $assoc;
+ }
+
+ /**
+ * Joins an associative array into a string for use in an HTTP header.
+ *
+ * The key and value of each entry are joined with "=", and all entries
+ * are joined with the specified separator and an additional space (for
+ * readability). Values are quoted if necessary.
+ *
+ * Example:
+ *
+ * HeaderUtils::toString(["foo" => "abc", "bar" => true, "baz" => "a b c"], ",")
+ * // => 'foo=abc, bar, baz="a b c"'
+ */
+ public static function toString(array $assoc, string $separator): string
+ {
+ $parts = [];
+ foreach ($assoc as $name => $value) {
+ if (true === $value) {
+ $parts[] = $name;
+ } else {
+ $parts[] = $name.'='.self::quote($value);
+ }
+ }
+
+ return implode($separator.' ', $parts);
+ }
+
+ /**
+ * Encodes a string as a quoted string, if necessary.
+ *
+ * If a string contains characters not allowed by the "token" construct in
+ * the HTTP specification, it is backslash-escaped and enclosed in quotes
+ * to match the "quoted-string" construct.
+ */
+ public static function quote(string $s): string
+ {
+ if (preg_match('/^[a-z0-9!#$%&\'*.^_`|~-]+$/i', $s)) {
+ return $s;
+ }
+
+ return '"'.addcslashes($s, '"\\"').'"';
+ }
+
+ /**
+ * Decodes a quoted string.
+ *
+ * If passed an unquoted string that matches the "token" construct (as
+ * defined in the HTTP specification), it is passed through verbatimly.
+ */
+ public static function unquote(string $s): string
+ {
+ return preg_replace('/\\\\(.)|"/', '$1', $s);
+ }
+
+ /**
+ * Generates an HTTP Content-Disposition field-value.
+ *
+ * @param string $disposition One of "inline" or "attachment"
+ * @param string $filename A unicode string
+ * @param string $filenameFallback A string containing only ASCII characters that
+ * is semantically equivalent to $filename. If the filename is already ASCII,
+ * it can be omitted, or just copied from $filename
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @see RFC 6266
+ */
+ public static function makeDisposition(string $disposition, string $filename, string $filenameFallback = ''): string
+ {
+ if (!\in_array($disposition, [self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE])) {
+ throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE));
+ }
+
+ if ('' === $filenameFallback) {
+ $filenameFallback = $filename;
+ }
+
+ // filenameFallback is not ASCII.
+ if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) {
+ throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.');
+ }
+
+ // percent characters aren't safe in fallback.
+ if (str_contains($filenameFallback, '%')) {
+ throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.');
+ }
+
+ // path separators aren't allowed in either.
+ if (str_contains($filename, '/') || str_contains($filename, '\\') || str_contains($filenameFallback, '/') || str_contains($filenameFallback, '\\')) {
+ throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.');
+ }
+
+ $params = ['filename' => $filenameFallback];
+ if ($filename !== $filenameFallback) {
+ $params['filename*'] = "utf-8''".rawurlencode($filename);
+ }
+
+ return $disposition.'; '.self::toString($params, ';');
+ }
+
+ /**
+ * Like parse_str(), but preserves dots in variable names.
+ */
+ public static function parseQuery(string $query, bool $ignoreBrackets = false, string $separator = '&'): array
+ {
+ $q = [];
+
+ foreach (explode($separator, $query) as $v) {
+ if (false !== $i = strpos($v, "\0")) {
+ $v = substr($v, 0, $i);
+ }
+
+ if (false === $i = strpos($v, '=')) {
+ $k = urldecode($v);
+ $v = '';
+ } else {
+ $k = urldecode(substr($v, 0, $i));
+ $v = substr($v, $i);
+ }
+
+ if (false !== $i = strpos($k, "\0")) {
+ $k = substr($k, 0, $i);
+ }
+
+ $k = ltrim($k, ' ');
+
+ if ($ignoreBrackets) {
+ $q[$k][] = urldecode(substr($v, 1));
+
+ continue;
+ }
+
+ if (false === $i = strpos($k, '[')) {
+ $q[] = bin2hex($k).$v;
+ } else {
+ $q[] = bin2hex(substr($k, 0, $i)).rawurlencode(substr($k, $i)).$v;
+ }
+ }
+
+ if ($ignoreBrackets) {
+ return $q;
+ }
+
+ parse_str(implode('&', $q), $q);
+
+ $query = [];
+
+ foreach ($q as $k => $v) {
+ if (false !== $i = strpos($k, '_')) {
+ $query[substr_replace($k, hex2bin(substr($k, 0, $i)).'[', 0, 1 + $i)] = $v;
+ } else {
+ $query[hex2bin($k)] = $v;
+ }
+ }
+
+ return $query;
+ }
+
+ private static function groupParts(array $matches, string $separators, bool $first = true): array
+ {
+ $separator = $separators[0];
+ $partSeparators = substr($separators, 1);
+
+ $i = 0;
+ $partMatches = [];
+ $previousMatchWasSeparator = false;
+ foreach ($matches as $match) {
+ if (!$first && $previousMatchWasSeparator && isset($match['separator']) && $match['separator'] === $separator) {
+ $previousMatchWasSeparator = true;
+ $partMatches[$i][] = $match;
+ } elseif (isset($match['separator']) && $match['separator'] === $separator) {
+ $previousMatchWasSeparator = true;
+ ++$i;
+ } else {
+ $previousMatchWasSeparator = false;
+ $partMatches[$i][] = $match;
+ }
+ }
+
+ $parts = [];
+ if ($partSeparators) {
+ foreach ($partMatches as $matches) {
+ $parts[] = self::groupParts($matches, $partSeparators, false);
+ }
+ } else {
+ foreach ($partMatches as $matches) {
+ $parts[] = self::unquote($matches[0][0]);
+ }
+
+ if (!$first && 2 < \count($parts)) {
+ $parts = [
+ $parts[0],
+ implode($separator, \array_slice($parts, 1)),
+ ];
+ }
+ }
+
+ return $parts;
+ }
+}
diff --git a/vendor/symfony/http-foundation/InputBag.php b/vendor/symfony/http-foundation/InputBag.php
new file mode 100644
index 0000000..a9d3cd8
--- /dev/null
+++ b/vendor/symfony/http-foundation/InputBag.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\HttpFoundation;
+
+use Symfony\Component\HttpFoundation\Exception\BadRequestException;
+
+/**
+ * InputBag is a container for user input values such as $_GET, $_POST, $_REQUEST, and $_COOKIE.
+ *
+ * @author Saif Eddin Gmati
+ */
+final class InputBag extends ParameterBag
+{
+ /**
+ * Returns a scalar input value by name.
+ *
+ * @param string|int|float|bool|null $default The default value if the input key does not exist
+ *
+ * @return string|int|float|bool|null
+ */
+ public function get(string $key, $default = null)
+ {
+ if (null !== $default && !\is_scalar($default) && !(\is_object($default) && method_exists($default, '__toString'))) {
+ trigger_deprecation('symfony/http-foundation', '5.1', 'Passing a non-scalar value as 2nd argument to "%s()" is deprecated, pass a scalar or null instead.', __METHOD__);
+ }
+
+ $value = parent::get($key, $this);
+
+ if (null !== $value && $this !== $value && !\is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
+ trigger_deprecation('symfony/http-foundation', '5.1', 'Retrieving a non-scalar value from "%s()" is deprecated, and will throw a "%s" exception in Symfony 6.0, use "%s::all($key)" instead.', __METHOD__, BadRequestException::class, __CLASS__);
+ }
+
+ return $this === $value ? $default : $value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function all(string $key = null): array
+ {
+ return parent::all($key);
+ }
+
+ /**
+ * Replaces the current input values by a new set.
+ */
+ public function replace(array $inputs = [])
+ {
+ $this->parameters = [];
+ $this->add($inputs);
+ }
+
+ /**
+ * Adds input values.
+ */
+ public function add(array $inputs = [])
+ {
+ foreach ($inputs as $input => $value) {
+ $this->set($input, $value);
+ }
+ }
+
+ /**
+ * Sets an input by name.
+ *
+ * @param string|int|float|bool|array|null $value
+ */
+ public function set(string $key, $value)
+ {
+ if (null !== $value && !\is_scalar($value) && !\is_array($value) && !method_exists($value, '__toString')) {
+ trigger_deprecation('symfony/http-foundation', '5.1', 'Passing "%s" as a 2nd Argument to "%s()" is deprecated, pass a scalar, array, or null instead.', get_debug_type($value), __METHOD__);
+ }
+
+ $this->parameters[$key] = $value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function filter(string $key, $default = null, int $filter = \FILTER_DEFAULT, $options = [])
+ {
+ $value = $this->has($key) ? $this->all()[$key] : $default;
+
+ // Always turn $options into an array - this allows filter_var option shortcuts.
+ if (!\is_array($options) && $options) {
+ $options = ['flags' => $options];
+ }
+
+ if (\is_array($value) && !(($options['flags'] ?? 0) & (\FILTER_REQUIRE_ARRAY | \FILTER_FORCE_ARRAY))) {
+ trigger_deprecation('symfony/http-foundation', '5.1', 'Filtering an array value with "%s()" without passing the FILTER_REQUIRE_ARRAY or FILTER_FORCE_ARRAY flag is deprecated', __METHOD__);
+
+ if (!isset($options['flags'])) {
+ $options['flags'] = \FILTER_REQUIRE_ARRAY;
+ }
+ }
+
+ if ((\FILTER_CALLBACK & $filter) && !(($options['options'] ?? null) instanceof \Closure)) {
+ trigger_deprecation('symfony/http-foundation', '5.2', 'Not passing a Closure together with FILTER_CALLBACK to "%s()" is deprecated. Wrap your filter in a closure instead.', __METHOD__);
+ // throw new \InvalidArgumentException(sprintf('A Closure must be passed to "%s()" when FILTER_CALLBACK is used, "%s" given.', __METHOD__, get_debug_type($options['options'] ?? null)));
+ }
+
+ return filter_var($value, $filter, $options);
+ }
+}
diff --git a/vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php b/vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php
new file mode 100644
index 0000000..a6dd993
--- /dev/null
+++ b/vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php
@@ -0,0 +1,71 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\RateLimiter;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\RateLimiter\LimiterInterface;
+use Symfony\Component\RateLimiter\Policy\NoLimiter;
+use Symfony\Component\RateLimiter\RateLimit;
+
+/**
+ * An implementation of RequestRateLimiterInterface that
+ * fits most use-cases.
+ *
+ * @author Wouter de Jong
+ */
+abstract class AbstractRequestRateLimiter implements RequestRateLimiterInterface
+{
+ public function consume(Request $request): RateLimit
+ {
+ $limiters = $this->getLimiters($request);
+ if (0 === \count($limiters)) {
+ $limiters = [new NoLimiter()];
+ }
+
+ $minimalRateLimit = null;
+ foreach ($limiters as $limiter) {
+ $rateLimit = $limiter->consume(1);
+
+ $minimalRateLimit = $minimalRateLimit ? self::getMinimalRateLimit($minimalRateLimit, $rateLimit) : $rateLimit;
+ }
+
+ return $minimalRateLimit;
+ }
+
+ public function reset(Request $request): void
+ {
+ foreach ($this->getLimiters($request) as $limiter) {
+ $limiter->reset();
+ }
+ }
+
+ /**
+ * @return LimiterInterface[] a set of limiters using keys extracted from the request
+ */
+ abstract protected function getLimiters(Request $request): array;
+
+ private static function getMinimalRateLimit(RateLimit $first, RateLimit $second): RateLimit
+ {
+ if ($first->isAccepted() !== $second->isAccepted()) {
+ return $first->isAccepted() ? $second : $first;
+ }
+
+ $firstRemainingTokens = $first->getRemainingTokens();
+ $secondRemainingTokens = $second->getRemainingTokens();
+
+ if ($firstRemainingTokens === $secondRemainingTokens) {
+ return $first->getRetryAfter() < $second->getRetryAfter() ? $second : $first;
+ }
+
+ return $firstRemainingTokens > $secondRemainingTokens ? $second : $first;
+ }
+}
diff --git a/vendor/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php b/vendor/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php
new file mode 100644
index 0000000..4c87a40
--- /dev/null
+++ b/vendor/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.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\HttpFoundation\RateLimiter;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\RateLimiter\RateLimit;
+
+/**
+ * A special type of limiter that deals with requests.
+ *
+ * This allows to limit on different types of information
+ * from the requests.
+ *
+ * @author Wouter de Jong
+ */
+interface RequestRateLimiterInterface
+{
+ public function consume(Request $request): RateLimit;
+
+ public function reset(Request $request): void;
+}
diff --git a/vendor/symfony/http-foundation/Session/Session.php b/vendor/symfony/http-foundation/Session/Session.php
index db0b9ae..022e398 100644
--- a/vendor/symfony/http-foundation/Session/Session.php
+++ b/vendor/symfony/http-foundation/Session/Session.php
@@ -18,9 +18,16 @@ use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface;
+// Help opcache.preload discover always-needed symbols
+class_exists(AttributeBag::class);
+class_exists(FlashBag::class);
+class_exists(SessionBagProxy::class);
+
/**
* @author Fabien Potencier
* @author Drak
+ *
+ * @implements \IteratorAggregate
*/
class Session implements SessionInterface, \IteratorAggregate, \Countable
{
@@ -30,21 +37,18 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
private $attributeName;
private $data = [];
private $usageIndex = 0;
+ private $usageReporter;
- /**
- * @param SessionStorageInterface $storage A SessionStorageInterface instance
- * @param AttributeBagInterface $attributes An AttributeBagInterface instance, (defaults null for default AttributeBag)
- * @param FlashBagInterface $flashes A FlashBagInterface instance (defaults null for default FlashBag)
- */
- public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null)
+ public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null, callable $usageReporter = null)
{
- $this->storage = $storage ?: new NativeSessionStorage();
+ $this->storage = $storage ?? new NativeSessionStorage();
+ $this->usageReporter = $usageReporter;
- $attributes = $attributes ?: new AttributeBag();
+ $attributes = $attributes ?? new AttributeBag();
$this->attributeName = $attributes->getName();
$this->registerBag($attributes);
- $flashes = $flashes ?: new FlashBag();
+ $flashes = $flashes ?? new FlashBag();
$this->flashName = $flashes->getName();
$this->registerBag($flashes);
}
@@ -60,7 +64,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
/**
* {@inheritdoc}
*/
- public function has($name)
+ public function has(string $name)
{
return $this->getAttributeBag()->has($name);
}
@@ -68,7 +72,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
/**
* {@inheritdoc}
*/
- public function get($name, $default = null)
+ public function get(string $name, $default = null)
{
return $this->getAttributeBag()->get($name, $default);
}
@@ -76,7 +80,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
/**
* {@inheritdoc}
*/
- public function set($name, $value)
+ public function set(string $name, $value)
{
$this->getAttributeBag()->set($name, $value);
}
@@ -100,7 +104,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
/**
* {@inheritdoc}
*/
- public function remove($name)
+ public function remove(string $name)
{
return $this->getAttributeBag()->remove($name);
}
@@ -124,8 +128,9 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
/**
* Returns an iterator for attributes.
*
- * @return \ArrayIterator An \ArrayIterator instance
+ * @return \ArrayIterator
*/
+ #[\ReturnTypeWillChange]
public function getIterator()
{
return new \ArrayIterator($this->getAttributeBag()->all());
@@ -134,32 +139,29 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
/**
* Returns the number of attributes.
*
- * @return int The number of attributes
+ * @return int
*/
+ #[\ReturnTypeWillChange]
public function count()
{
return \count($this->getAttributeBag()->all());
}
- /**
- * @return int
- *
- * @internal
- */
- public function getUsageIndex()
+ public function &getUsageIndex(): int
{
return $this->usageIndex;
}
/**
- * @return bool
- *
* @internal
*/
- public function isEmpty()
+ public function isEmpty(): bool
{
if ($this->isStarted()) {
++$this->usageIndex;
+ if ($this->usageReporter && 0 <= $this->usageIndex) {
+ ($this->usageReporter)();
+ }
}
foreach ($this->data as &$data) {
if (!empty($data)) {
@@ -173,7 +175,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
/**
* {@inheritdoc}
*/
- public function invalidate($lifetime = null)
+ public function invalidate(int $lifetime = null)
{
$this->storage->clear();
@@ -183,7 +185,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
/**
* {@inheritdoc}
*/
- public function migrate($destroy = false, $lifetime = null)
+ public function migrate(bool $destroy = false, int $lifetime = null)
{
return $this->storage->regenerate($destroy, $lifetime);
}
@@ -207,7 +209,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
/**
* {@inheritdoc}
*/
- public function setId($id)
+ public function setId(string $id)
{
if ($this->storage->getId() !== $id) {
$this->storage->setId($id);
@@ -225,7 +227,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
/**
* {@inheritdoc}
*/
- public function setName($name)
+ public function setName(string $name)
{
$this->storage->setName($name);
}
@@ -236,6 +238,9 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
public function getMetadataBag()
{
++$this->usageIndex;
+ if ($this->usageReporter && 0 <= $this->usageIndex) {
+ ($this->usageReporter)();
+ }
return $this->storage->getMetadataBag();
}
@@ -245,13 +250,13 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
*/
public function registerBag(SessionBagInterface $bag)
{
- $this->storage->registerBag(new SessionBagProxy($bag, $this->data, $this->usageIndex));
+ $this->storage->registerBag(new SessionBagProxy($bag, $this->data, $this->usageIndex, $this->usageReporter));
}
/**
* {@inheritdoc}
*/
- public function getBag($name)
+ public function getBag(string $name)
{
$bag = $this->storage->getBag($name);
@@ -272,10 +277,8 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
* Gets the attributebag interface.
*
* Note that this method was added to help with IDE autocompletion.
- *
- * @return AttributeBagInterface
*/
- private function getAttributeBag()
+ private function getAttributeBag(): AttributeBagInterface
{
return $this->getBag($this->attributeName);
}
diff --git a/vendor/symfony/http-foundation/Session/SessionBagProxy.php b/vendor/symfony/http-foundation/Session/SessionBagProxy.php
index 3504bdf..90aa010 100644
--- a/vendor/symfony/http-foundation/Session/SessionBagProxy.php
+++ b/vendor/symfony/http-foundation/Session/SessionBagProxy.php
@@ -21,33 +21,35 @@ final class SessionBagProxy implements SessionBagInterface
private $bag;
private $data;
private $usageIndex;
+ private $usageReporter;
- public function __construct(SessionBagInterface $bag, array &$data, &$usageIndex)
+ public function __construct(SessionBagInterface $bag, array &$data, ?int &$usageIndex, ?callable $usageReporter)
{
$this->bag = $bag;
$this->data = &$data;
$this->usageIndex = &$usageIndex;
+ $this->usageReporter = $usageReporter;
}
- /**
- * @return SessionBagInterface
- */
- public function getBag()
+ public function getBag(): SessionBagInterface
{
++$this->usageIndex;
+ if ($this->usageReporter && 0 <= $this->usageIndex) {
+ ($this->usageReporter)();
+ }
return $this->bag;
}
- /**
- * @return bool
- */
- public function isEmpty()
+ public function isEmpty(): bool
{
if (!isset($this->data[$this->bag->getStorageKey()])) {
return true;
}
++$this->usageIndex;
+ if ($this->usageReporter && 0 <= $this->usageIndex) {
+ ($this->usageReporter)();
+ }
return empty($this->data[$this->bag->getStorageKey()]);
}
@@ -55,7 +57,7 @@ final class SessionBagProxy implements SessionBagInterface
/**
* {@inheritdoc}
*/
- public function getName()
+ public function getName(): string
{
return $this->bag->getName();
}
@@ -63,9 +65,13 @@ final class SessionBagProxy implements SessionBagInterface
/**
* {@inheritdoc}
*/
- public function initialize(array &$array)
+ public function initialize(array &$array): void
{
++$this->usageIndex;
+ if ($this->usageReporter && 0 <= $this->usageIndex) {
+ ($this->usageReporter)();
+ }
+
$this->data[$this->bag->getStorageKey()] = &$array;
$this->bag->initialize($array);
@@ -74,7 +80,7 @@ final class SessionBagProxy implements SessionBagInterface
/**
* {@inheritdoc}
*/
- public function getStorageKey()
+ public function getStorageKey(): string
{
return $this->bag->getStorageKey();
}
diff --git a/vendor/symfony/http-foundation/Session/SessionFactory.php b/vendor/symfony/http-foundation/Session/SessionFactory.php
new file mode 100644
index 0000000..04c4b06
--- /dev/null
+++ b/vendor/symfony/http-foundation/Session/SessionFactory.php
@@ -0,0 +1,40 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\Session;
+
+use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageFactoryInterface;
+
+// Help opcache.preload discover always-needed symbols
+class_exists(Session::class);
+
+/**
+ * @author Jérémy Derussé
+ */
+class SessionFactory implements SessionFactoryInterface
+{
+ private $requestStack;
+ private $storageFactory;
+ private $usageReporter;
+
+ public function __construct(RequestStack $requestStack, SessionStorageFactoryInterface $storageFactory, callable $usageReporter = null)
+ {
+ $this->requestStack = $requestStack;
+ $this->storageFactory = $storageFactory;
+ $this->usageReporter = $usageReporter;
+ }
+
+ public function createSession(): SessionInterface
+ {
+ return new Session($this->storageFactory->createStorage($this->requestStack->getMainRequest()), null, null, $this->usageReporter);
+ }
+}
diff --git a/vendor/symfony/http-foundation/Session/SessionFactoryInterface.php b/vendor/symfony/http-foundation/Session/SessionFactoryInterface.php
new file mode 100644
index 0000000..b24fdc4
--- /dev/null
+++ b/vendor/symfony/http-foundation/Session/SessionFactoryInterface.php
@@ -0,0 +1,20 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\Session;
+
+/**
+ * @author Kevin Bond
+ */
+interface SessionFactoryInterface
+{
+ public function createSession(): SessionInterface;
+}
diff --git a/vendor/symfony/http-foundation/Session/SessionInterface.php b/vendor/symfony/http-foundation/Session/SessionInterface.php
index 95fca85..b2f09fd 100644
--- a/vendor/symfony/http-foundation/Session/SessionInterface.php
+++ b/vendor/symfony/http-foundation/Session/SessionInterface.php
@@ -23,7 +23,7 @@ interface SessionInterface
/**
* Starts the session storage.
*
- * @return bool True if session started
+ * @return bool
*
* @throws \RuntimeException if session fails to start
*/
@@ -32,30 +32,26 @@ interface SessionInterface
/**
* Returns the session ID.
*
- * @return string The session ID
+ * @return string
*/
public function getId();
/**
* Sets the session ID.
- *
- * @param string $id
*/
- public function setId($id);
+ public function setId(string $id);
/**
* Returns the session name.
*
- * @return mixed The session name
+ * @return string
*/
public function getName();
/**
* Sets the session name.
- *
- * @param string $name
*/
- public function setName($name);
+ public function setName(string $name);
/**
* Invalidates the current session.
@@ -68,9 +64,9 @@ interface SessionInterface
* to expire with browser session. Time is in seconds, and is
* not a Unix timestamp.
*
- * @return bool True if session invalidated, false if error
+ * @return bool
*/
- public function invalidate($lifetime = null);
+ public function invalidate(int $lifetime = null);
/**
* Migrates the current session to a new session id while maintaining all
@@ -82,9 +78,9 @@ interface SessionInterface
* to expire with browser session. Time is in seconds, and is
* not a Unix timestamp.
*
- * @return bool True if session migrated, false if error
+ * @return bool
*/
- public function migrate($destroy = false, $lifetime = null);
+ public function migrate(bool $destroy = false, int $lifetime = null);
/**
* Force the session to be saved and closed.
@@ -98,52 +94,44 @@ interface SessionInterface
/**
* Checks if an attribute is defined.
*
- * @param string $name The attribute name
- *
- * @return bool true if the attribute is defined, false otherwise
+ * @return bool
*/
- public function has($name);
+ public function has(string $name);
/**
* Returns an attribute.
*
- * @param string $name The attribute name
- * @param mixed $default The default value if not found
+ * @param mixed $default The default value if not found
*
* @return mixed
*/
- public function get($name, $default = null);
+ public function get(string $name, $default = null);
/**
* Sets an attribute.
*
- * @param string $name
- * @param mixed $value
+ * @param mixed $value
*/
- public function set($name, $value);
+ public function set(string $name, $value);
/**
* Returns attributes.
*
- * @return array Attributes
+ * @return array
*/
public function all();
/**
* Sets attributes.
- *
- * @param array $attributes Attributes
*/
public function replace(array $attributes);
/**
* Removes an attribute.
*
- * @param string $name
- *
* @return mixed The removed value or null when it does not exist
*/
- public function remove($name);
+ public function remove(string $name);
/**
* Clears all attributes.
@@ -165,11 +153,9 @@ interface SessionInterface
/**
* Gets a bag instance by name.
*
- * @param string $name
- *
* @return SessionBagInterface
*/
- public function getBag($name);
+ public function getBag(string $name);
/**
* Gets session meta.
diff --git a/vendor/symfony/http-foundation/Session/SessionUtils.php b/vendor/symfony/http-foundation/Session/SessionUtils.php
index 04a25f7..b5bce4a 100644
--- a/vendor/symfony/http-foundation/Session/SessionUtils.php
+++ b/vendor/symfony/http-foundation/Session/SessionUtils.php
@@ -22,10 +22,10 @@ namespace Symfony\Component\HttpFoundation\Session;
final class SessionUtils
{
/**
- * Find the session header amongst the headers that are to be sent, remove it, and return
+ * Finds the session header amongst the headers that are to be sent, removes it, and returns
* it so the caller can process it further.
*/
- public static function popSessionCookie($sessionName, $sessionId)
+ public static function popSessionCookie(string $sessionName, string $sessionId): ?string
{
$sessionCookie = null;
$sessionCookiePrefix = sprintf(' %s=', urlencode($sessionName));
diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php b/vendor/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php
new file mode 100644
index 0000000..bea3a32
--- /dev/null
+++ b/vendor/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.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\HttpFoundation\Session\Storage\Handler;
+
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+
+/**
+ * @author Ahmed TAILOULOUTE
+ */
+class IdentityMarshaller implements MarshallerInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function marshall(array $values, ?array &$failed): array
+ {
+ foreach ($values as $key => $value) {
+ if (!\is_string($value)) {
+ throw new \LogicException(sprintf('%s accepts only string as data.', __METHOD__));
+ }
+ }
+
+ return $values;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function unmarshall(string $value): string
+ {
+ return $value;
+ }
+}
diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php
new file mode 100644
index 0000000..c321c8c
--- /dev/null
+++ b/vendor/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php
@@ -0,0 +1,108 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
+
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+
+/**
+ * @author Ahmed TAILOULOUTE
+ */
+class MarshallingSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface
+{
+ private $handler;
+ private $marshaller;
+
+ public function __construct(AbstractSessionHandler $handler, MarshallerInterface $marshaller)
+ {
+ $this->handler = $handler;
+ $this->marshaller = $marshaller;
+ }
+
+ /**
+ * @return bool
+ */
+ #[\ReturnTypeWillChange]
+ public function open($savePath, $name)
+ {
+ return $this->handler->open($savePath, $name);
+ }
+
+ /**
+ * @return bool
+ */
+ #[\ReturnTypeWillChange]
+ public function close()
+ {
+ return $this->handler->close();
+ }
+
+ /**
+ * @return bool
+ */
+ #[\ReturnTypeWillChange]
+ public function destroy($sessionId)
+ {
+ return $this->handler->destroy($sessionId);
+ }
+
+ /**
+ * @return int|false
+ */
+ #[\ReturnTypeWillChange]
+ public function gc($maxlifetime)
+ {
+ return $this->handler->gc($maxlifetime);
+ }
+
+ /**
+ * @return string
+ */
+ #[\ReturnTypeWillChange]
+ public function read($sessionId)
+ {
+ return $this->marshaller->unmarshall($this->handler->read($sessionId));
+ }
+
+ /**
+ * @return bool
+ */
+ #[\ReturnTypeWillChange]
+ public function write($sessionId, $data)
+ {
+ $failed = [];
+ $marshalledData = $this->marshaller->marshall(['data' => $data], $failed);
+
+ if (isset($failed['data'])) {
+ return false;
+ }
+
+ return $this->handler->write($sessionId, $marshalledData['data']);
+ }
+
+ /**
+ * @return bool
+ */
+ #[\ReturnTypeWillChange]
+ public function validateId($sessionId)
+ {
+ return $this->handler->validateId($sessionId);
+ }
+
+ /**
+ * @return bool
+ */
+ #[\ReturnTypeWillChange]
+ public function updateTimestamp($sessionId, $data)
+ {
+ return $this->handler->updateTimestamp($sessionId, $data);
+ }
+}
diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php
new file mode 100644
index 0000000..bf27ca6
--- /dev/null
+++ b/vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php
@@ -0,0 +1,139 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
+
+/**
+ * Migrating session handler for migrating from one handler to another. It reads
+ * from the current handler and writes both the current and new ones.
+ *
+ * It ignores errors from the new handler.
+ *
+ * @author Ross Motley
+ * @author Oliver Radwell
+ */
+class MigratingSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface
+{
+ /**
+ * @var \SessionHandlerInterface&\SessionUpdateTimestampHandlerInterface
+ */
+ private $currentHandler;
+
+ /**
+ * @var \SessionHandlerInterface&\SessionUpdateTimestampHandlerInterface
+ */
+ private $writeOnlyHandler;
+
+ public function __construct(\SessionHandlerInterface $currentHandler, \SessionHandlerInterface $writeOnlyHandler)
+ {
+ if (!$currentHandler instanceof \SessionUpdateTimestampHandlerInterface) {
+ $currentHandler = new StrictSessionHandler($currentHandler);
+ }
+ if (!$writeOnlyHandler instanceof \SessionUpdateTimestampHandlerInterface) {
+ $writeOnlyHandler = new StrictSessionHandler($writeOnlyHandler);
+ }
+
+ $this->currentHandler = $currentHandler;
+ $this->writeOnlyHandler = $writeOnlyHandler;
+ }
+
+ /**
+ * @return bool
+ */
+ #[\ReturnTypeWillChange]
+ public function close()
+ {
+ $result = $this->currentHandler->close();
+ $this->writeOnlyHandler->close();
+
+ return $result;
+ }
+
+ /**
+ * @return bool
+ */
+ #[\ReturnTypeWillChange]
+ public function destroy($sessionId)
+ {
+ $result = $this->currentHandler->destroy($sessionId);
+ $this->writeOnlyHandler->destroy($sessionId);
+
+ return $result;
+ }
+
+ /**
+ * @return int|false
+ */
+ #[\ReturnTypeWillChange]
+ public function gc($maxlifetime)
+ {
+ $result = $this->currentHandler->gc($maxlifetime);
+ $this->writeOnlyHandler->gc($maxlifetime);
+
+ return $result;
+ }
+
+ /**
+ * @return bool
+ */
+ #[\ReturnTypeWillChange]
+ public function open($savePath, $sessionName)
+ {
+ $result = $this->currentHandler->open($savePath, $sessionName);
+ $this->writeOnlyHandler->open($savePath, $sessionName);
+
+ return $result;
+ }
+
+ /**
+ * @return string
+ */
+ #[\ReturnTypeWillChange]
+ public function read($sessionId)
+ {
+ // No reading from new handler until switch-over
+ return $this->currentHandler->read($sessionId);
+ }
+
+ /**
+ * @return bool
+ */
+ #[\ReturnTypeWillChange]
+ public function write($sessionId, $sessionData)
+ {
+ $result = $this->currentHandler->write($sessionId, $sessionData);
+ $this->writeOnlyHandler->write($sessionId, $sessionData);
+
+ return $result;
+ }
+
+ /**
+ * @return bool
+ */
+ #[\ReturnTypeWillChange]
+ public function validateId($sessionId)
+ {
+ // No reading from new handler until switch-over
+ return $this->currentHandler->validateId($sessionId);
+ }
+
+ /**
+ * @return bool
+ */
+ #[\ReturnTypeWillChange]
+ public function updateTimestamp($sessionId, $sessionData)
+ {
+ $result = $this->currentHandler->updateTimestamp($sessionId, $sessionData);
+ $this->writeOnlyHandler->updateTimestamp($sessionId, $sessionData);
+
+ return $result;
+ }
+}
diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php
new file mode 100644
index 0000000..31954e6
--- /dev/null
+++ b/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php
@@ -0,0 +1,137 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
+
+use Predis\Response\ErrorInterface;
+use Symfony\Component\Cache\Traits\RedisClusterProxy;
+use Symfony\Component\Cache\Traits\RedisProxy;
+
+/**
+ * Redis based session storage handler based on the Redis class
+ * provided by the PHP redis extension.
+ *
+ * @author Dalibor Karlović
+ */
+class RedisSessionHandler extends AbstractSessionHandler
+{
+ private $redis;
+
+ /**
+ * @var string Key prefix for shared environments
+ */
+ private $prefix;
+
+ /**
+ * @var int Time to live in seconds
+ */
+ private $ttl;
+
+ /**
+ * List of available options:
+ * * prefix: The prefix to use for the keys in order to avoid collision on the Redis server
+ * * ttl: The time to live in seconds.
+ *
+ * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis
+ *
+ * @throws \InvalidArgumentException When unsupported client or options are passed
+ */
+ public function __construct($redis, array $options = [])
+ {
+ if (
+ !$redis instanceof \Redis &&
+ !$redis instanceof \RedisArray &&
+ !$redis instanceof \RedisCluster &&
+ !$redis instanceof \Predis\ClientInterface &&
+ !$redis instanceof RedisProxy &&
+ !$redis instanceof RedisClusterProxy
+ ) {
+ throw new \InvalidArgumentException(sprintf('"%s()" expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, "%s" given.', __METHOD__, get_debug_type($redis)));
+ }
+
+ if ($diff = array_diff(array_keys($options), ['prefix', 'ttl'])) {
+ throw new \InvalidArgumentException(sprintf('The following options are not supported "%s".', implode(', ', $diff)));
+ }
+
+ $this->redis = $redis;
+ $this->prefix = $options['prefix'] ?? 'sf_s';
+ $this->ttl = $options['ttl'] ?? null;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doRead(string $sessionId): string
+ {
+ return $this->redis->get($this->prefix.$sessionId) ?: '';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doWrite(string $sessionId, string $data): bool
+ {
+ $result = $this->redis->setEx($this->prefix.$sessionId, (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime')), $data);
+
+ return $result && !$result instanceof ErrorInterface;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDestroy(string $sessionId): bool
+ {
+ static $unlink = true;
+
+ if ($unlink) {
+ try {
+ $unlink = false !== $this->redis->unlink($this->prefix.$sessionId);
+ } catch (\Throwable $e) {
+ $unlink = false;
+ }
+ }
+
+ if (!$unlink) {
+ $this->redis->del($this->prefix.$sessionId);
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ #[\ReturnTypeWillChange]
+ public function close(): bool
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return int|false
+ */
+ #[\ReturnTypeWillChange]
+ public function gc($maxlifetime)
+ {
+ return 0;
+ }
+
+ /**
+ * @return bool
+ */
+ #[\ReturnTypeWillChange]
+ public function updateTimestamp($sessionId, $data)
+ {
+ return (bool) $this->redis->expire($this->prefix.$sessionId, (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime')));
+ }
+}
diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php b/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php
new file mode 100644
index 0000000..f3f7b20
--- /dev/null
+++ b/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php
@@ -0,0 +1,91 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
+
+use Doctrine\DBAL\DriverManager;
+use Symfony\Component\Cache\Adapter\AbstractAdapter;
+use Symfony\Component\Cache\Traits\RedisClusterProxy;
+use Symfony\Component\Cache\Traits\RedisProxy;
+
+/**
+ * @author Nicolas Grekas
+ */
+class SessionHandlerFactory
+{
+ /**
+ * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy|\Memcached|\PDO|string $connection Connection or DSN
+ */
+ public static function createHandler($connection): AbstractSessionHandler
+ {
+ if (!\is_string($connection) && !\is_object($connection)) {
+ throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a string or a connection object, "%s" given.', __METHOD__, get_debug_type($connection)));
+ }
+
+ if ($options = \is_string($connection) ? parse_url($connection) : false) {
+ parse_str($options['query'] ?? '', $options);
+ }
+
+ switch (true) {
+ case $connection instanceof \Redis:
+ case $connection instanceof \RedisArray:
+ case $connection instanceof \RedisCluster:
+ case $connection instanceof \Predis\ClientInterface:
+ case $connection instanceof RedisProxy:
+ case $connection instanceof RedisClusterProxy:
+ return new RedisSessionHandler($connection);
+
+ case $connection instanceof \Memcached:
+ return new MemcachedSessionHandler($connection);
+
+ case $connection instanceof \PDO:
+ return new PdoSessionHandler($connection);
+
+ case !\is_string($connection):
+ throw new \InvalidArgumentException(sprintf('Unsupported Connection: "%s".', get_debug_type($connection)));
+ case str_starts_with($connection, 'file://'):
+ $savePath = substr($connection, 7);
+
+ return new StrictSessionHandler(new NativeFileSessionHandler('' === $savePath ? null : $savePath));
+
+ case str_starts_with($connection, 'redis:'):
+ case str_starts_with($connection, 'rediss:'):
+ case str_starts_with($connection, 'memcached:'):
+ if (!class_exists(AbstractAdapter::class)) {
+ throw new \InvalidArgumentException(sprintf('Unsupported DSN "%s". Try running "composer require symfony/cache".', $connection));
+ }
+ $handlerClass = str_starts_with($connection, 'memcached:') ? MemcachedSessionHandler::class : RedisSessionHandler::class;
+ $connection = AbstractAdapter::createConnection($connection, ['lazy' => true]);
+
+ return new $handlerClass($connection, array_intersect_key($options ?: [], ['prefix' => 1, 'ttl' => 1]));
+
+ case str_starts_with($connection, 'pdo_oci://'):
+ if (!class_exists(DriverManager::class)) {
+ throw new \InvalidArgumentException(sprintf('Unsupported DSN "%s". Try running "composer require doctrine/dbal".', $connection));
+ }
+ $connection = DriverManager::getConnection(['url' => $connection])->getWrappedConnection();
+ // no break;
+
+ case str_starts_with($connection, 'mssql://'):
+ case str_starts_with($connection, 'mysql://'):
+ case str_starts_with($connection, 'mysql2://'):
+ case str_starts_with($connection, 'pgsql://'):
+ case str_starts_with($connection, 'postgres://'):
+ case str_starts_with($connection, 'postgresql://'):
+ case str_starts_with($connection, 'sqlsrv://'):
+ case str_starts_with($connection, 'sqlite://'):
+ case str_starts_with($connection, 'sqlite3://'):
+ return new PdoSessionHandler($connection, $options ?: []);
+ }
+
+ throw new \InvalidArgumentException(sprintf('Unsupported Connection: "%s".', $connection));
+ }
+}
diff --git a/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php b/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php
new file mode 100644
index 0000000..d0da1e1
--- /dev/null
+++ b/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.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\HttpFoundation\Session\Storage;
+
+use Symfony\Component\HttpFoundation\Request;
+
+// Help opcache.preload discover always-needed symbols
+class_exists(MockFileSessionStorage::class);
+
+/**
+ * @author Jérémy Derussé
+ */
+class MockFileSessionStorageFactory implements SessionStorageFactoryInterface
+{
+ private $savePath;
+ private $name;
+ private $metaBag;
+
+ /**
+ * @see MockFileSessionStorage constructor.
+ */
+ public function __construct(string $savePath = null, string $name = 'MOCKSESSID', MetadataBag $metaBag = null)
+ {
+ $this->savePath = $savePath;
+ $this->name = $name;
+ $this->metaBag = $metaBag;
+ }
+
+ public function createStorage(?Request $request): SessionStorageInterface
+ {
+ return new MockFileSessionStorage($this->savePath, $this->name, $this->metaBag);
+ }
+}
diff --git a/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php b/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php
new file mode 100644
index 0000000..a7d7411
--- /dev/null
+++ b/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php
@@ -0,0 +1,49 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\Session\Storage;
+
+use Symfony\Component\HttpFoundation\Request;
+
+// Help opcache.preload discover always-needed symbols
+class_exists(NativeSessionStorage::class);
+
+/**
+ * @author Jérémy Derussé
+ */
+class NativeSessionStorageFactory implements SessionStorageFactoryInterface
+{
+ private $options;
+ private $handler;
+ private $metaBag;
+ private $secure;
+
+ /**
+ * @see NativeSessionStorage constructor.
+ */
+ public function __construct(array $options = [], $handler = null, MetadataBag $metaBag = null, bool $secure = false)
+ {
+ $this->options = $options;
+ $this->handler = $handler;
+ $this->metaBag = $metaBag;
+ $this->secure = $secure;
+ }
+
+ public function createStorage(?Request $request): SessionStorageInterface
+ {
+ $storage = new NativeSessionStorage($this->options, $this->handler, $this->metaBag);
+ if ($this->secure && $request && $request->isSecure()) {
+ $storage->setOptions(['cookie_secure' => true]);
+ }
+
+ return $storage;
+ }
+}
diff --git a/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php b/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php
new file mode 100644
index 0000000..173ef71
--- /dev/null
+++ b/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.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\HttpFoundation\Session\Storage;
+
+use Symfony\Component\HttpFoundation\Request;
+
+// Help opcache.preload discover always-needed symbols
+class_exists(PhpBridgeSessionStorage::class);
+
+/**
+ * @author Jérémy Derussé
+ */
+class PhpBridgeSessionStorageFactory implements SessionStorageFactoryInterface
+{
+ private $handler;
+ private $metaBag;
+ private $secure;
+
+ /**
+ * @see PhpBridgeSessionStorage constructor.
+ */
+ public function __construct($handler = null, MetadataBag $metaBag = null, bool $secure = false)
+ {
+ $this->handler = $handler;
+ $this->metaBag = $metaBag;
+ $this->secure = $secure;
+ }
+
+ public function createStorage(?Request $request): SessionStorageInterface
+ {
+ $storage = new PhpBridgeSessionStorage($this->handler, $this->metaBag);
+ if ($this->secure && $request && $request->isSecure()) {
+ $storage->setOptions(['cookie_secure' => true]);
+ }
+
+ return $storage;
+ }
+}
diff --git a/vendor/symfony/http-foundation/Session/Storage/ServiceSessionFactory.php b/vendor/symfony/http-foundation/Session/Storage/ServiceSessionFactory.php
new file mode 100644
index 0000000..d17c60a
--- /dev/null
+++ b/vendor/symfony/http-foundation/Session/Storage/ServiceSessionFactory.php
@@ -0,0 +1,38 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\Session\Storage;
+
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * @author Jérémy Derussé
+ *
+ * @internal to be removed in Symfony 6
+ */
+final class ServiceSessionFactory implements SessionStorageFactoryInterface
+{
+ private $storage;
+
+ public function __construct(SessionStorageInterface $storage)
+ {
+ $this->storage = $storage;
+ }
+
+ public function createStorage(?Request $request): SessionStorageInterface
+ {
+ if ($this->storage instanceof NativeSessionStorage && $request && $request->isSecure()) {
+ $this->storage->setOptions(['cookie_secure' => true]);
+ }
+
+ return $this->storage;
+ }
+}
diff --git a/vendor/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php b/vendor/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php
new file mode 100644
index 0000000..d03f0da
--- /dev/null
+++ b/vendor/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.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\HttpFoundation\Session\Storage;
+
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * @author Jérémy Derussé
+ */
+interface SessionStorageFactoryInterface
+{
+ /**
+ * Creates a new instance of SessionStorageInterface.
+ */
+ public function createStorage(?Request $request): SessionStorageInterface;
+}
diff --git a/vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php b/vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php
new file mode 100644
index 0000000..cb216ea
--- /dev/null
+++ b/vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php
@@ -0,0 +1,55 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\Test\Constraint;
+
+use PHPUnit\Framework\Constraint\Constraint;
+use Symfony\Component\HttpFoundation\Request;
+
+final class RequestAttributeValueSame extends Constraint
+{
+ private $name;
+ private $value;
+
+ public function __construct(string $name, string $value)
+ {
+ $this->name = $name;
+ $this->value = $value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function toString(): string
+ {
+ return sprintf('has attribute "%s" with value "%s"', $this->name, $this->value);
+ }
+
+ /**
+ * @param Request $request
+ *
+ * {@inheritdoc}
+ */
+ protected function matches($request): bool
+ {
+ return $this->value === $request->attributes->get($this->name);
+ }
+
+ /**
+ * @param Request $request
+ *
+ * {@inheritdoc}
+ */
+ protected function failureDescription($request): string
+ {
+ return 'the Request '.$this->toString();
+ }
+}
diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php
new file mode 100644
index 0000000..554e1a1
--- /dev/null
+++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php
@@ -0,0 +1,85 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\Test\Constraint;
+
+use PHPUnit\Framework\Constraint\Constraint;
+use Symfony\Component\HttpFoundation\Cookie;
+use Symfony\Component\HttpFoundation\Response;
+
+final class ResponseCookieValueSame extends Constraint
+{
+ private $name;
+ private $value;
+ private $path;
+ private $domain;
+
+ public function __construct(string $name, string $value, string $path = '/', string $domain = null)
+ {
+ $this->name = $name;
+ $this->value = $value;
+ $this->path = $path;
+ $this->domain = $domain;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function toString(): string
+ {
+ $str = sprintf('has cookie "%s"', $this->name);
+ if ('/' !== $this->path) {
+ $str .= sprintf(' with path "%s"', $this->path);
+ }
+ if ($this->domain) {
+ $str .= sprintf(' for domain "%s"', $this->domain);
+ }
+ $str .= sprintf(' with value "%s"', $this->value);
+
+ return $str;
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function matches($response): bool
+ {
+ $cookie = $this->getCookie($response);
+ if (!$cookie) {
+ return false;
+ }
+
+ return $this->value === $cookie->getValue();
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function failureDescription($response): string
+ {
+ return 'the Response '.$this->toString();
+ }
+
+ protected function getCookie(Response $response): ?Cookie
+ {
+ $cookies = $response->headers->getCookies();
+
+ $filteredCookies = array_filter($cookies, function (Cookie $cookie) {
+ return $cookie->getName() === $this->name && $cookie->getPath() === $this->path && $cookie->getDomain() === $this->domain;
+ });
+
+ return reset($filteredCookies) ?: null;
+ }
+}
diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php
new file mode 100644
index 0000000..f73aedf
--- /dev/null
+++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php
@@ -0,0 +1,71 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\Test\Constraint;
+
+use PHPUnit\Framework\Constraint\Constraint;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * Asserts that the response is in the given format.
+ *
+ * @author Kévin Dunglas
+ */
+final class ResponseFormatSame extends Constraint
+{
+ private $request;
+ private $format;
+
+ public function __construct(Request $request, ?string $format)
+ {
+ $this->request = $request;
+ $this->format = $format;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function toString(): string
+ {
+ return 'format is '.($this->format ?? 'null');
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function matches($response): bool
+ {
+ return $this->format === $this->request->getFormat($response->headers->get('Content-Type'));
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function failureDescription($response): string
+ {
+ return 'the Response '.$this->toString();
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function additionalFailureDescription($response): string
+ {
+ return (string) $response;
+ }
+}
diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php
new file mode 100644
index 0000000..eae9e27
--- /dev/null
+++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.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\HttpFoundation\Test\Constraint;
+
+use PHPUnit\Framework\Constraint\Constraint;
+use Symfony\Component\HttpFoundation\Cookie;
+use Symfony\Component\HttpFoundation\Response;
+
+final class ResponseHasCookie extends Constraint
+{
+ private $name;
+ private $path;
+ private $domain;
+
+ public function __construct(string $name, string $path = '/', string $domain = null)
+ {
+ $this->name = $name;
+ $this->path = $path;
+ $this->domain = $domain;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function toString(): string
+ {
+ $str = sprintf('has cookie "%s"', $this->name);
+ if ('/' !== $this->path) {
+ $str .= sprintf(' with path "%s"', $this->path);
+ }
+ if ($this->domain) {
+ $str .= sprintf(' for domain "%s"', $this->domain);
+ }
+
+ return $str;
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function matches($response): bool
+ {
+ return null !== $this->getCookie($response);
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function failureDescription($response): string
+ {
+ return 'the Response '.$this->toString();
+ }
+
+ private function getCookie(Response $response): ?Cookie
+ {
+ $cookies = $response->headers->getCookies();
+
+ $filteredCookies = array_filter($cookies, function (Cookie $cookie) {
+ return $cookie->getName() === $this->name && $cookie->getPath() === $this->path && $cookie->getDomain() === $this->domain;
+ });
+
+ return reset($filteredCookies) ?: null;
+ }
+}
diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php
new file mode 100644
index 0000000..68ad827
--- /dev/null
+++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.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\HttpFoundation\Test\Constraint;
+
+use PHPUnit\Framework\Constraint\Constraint;
+use Symfony\Component\HttpFoundation\Response;
+
+final class ResponseHasHeader extends Constraint
+{
+ private $headerName;
+
+ public function __construct(string $headerName)
+ {
+ $this->headerName = $headerName;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function toString(): string
+ {
+ return sprintf('has header "%s"', $this->headerName);
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function matches($response): bool
+ {
+ return $response->headers->has($this->headerName);
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function failureDescription($response): string
+ {
+ return 'the Response '.$this->toString();
+ }
+}
diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php
new file mode 100644
index 0000000..a27d0c7
--- /dev/null
+++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php
@@ -0,0 +1,55 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\Test\Constraint;
+
+use PHPUnit\Framework\Constraint\Constraint;
+use Symfony\Component\HttpFoundation\Response;
+
+final class ResponseHeaderSame extends Constraint
+{
+ private $headerName;
+ private $expectedValue;
+
+ public function __construct(string $headerName, string $expectedValue)
+ {
+ $this->headerName = $headerName;
+ $this->expectedValue = $expectedValue;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function toString(): string
+ {
+ return sprintf('has header "%s" with value "%s"', $this->headerName, $this->expectedValue);
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function matches($response): bool
+ {
+ return $this->expectedValue === $response->headers->get($this->headerName, null);
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function failureDescription($response): string
+ {
+ return 'the Response '.$this->toString();
+ }
+}
diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php
new file mode 100644
index 0000000..8c4b883
--- /dev/null
+++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.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\HttpFoundation\Test\Constraint;
+
+use PHPUnit\Framework\Constraint\Constraint;
+use Symfony\Component\HttpFoundation\Response;
+
+final class ResponseIsRedirected extends Constraint
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function toString(): string
+ {
+ return 'is redirected';
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function matches($response): bool
+ {
+ return $response->isRedirect();
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function failureDescription($response): string
+ {
+ return 'the Response '.$this->toString();
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function additionalFailureDescription($response): string
+ {
+ return (string) $response;
+ }
+}
diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php
new file mode 100644
index 0000000..9c66558
--- /dev/null
+++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.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\HttpFoundation\Test\Constraint;
+
+use PHPUnit\Framework\Constraint\Constraint;
+use Symfony\Component\HttpFoundation\Response;
+
+final class ResponseIsSuccessful extends Constraint
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function toString(): string
+ {
+ return 'is successful';
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function matches($response): bool
+ {
+ return $response->isSuccessful();
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function failureDescription($response): string
+ {
+ return 'the Response '.$this->toString();
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function additionalFailureDescription($response): string
+ {
+ return (string) $response;
+ }
+}
diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseIsUnprocessable.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsUnprocessable.php
new file mode 100644
index 0000000..880c781
--- /dev/null
+++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsUnprocessable.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\HttpFoundation\Test\Constraint;
+
+use PHPUnit\Framework\Constraint\Constraint;
+use Symfony\Component\HttpFoundation\Response;
+
+final class ResponseIsUnprocessable extends Constraint
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function toString(): string
+ {
+ return 'is unprocessable';
+ }
+
+ /**
+ * @param Response $other
+ *
+ * {@inheritdoc}
+ */
+ protected function matches($other): bool
+ {
+ return Response::HTTP_UNPROCESSABLE_ENTITY === $other->getStatusCode();
+ }
+
+ /**
+ * @param Response $other
+ *
+ * {@inheritdoc}
+ */
+ protected function failureDescription($other): string
+ {
+ return 'the Response '.$this->toString();
+ }
+
+ /**
+ * @param Response $other
+ *
+ * {@inheritdoc}
+ */
+ protected function additionalFailureDescription($other): string
+ {
+ return (string) $other;
+ }
+}
diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php
new file mode 100644
index 0000000..72bb000
--- /dev/null
+++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php
@@ -0,0 +1,63 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation\Test\Constraint;
+
+use PHPUnit\Framework\Constraint\Constraint;
+use Symfony\Component\HttpFoundation\Response;
+
+final class ResponseStatusCodeSame extends Constraint
+{
+ private $statusCode;
+
+ public function __construct(int $statusCode)
+ {
+ $this->statusCode = $statusCode;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function toString(): string
+ {
+ return 'status code is '.$this->statusCode;
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function matches($response): bool
+ {
+ return $this->statusCode === $response->getStatusCode();
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function failureDescription($response): string
+ {
+ return 'the Response '.$this->toString();
+ }
+
+ /**
+ * @param Response $response
+ *
+ * {@inheritdoc}
+ */
+ protected function additionalFailureDescription($response): string
+ {
+ return (string) $response;
+ }
+}
diff --git a/vendor/symfony/http-foundation/UrlHelper.php b/vendor/symfony/http-foundation/UrlHelper.php
new file mode 100644
index 0000000..c15f101
--- /dev/null
+++ b/vendor/symfony/http-foundation/UrlHelper.php
@@ -0,0 +1,102 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpFoundation;
+
+use Symfony\Component\Routing\RequestContext;
+
+/**
+ * A helper service for manipulating URLs within and outside the request scope.
+ *
+ * @author Valentin Udaltsov
+ */
+final class UrlHelper
+{
+ private $requestStack;
+ private $requestContext;
+
+ public function __construct(RequestStack $requestStack, RequestContext $requestContext = null)
+ {
+ $this->requestStack = $requestStack;
+ $this->requestContext = $requestContext;
+ }
+
+ public function getAbsoluteUrl(string $path): string
+ {
+ if (str_contains($path, '://') || '//' === substr($path, 0, 2)) {
+ return $path;
+ }
+
+ if (null === $request = $this->requestStack->getMainRequest()) {
+ return $this->getAbsoluteUrlFromContext($path);
+ }
+
+ if ('#' === $path[0]) {
+ $path = $request->getRequestUri().$path;
+ } elseif ('?' === $path[0]) {
+ $path = $request->getPathInfo().$path;
+ }
+
+ if (!$path || '/' !== $path[0]) {
+ $prefix = $request->getPathInfo();
+ $last = \strlen($prefix) - 1;
+ if ($last !== $pos = strrpos($prefix, '/')) {
+ $prefix = substr($prefix, 0, $pos).'/';
+ }
+
+ return $request->getUriForPath($prefix.$path);
+ }
+
+ return $request->getSchemeAndHttpHost().$path;
+ }
+
+ public function getRelativePath(string $path): string
+ {
+ if (str_contains($path, '://') || '//' === substr($path, 0, 2)) {
+ return $path;
+ }
+
+ if (null === $request = $this->requestStack->getMainRequest()) {
+ return $path;
+ }
+
+ return $request->getRelativeUriForPath($path);
+ }
+
+ private function getAbsoluteUrlFromContext(string $path): string
+ {
+ if (null === $this->requestContext || '' === $host = $this->requestContext->getHost()) {
+ return $path;
+ }
+
+ $scheme = $this->requestContext->getScheme();
+ $port = '';
+
+ if ('http' === $scheme && 80 !== $this->requestContext->getHttpPort()) {
+ $port = ':'.$this->requestContext->getHttpPort();
+ } elseif ('https' === $scheme && 443 !== $this->requestContext->getHttpsPort()) {
+ $port = ':'.$this->requestContext->getHttpsPort();
+ }
+
+ if ('#' === $path[0]) {
+ $queryString = $this->requestContext->getQueryString();
+ $path = $this->requestContext->getPathInfo().($queryString ? '?'.$queryString : '').$path;
+ } elseif ('?' === $path[0]) {
+ $path = $this->requestContext->getPathInfo().$path;
+ }
+
+ if ('/' !== $path[0]) {
+ $path = rtrim($this->requestContext->getBaseUrl(), '/').'/'.$path;
+ }
+
+ return $scheme.'://'.$host.$port.$path;
+ }
+}
diff --git a/vendor/symfony/polyfill-ctype/bootstrap80.php b/vendor/symfony/polyfill-ctype/bootstrap80.php
new file mode 100644
index 0000000..ab2f861
--- /dev/null
+++ b/vendor/symfony/polyfill-ctype/bootstrap80.php
@@ -0,0 +1,46 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Polyfill\Ctype as p;
+
+if (!function_exists('ctype_alnum')) {
+ function ctype_alnum(mixed $text): bool { return p\Ctype::ctype_alnum($text); }
+}
+if (!function_exists('ctype_alpha')) {
+ function ctype_alpha(mixed $text): bool { return p\Ctype::ctype_alpha($text); }
+}
+if (!function_exists('ctype_cntrl')) {
+ function ctype_cntrl(mixed $text): bool { return p\Ctype::ctype_cntrl($text); }
+}
+if (!function_exists('ctype_digit')) {
+ function ctype_digit(mixed $text): bool { return p\Ctype::ctype_digit($text); }
+}
+if (!function_exists('ctype_graph')) {
+ function ctype_graph(mixed $text): bool { return p\Ctype::ctype_graph($text); }
+}
+if (!function_exists('ctype_lower')) {
+ function ctype_lower(mixed $text): bool { return p\Ctype::ctype_lower($text); }
+}
+if (!function_exists('ctype_print')) {
+ function ctype_print(mixed $text): bool { return p\Ctype::ctype_print($text); }
+}
+if (!function_exists('ctype_punct')) {
+ function ctype_punct(mixed $text): bool { return p\Ctype::ctype_punct($text); }
+}
+if (!function_exists('ctype_space')) {
+ function ctype_space(mixed $text): bool { return p\Ctype::ctype_space($text); }
+}
+if (!function_exists('ctype_upper')) {
+ function ctype_upper(mixed $text): bool { return p\Ctype::ctype_upper($text); }
+}
+if (!function_exists('ctype_xdigit')) {
+ function ctype_xdigit(mixed $text): bool { return p\Ctype::ctype_xdigit($text); }
+}
diff --git a/vendor/symfony/polyfill-intl-grapheme/bootstrap80.php b/vendor/symfony/polyfill-intl-grapheme/bootstrap80.php
new file mode 100644
index 0000000..53b4529
--- /dev/null
+++ b/vendor/symfony/polyfill-intl-grapheme/bootstrap80.php
@@ -0,0 +1,50 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Polyfill\Intl\Grapheme as p;
+
+if (!defined('GRAPHEME_EXTR_COUNT')) {
+ define('GRAPHEME_EXTR_COUNT', 0);
+}
+if (!defined('GRAPHEME_EXTR_MAXBYTES')) {
+ define('GRAPHEME_EXTR_MAXBYTES', 1);
+}
+if (!defined('GRAPHEME_EXTR_MAXCHARS')) {
+ define('GRAPHEME_EXTR_MAXCHARS', 2);
+}
+
+if (!function_exists('grapheme_extract')) {
+ function grapheme_extract(?string $haystack, ?int $size, ?int $type = GRAPHEME_EXTR_COUNT, ?int $offset = 0, &$next = null): string|false { return p\Grapheme::grapheme_extract((string) $haystack, (int) $size, (int) $type, (int) $offset, $next); }
+}
+if (!function_exists('grapheme_stripos')) {
+ function grapheme_stripos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_stripos((string) $haystack, (string) $needle, (int) $offset); }
+}
+if (!function_exists('grapheme_stristr')) {
+ function grapheme_stristr(?string $haystack, ?string $needle, ?bool $beforeNeedle = false): string|false { return p\Grapheme::grapheme_stristr((string) $haystack, (string) $needle, (bool) $beforeNeedle); }
+}
+if (!function_exists('grapheme_strlen')) {
+ function grapheme_strlen(?string $string): int|false|null { return p\Grapheme::grapheme_strlen((string) $string); }
+}
+if (!function_exists('grapheme_strpos')) {
+ function grapheme_strpos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_strpos((string) $haystack, (string) $needle, (int) $offset); }
+}
+if (!function_exists('grapheme_strripos')) {
+ function grapheme_strripos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_strripos((string) $haystack, (string) $needle, (int) $offset); }
+}
+if (!function_exists('grapheme_strrpos')) {
+ function grapheme_strrpos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_strrpos((string) $haystack, (string) $needle, (int) $offset); }
+}
+if (!function_exists('grapheme_strstr')) {
+ function grapheme_strstr(?string $haystack, ?string $needle, ?bool $beforeNeedle = false): string|false { return p\Grapheme::grapheme_strstr((string) $haystack, (string) $needle, (bool) $beforeNeedle); }
+}
+if (!function_exists('grapheme_substr')) {
+ function grapheme_substr(?string $string, ?int $offset, ?int $length = null): string|false { return p\Grapheme::grapheme_substr((string) $string, (int) $offset, (int) $length); }
+}
diff --git a/vendor/symfony/polyfill-intl-idn/Idn.php b/vendor/symfony/polyfill-intl-idn/Idn.php
new file mode 100644
index 0000000..fee3026
--- /dev/null
+++ b/vendor/symfony/polyfill-intl-idn/Idn.php
@@ -0,0 +1,925 @@
+ and Trevor Rowbotham
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Polyfill\Intl\Idn;
+
+use Exception;
+use Normalizer;
+use Symfony\Polyfill\Intl\Idn\Resources\unidata\DisallowedRanges;
+use Symfony\Polyfill\Intl\Idn\Resources\unidata\Regex;
+
+/**
+ * @see https://www.unicode.org/reports/tr46/
+ *
+ * @internal
+ */
+final class Idn
+{
+ public const ERROR_EMPTY_LABEL = 1;
+ public const ERROR_LABEL_TOO_LONG = 2;
+ public const ERROR_DOMAIN_NAME_TOO_LONG = 4;
+ public const ERROR_LEADING_HYPHEN = 8;
+ public const ERROR_TRAILING_HYPHEN = 0x10;
+ public const ERROR_HYPHEN_3_4 = 0x20;
+ public const ERROR_LEADING_COMBINING_MARK = 0x40;
+ public const ERROR_DISALLOWED = 0x80;
+ public const ERROR_PUNYCODE = 0x100;
+ public const ERROR_LABEL_HAS_DOT = 0x200;
+ public const ERROR_INVALID_ACE_LABEL = 0x400;
+ public const ERROR_BIDI = 0x800;
+ public const ERROR_CONTEXTJ = 0x1000;
+ public const ERROR_CONTEXTO_PUNCTUATION = 0x2000;
+ public const ERROR_CONTEXTO_DIGITS = 0x4000;
+
+ public const INTL_IDNA_VARIANT_2003 = 0;
+ public const INTL_IDNA_VARIANT_UTS46 = 1;
+
+ public const IDNA_DEFAULT = 0;
+ public const IDNA_ALLOW_UNASSIGNED = 1;
+ public const IDNA_USE_STD3_RULES = 2;
+ public const IDNA_CHECK_BIDI = 4;
+ public const IDNA_CHECK_CONTEXTJ = 8;
+ public const IDNA_NONTRANSITIONAL_TO_ASCII = 16;
+ public const IDNA_NONTRANSITIONAL_TO_UNICODE = 32;
+
+ public const MAX_DOMAIN_SIZE = 253;
+ public const MAX_LABEL_SIZE = 63;
+
+ public const BASE = 36;
+ public const TMIN = 1;
+ public const TMAX = 26;
+ public const SKEW = 38;
+ public const DAMP = 700;
+ public const INITIAL_BIAS = 72;
+ public const INITIAL_N = 128;
+ public const DELIMITER = '-';
+ public const MAX_INT = 2147483647;
+
+ /**
+ * Contains the numeric value of a basic code point (for use in representing integers) in the
+ * range 0 to BASE-1, or -1 if b is does not represent a value.
+ *
+ * @var array
+ */
+ private static $basicToDigit = [
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
+
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ ];
+
+ /**
+ * @var array
+ */
+ private static $virama;
+
+ /**
+ * @var array
+ */
+ private static $mapped;
+
+ /**
+ * @var array
+ */
+ private static $ignored;
+
+ /**
+ * @var array
+ */
+ private static $deviation;
+
+ /**
+ * @var array
+ */
+ private static $disallowed;
+
+ /**
+ * @var array
+ */
+ private static $disallowed_STD3_mapped;
+
+ /**
+ * @var array
+ */
+ private static $disallowed_STD3_valid;
+
+ /**
+ * @var bool
+ */
+ private static $mappingTableLoaded = false;
+
+ /**
+ * @see https://www.unicode.org/reports/tr46/#ToASCII
+ *
+ * @param string $domainName
+ * @param int $options
+ * @param int $variant
+ * @param array $idna_info
+ *
+ * @return string|false
+ */
+ public static function idn_to_ascii($domainName, $options = self::IDNA_DEFAULT, $variant = self::INTL_IDNA_VARIANT_UTS46, &$idna_info = [])
+ {
+ if (\PHP_VERSION_ID >= 70200 && self::INTL_IDNA_VARIANT_2003 === $variant) {
+ @trigger_error('idn_to_ascii(): INTL_IDNA_VARIANT_2003 is deprecated', \E_USER_DEPRECATED);
+ }
+
+ $options = [
+ 'CheckHyphens' => true,
+ 'CheckBidi' => self::INTL_IDNA_VARIANT_2003 === $variant || 0 !== ($options & self::IDNA_CHECK_BIDI),
+ 'CheckJoiners' => self::INTL_IDNA_VARIANT_UTS46 === $variant && 0 !== ($options & self::IDNA_CHECK_CONTEXTJ),
+ 'UseSTD3ASCIIRules' => 0 !== ($options & self::IDNA_USE_STD3_RULES),
+ 'Transitional_Processing' => self::INTL_IDNA_VARIANT_2003 === $variant || 0 === ($options & self::IDNA_NONTRANSITIONAL_TO_ASCII),
+ 'VerifyDnsLength' => true,
+ ];
+ $info = new Info();
+ $labels = self::process((string) $domainName, $options, $info);
+
+ foreach ($labels as $i => $label) {
+ // Only convert labels to punycode that contain non-ASCII code points
+ if (1 === preg_match('/[^\x00-\x7F]/', $label)) {
+ try {
+ $label = 'xn--'.self::punycodeEncode($label);
+ } catch (Exception $e) {
+ $info->errors |= self::ERROR_PUNYCODE;
+ }
+
+ $labels[$i] = $label;
+ }
+ }
+
+ if ($options['VerifyDnsLength']) {
+ self::validateDomainAndLabelLength($labels, $info);
+ }
+
+ $idna_info = [
+ 'result' => implode('.', $labels),
+ 'isTransitionalDifferent' => $info->transitionalDifferent,
+ 'errors' => $info->errors,
+ ];
+
+ return 0 === $info->errors ? $idna_info['result'] : false;
+ }
+
+ /**
+ * @see https://www.unicode.org/reports/tr46/#ToUnicode
+ *
+ * @param string $domainName
+ * @param int $options
+ * @param int $variant
+ * @param array $idna_info
+ *
+ * @return string|false
+ */
+ public static function idn_to_utf8($domainName, $options = self::IDNA_DEFAULT, $variant = self::INTL_IDNA_VARIANT_UTS46, &$idna_info = [])
+ {
+ if (\PHP_VERSION_ID >= 70200 && self::INTL_IDNA_VARIANT_2003 === $variant) {
+ @trigger_error('idn_to_utf8(): INTL_IDNA_VARIANT_2003 is deprecated', \E_USER_DEPRECATED);
+ }
+
+ $info = new Info();
+ $labels = self::process((string) $domainName, [
+ 'CheckHyphens' => true,
+ 'CheckBidi' => self::INTL_IDNA_VARIANT_2003 === $variant || 0 !== ($options & self::IDNA_CHECK_BIDI),
+ 'CheckJoiners' => self::INTL_IDNA_VARIANT_UTS46 === $variant && 0 !== ($options & self::IDNA_CHECK_CONTEXTJ),
+ 'UseSTD3ASCIIRules' => 0 !== ($options & self::IDNA_USE_STD3_RULES),
+ 'Transitional_Processing' => self::INTL_IDNA_VARIANT_2003 === $variant || 0 === ($options & self::IDNA_NONTRANSITIONAL_TO_UNICODE),
+ ], $info);
+ $idna_info = [
+ 'result' => implode('.', $labels),
+ 'isTransitionalDifferent' => $info->transitionalDifferent,
+ 'errors' => $info->errors,
+ ];
+
+ return 0 === $info->errors ? $idna_info['result'] : false;
+ }
+
+ /**
+ * @param string $label
+ *
+ * @return bool
+ */
+ private static function isValidContextJ(array $codePoints, $label)
+ {
+ if (!isset(self::$virama)) {
+ self::$virama = require __DIR__.\DIRECTORY_SEPARATOR.'Resources'.\DIRECTORY_SEPARATOR.'unidata'.\DIRECTORY_SEPARATOR.'virama.php';
+ }
+
+ $offset = 0;
+
+ foreach ($codePoints as $i => $codePoint) {
+ if (0x200C !== $codePoint && 0x200D !== $codePoint) {
+ continue;
+ }
+
+ if (!isset($codePoints[$i - 1])) {
+ return false;
+ }
+
+ // If Canonical_Combining_Class(Before(cp)) .eq. Virama Then True;
+ if (isset(self::$virama[$codePoints[$i - 1]])) {
+ continue;
+ }
+
+ // If RegExpMatch((Joining_Type:{L,D})(Joining_Type:T)*\u200C(Joining_Type:T)*(Joining_Type:{R,D})) Then
+ // True;
+ // Generated RegExp = ([Joining_Type:{L,D}][Joining_Type:T]*\u200C[Joining_Type:T]*)[Joining_Type:{R,D}]
+ if (0x200C === $codePoint && 1 === preg_match(Regex::ZWNJ, $label, $matches, \PREG_OFFSET_CAPTURE, $offset)) {
+ $offset += \strlen($matches[1][0]);
+
+ continue;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @see https://www.unicode.org/reports/tr46/#ProcessingStepMap
+ *
+ * @param string $input
+ * @param array $options
+ *
+ * @return string
+ */
+ private static function mapCodePoints($input, array $options, Info $info)
+ {
+ $str = '';
+ $useSTD3ASCIIRules = $options['UseSTD3ASCIIRules'];
+ $transitional = $options['Transitional_Processing'];
+
+ foreach (self::utf8Decode($input) as $codePoint) {
+ $data = self::lookupCodePointStatus($codePoint, $useSTD3ASCIIRules);
+
+ switch ($data['status']) {
+ case 'disallowed':
+ $info->errors |= self::ERROR_DISALLOWED;
+
+ // no break.
+
+ case 'valid':
+ $str .= mb_chr($codePoint, 'utf-8');
+
+ break;
+
+ case 'ignored':
+ // Do nothing.
+ break;
+
+ case 'mapped':
+ $str .= $data['mapping'];
+
+ break;
+
+ case 'deviation':
+ $info->transitionalDifferent = true;
+ $str .= ($transitional ? $data['mapping'] : mb_chr($codePoint, 'utf-8'));
+
+ break;
+ }
+ }
+
+ return $str;
+ }
+
+ /**
+ * @see https://www.unicode.org/reports/tr46/#Processing
+ *
+ * @param string $domain
+ * @param array $options
+ *
+ * @return array
+ */
+ private static function process($domain, array $options, Info $info)
+ {
+ // If VerifyDnsLength is not set, we are doing ToUnicode otherwise we are doing ToASCII and
+ // we need to respect the VerifyDnsLength option.
+ $checkForEmptyLabels = !isset($options['VerifyDnsLength']) || $options['VerifyDnsLength'];
+
+ if ($checkForEmptyLabels && '' === $domain) {
+ $info->errors |= self::ERROR_EMPTY_LABEL;
+
+ return [$domain];
+ }
+
+ // Step 1. Map each code point in the domain name string
+ $domain = self::mapCodePoints($domain, $options, $info);
+
+ // Step 2. Normalize the domain name string to Unicode Normalization Form C.
+ if (!Normalizer::isNormalized($domain, Normalizer::FORM_C)) {
+ $domain = Normalizer::normalize($domain, Normalizer::FORM_C);
+ }
+
+ // Step 3. Break the string into labels at U+002E (.) FULL STOP.
+ $labels = explode('.', $domain);
+ $lastLabelIndex = \count($labels) - 1;
+
+ // Step 4. Convert and validate each label in the domain name string.
+ foreach ($labels as $i => $label) {
+ $validationOptions = $options;
+
+ if ('xn--' === substr($label, 0, 4)) {
+ try {
+ $label = self::punycodeDecode(substr($label, 4));
+ } catch (Exception $e) {
+ $info->errors |= self::ERROR_PUNYCODE;
+
+ continue;
+ }
+
+ $validationOptions['Transitional_Processing'] = false;
+ $labels[$i] = $label;
+ }
+
+ self::validateLabel($label, $info, $validationOptions, $i > 0 && $i === $lastLabelIndex);
+ }
+
+ if ($info->bidiDomain && !$info->validBidiDomain) {
+ $info->errors |= self::ERROR_BIDI;
+ }
+
+ // Any input domain name string that does not record an error has been successfully
+ // processed according to this specification. Conversely, if an input domain_name string
+ // causes an error, then the processing of the input domain_name string fails. Determining
+ // what to do with error input is up to the caller, and not in the scope of this document.
+ return $labels;
+ }
+
+ /**
+ * @see https://tools.ietf.org/html/rfc5893#section-2
+ *
+ * @param string $label
+ */
+ private static function validateBidiLabel($label, Info $info)
+ {
+ if (1 === preg_match(Regex::RTL_LABEL, $label)) {
+ $info->bidiDomain = true;
+
+ // Step 1. The first character must be a character with Bidi property L, R, or AL.
+ // If it has the R or AL property, it is an RTL label
+ if (1 !== preg_match(Regex::BIDI_STEP_1_RTL, $label)) {
+ $info->validBidiDomain = false;
+
+ return;
+ }
+
+ // Step 2. In an RTL label, only characters with the Bidi properties R, AL, AN, EN, ES,
+ // CS, ET, ON, BN, or NSM are allowed.
+ if (1 === preg_match(Regex::BIDI_STEP_2, $label)) {
+ $info->validBidiDomain = false;
+
+ return;
+ }
+
+ // Step 3. In an RTL label, the end of the label must be a character with Bidi property
+ // R, AL, EN, or AN, followed by zero or more characters with Bidi property NSM.
+ if (1 !== preg_match(Regex::BIDI_STEP_3, $label)) {
+ $info->validBidiDomain = false;
+
+ return;
+ }
+
+ // Step 4. In an RTL label, if an EN is present, no AN may be present, and vice versa.
+ if (1 === preg_match(Regex::BIDI_STEP_4_AN, $label) && 1 === preg_match(Regex::BIDI_STEP_4_EN, $label)) {
+ $info->validBidiDomain = false;
+
+ return;
+ }
+
+ return;
+ }
+
+ // We are a LTR label
+ // Step 1. The first character must be a character with Bidi property L, R, or AL.
+ // If it has the L property, it is an LTR label.
+ if (1 !== preg_match(Regex::BIDI_STEP_1_LTR, $label)) {
+ $info->validBidiDomain = false;
+
+ return;
+ }
+
+ // Step 5. In an LTR label, only characters with the Bidi properties L, EN,
+ // ES, CS, ET, ON, BN, or NSM are allowed.
+ if (1 === preg_match(Regex::BIDI_STEP_5, $label)) {
+ $info->validBidiDomain = false;
+
+ return;
+ }
+
+ // Step 6.In an LTR label, the end of the label must be a character with Bidi property L or
+ // EN, followed by zero or more characters with Bidi property NSM.
+ if (1 !== preg_match(Regex::BIDI_STEP_6, $label)) {
+ $info->validBidiDomain = false;
+
+ return;
+ }
+ }
+
+ /**
+ * @param array $labels
+ */
+ private static function validateDomainAndLabelLength(array $labels, Info $info)
+ {
+ $maxDomainSize = self::MAX_DOMAIN_SIZE;
+ $length = \count($labels);
+
+ // Number of "." delimiters.
+ $domainLength = $length - 1;
+
+ // If the last label is empty and it is not the first label, then it is the root label.
+ // Increase the max size by 1, making it 254, to account for the root label's "."
+ // delimiter. This also means we don't need to check the last label's length for being too
+ // long.
+ if ($length > 1 && '' === $labels[$length - 1]) {
+ ++$maxDomainSize;
+ --$length;
+ }
+
+ for ($i = 0; $i < $length; ++$i) {
+ $bytes = \strlen($labels[$i]);
+ $domainLength += $bytes;
+
+ if ($bytes > self::MAX_LABEL_SIZE) {
+ $info->errors |= self::ERROR_LABEL_TOO_LONG;
+ }
+ }
+
+ if ($domainLength > $maxDomainSize) {
+ $info->errors |= self::ERROR_DOMAIN_NAME_TOO_LONG;
+ }
+ }
+
+ /**
+ * @see https://www.unicode.org/reports/tr46/#Validity_Criteria
+ *
+ * @param string $label
+ * @param array $options
+ * @param bool $canBeEmpty
+ */
+ private static function validateLabel($label, Info $info, array $options, $canBeEmpty)
+ {
+ if ('' === $label) {
+ if (!$canBeEmpty && (!isset($options['VerifyDnsLength']) || $options['VerifyDnsLength'])) {
+ $info->errors |= self::ERROR_EMPTY_LABEL;
+ }
+
+ return;
+ }
+
+ // Step 1. The label must be in Unicode Normalization Form C.
+ if (!Normalizer::isNormalized($label, Normalizer::FORM_C)) {
+ $info->errors |= self::ERROR_INVALID_ACE_LABEL;
+ }
+
+ $codePoints = self::utf8Decode($label);
+
+ if ($options['CheckHyphens']) {
+ // Step 2. If CheckHyphens, the label must not contain a U+002D HYPHEN-MINUS character
+ // in both the thrid and fourth positions.
+ if (isset($codePoints[2], $codePoints[3]) && 0x002D === $codePoints[2] && 0x002D === $codePoints[3]) {
+ $info->errors |= self::ERROR_HYPHEN_3_4;
+ }
+
+ // Step 3. If CheckHyphens, the label must neither begin nor end with a U+002D
+ // HYPHEN-MINUS character.
+ if ('-' === substr($label, 0, 1)) {
+ $info->errors |= self::ERROR_LEADING_HYPHEN;
+ }
+
+ if ('-' === substr($label, -1, 1)) {
+ $info->errors |= self::ERROR_TRAILING_HYPHEN;
+ }
+ }
+
+ // Step 4. The label must not contain a U+002E (.) FULL STOP.
+ if (false !== strpos($label, '.')) {
+ $info->errors |= self::ERROR_LABEL_HAS_DOT;
+ }
+
+ // Step 5. The label must not begin with a combining mark, that is: General_Category=Mark.
+ if (1 === preg_match(Regex::COMBINING_MARK, $label)) {
+ $info->errors |= self::ERROR_LEADING_COMBINING_MARK;
+ }
+
+ // Step 6. Each code point in the label must only have certain status values according to
+ // Section 5, IDNA Mapping Table:
+ $transitional = $options['Transitional_Processing'];
+ $useSTD3ASCIIRules = $options['UseSTD3ASCIIRules'];
+
+ foreach ($codePoints as $codePoint) {
+ $data = self::lookupCodePointStatus($codePoint, $useSTD3ASCIIRules);
+ $status = $data['status'];
+
+ if ('valid' === $status || (!$transitional && 'deviation' === $status)) {
+ continue;
+ }
+
+ $info->errors |= self::ERROR_DISALLOWED;
+
+ break;
+ }
+
+ // Step 7. If CheckJoiners, the label must satisify the ContextJ rules from Appendix A, in
+ // The Unicode Code Points and Internationalized Domain Names for Applications (IDNA)
+ // [IDNA2008].
+ if ($options['CheckJoiners'] && !self::isValidContextJ($codePoints, $label)) {
+ $info->errors |= self::ERROR_CONTEXTJ;
+ }
+
+ // Step 8. If CheckBidi, and if the domain name is a Bidi domain name, then the label must
+ // satisfy all six of the numbered conditions in [IDNA2008] RFC 5893, Section 2.
+ if ($options['CheckBidi'] && (!$info->bidiDomain || $info->validBidiDomain)) {
+ self::validateBidiLabel($label, $info);
+ }
+ }
+
+ /**
+ * @see https://tools.ietf.org/html/rfc3492#section-6.2
+ *
+ * @param string $input
+ *
+ * @return string
+ */
+ private static function punycodeDecode($input)
+ {
+ $n = self::INITIAL_N;
+ $out = 0;
+ $i = 0;
+ $bias = self::INITIAL_BIAS;
+ $lastDelimIndex = strrpos($input, self::DELIMITER);
+ $b = false === $lastDelimIndex ? 0 : $lastDelimIndex;
+ $inputLength = \strlen($input);
+ $output = [];
+ $bytes = array_map('ord', str_split($input));
+
+ for ($j = 0; $j < $b; ++$j) {
+ if ($bytes[$j] > 0x7F) {
+ throw new Exception('Invalid input');
+ }
+
+ $output[$out++] = $input[$j];
+ }
+
+ if ($b > 0) {
+ ++$b;
+ }
+
+ for ($in = $b; $in < $inputLength; ++$out) {
+ $oldi = $i;
+ $w = 1;
+
+ for ($k = self::BASE; /* no condition */; $k += self::BASE) {
+ if ($in >= $inputLength) {
+ throw new Exception('Invalid input');
+ }
+
+ $digit = self::$basicToDigit[$bytes[$in++] & 0xFF];
+
+ if ($digit < 0) {
+ throw new Exception('Invalid input');
+ }
+
+ if ($digit > intdiv(self::MAX_INT - $i, $w)) {
+ throw new Exception('Integer overflow');
+ }
+
+ $i += $digit * $w;
+
+ if ($k <= $bias) {
+ $t = self::TMIN;
+ } elseif ($k >= $bias + self::TMAX) {
+ $t = self::TMAX;
+ } else {
+ $t = $k - $bias;
+ }
+
+ if ($digit < $t) {
+ break;
+ }
+
+ $baseMinusT = self::BASE - $t;
+
+ if ($w > intdiv(self::MAX_INT, $baseMinusT)) {
+ throw new Exception('Integer overflow');
+ }
+
+ $w *= $baseMinusT;
+ }
+
+ $outPlusOne = $out + 1;
+ $bias = self::adaptBias($i - $oldi, $outPlusOne, 0 === $oldi);
+
+ if (intdiv($i, $outPlusOne) > self::MAX_INT - $n) {
+ throw new Exception('Integer overflow');
+ }
+
+ $n += intdiv($i, $outPlusOne);
+ $i %= $outPlusOne;
+ array_splice($output, $i++, 0, [mb_chr($n, 'utf-8')]);
+ }
+
+ return implode('', $output);
+ }
+
+ /**
+ * @see https://tools.ietf.org/html/rfc3492#section-6.3
+ *
+ * @param string $input
+ *
+ * @return string
+ */
+ private static function punycodeEncode($input)
+ {
+ $n = self::INITIAL_N;
+ $delta = 0;
+ $out = 0;
+ $bias = self::INITIAL_BIAS;
+ $inputLength = 0;
+ $output = '';
+ $iter = self::utf8Decode($input);
+
+ foreach ($iter as $codePoint) {
+ ++$inputLength;
+
+ if ($codePoint < 0x80) {
+ $output .= \chr($codePoint);
+ ++$out;
+ }
+ }
+
+ $h = $out;
+ $b = $out;
+
+ if ($b > 0) {
+ $output .= self::DELIMITER;
+ ++$out;
+ }
+
+ while ($h < $inputLength) {
+ $m = self::MAX_INT;
+
+ foreach ($iter as $codePoint) {
+ if ($codePoint >= $n && $codePoint < $m) {
+ $m = $codePoint;
+ }
+ }
+
+ if ($m - $n > intdiv(self::MAX_INT - $delta, $h + 1)) {
+ throw new Exception('Integer overflow');
+ }
+
+ $delta += ($m - $n) * ($h + 1);
+ $n = $m;
+
+ foreach ($iter as $codePoint) {
+ if ($codePoint < $n && 0 === ++$delta) {
+ throw new Exception('Integer overflow');
+ }
+
+ if ($codePoint === $n) {
+ $q = $delta;
+
+ for ($k = self::BASE; /* no condition */; $k += self::BASE) {
+ if ($k <= $bias) {
+ $t = self::TMIN;
+ } elseif ($k >= $bias + self::TMAX) {
+ $t = self::TMAX;
+ } else {
+ $t = $k - $bias;
+ }
+
+ if ($q < $t) {
+ break;
+ }
+
+ $qMinusT = $q - $t;
+ $baseMinusT = self::BASE - $t;
+ $output .= self::encodeDigit($t + ($qMinusT) % ($baseMinusT), false);
+ ++$out;
+ $q = intdiv($qMinusT, $baseMinusT);
+ }
+
+ $output .= self::encodeDigit($q, false);
+ ++$out;
+ $bias = self::adaptBias($delta, $h + 1, $h === $b);
+ $delta = 0;
+ ++$h;
+ }
+ }
+
+ ++$delta;
+ ++$n;
+ }
+
+ return $output;
+ }
+
+ /**
+ * @see https://tools.ietf.org/html/rfc3492#section-6.1
+ *
+ * @param int $delta
+ * @param int $numPoints
+ * @param bool $firstTime
+ *
+ * @return int
+ */
+ private static function adaptBias($delta, $numPoints, $firstTime)
+ {
+ // xxx >> 1 is a faster way of doing intdiv(xxx, 2)
+ $delta = $firstTime ? intdiv($delta, self::DAMP) : $delta >> 1;
+ $delta += intdiv($delta, $numPoints);
+ $k = 0;
+
+ while ($delta > ((self::BASE - self::TMIN) * self::TMAX) >> 1) {
+ $delta = intdiv($delta, self::BASE - self::TMIN);
+ $k += self::BASE;
+ }
+
+ return $k + intdiv((self::BASE - self::TMIN + 1) * $delta, $delta + self::SKEW);
+ }
+
+ /**
+ * @param int $d
+ * @param bool $flag
+ *
+ * @return string
+ */
+ private static function encodeDigit($d, $flag)
+ {
+ return \chr($d + 22 + 75 * ($d < 26 ? 1 : 0) - (($flag ? 1 : 0) << 5));
+ }
+
+ /**
+ * Takes a UTF-8 encoded string and converts it into a series of integer code points. Any
+ * invalid byte sequences will be replaced by a U+FFFD replacement code point.
+ *
+ * @see https://encoding.spec.whatwg.org/#utf-8-decoder
+ *
+ * @param string $input
+ *
+ * @return array
+ */
+ private static function utf8Decode($input)
+ {
+ $bytesSeen = 0;
+ $bytesNeeded = 0;
+ $lowerBoundary = 0x80;
+ $upperBoundary = 0xBF;
+ $codePoint = 0;
+ $codePoints = [];
+ $length = \strlen($input);
+
+ for ($i = 0; $i < $length; ++$i) {
+ $byte = \ord($input[$i]);
+
+ if (0 === $bytesNeeded) {
+ if ($byte >= 0x00 && $byte <= 0x7F) {
+ $codePoints[] = $byte;
+
+ continue;
+ }
+
+ if ($byte >= 0xC2 && $byte <= 0xDF) {
+ $bytesNeeded = 1;
+ $codePoint = $byte & 0x1F;
+ } elseif ($byte >= 0xE0 && $byte <= 0xEF) {
+ if (0xE0 === $byte) {
+ $lowerBoundary = 0xA0;
+ } elseif (0xED === $byte) {
+ $upperBoundary = 0x9F;
+ }
+
+ $bytesNeeded = 2;
+ $codePoint = $byte & 0xF;
+ } elseif ($byte >= 0xF0 && $byte <= 0xF4) {
+ if (0xF0 === $byte) {
+ $lowerBoundary = 0x90;
+ } elseif (0xF4 === $byte) {
+ $upperBoundary = 0x8F;
+ }
+
+ $bytesNeeded = 3;
+ $codePoint = $byte & 0x7;
+ } else {
+ $codePoints[] = 0xFFFD;
+ }
+
+ continue;
+ }
+
+ if ($byte < $lowerBoundary || $byte > $upperBoundary) {
+ $codePoint = 0;
+ $bytesNeeded = 0;
+ $bytesSeen = 0;
+ $lowerBoundary = 0x80;
+ $upperBoundary = 0xBF;
+ --$i;
+ $codePoints[] = 0xFFFD;
+
+ continue;
+ }
+
+ $lowerBoundary = 0x80;
+ $upperBoundary = 0xBF;
+ $codePoint = ($codePoint << 6) | ($byte & 0x3F);
+
+ if (++$bytesSeen !== $bytesNeeded) {
+ continue;
+ }
+
+ $codePoints[] = $codePoint;
+ $codePoint = 0;
+ $bytesNeeded = 0;
+ $bytesSeen = 0;
+ }
+
+ // String unexpectedly ended, so append a U+FFFD code point.
+ if (0 !== $bytesNeeded) {
+ $codePoints[] = 0xFFFD;
+ }
+
+ return $codePoints;
+ }
+
+ /**
+ * @param int $codePoint
+ * @param bool $useSTD3ASCIIRules
+ *
+ * @return array{status: string, mapping?: string}
+ */
+ private static function lookupCodePointStatus($codePoint, $useSTD3ASCIIRules)
+ {
+ if (!self::$mappingTableLoaded) {
+ self::$mappingTableLoaded = true;
+ self::$mapped = require __DIR__.'/Resources/unidata/mapped.php';
+ self::$ignored = require __DIR__.'/Resources/unidata/ignored.php';
+ self::$deviation = require __DIR__.'/Resources/unidata/deviation.php';
+ self::$disallowed = require __DIR__.'/Resources/unidata/disallowed.php';
+ self::$disallowed_STD3_mapped = require __DIR__.'/Resources/unidata/disallowed_STD3_mapped.php';
+ self::$disallowed_STD3_valid = require __DIR__.'/Resources/unidata/disallowed_STD3_valid.php';
+ }
+
+ if (isset(self::$mapped[$codePoint])) {
+ return ['status' => 'mapped', 'mapping' => self::$mapped[$codePoint]];
+ }
+
+ if (isset(self::$ignored[$codePoint])) {
+ return ['status' => 'ignored'];
+ }
+
+ if (isset(self::$deviation[$codePoint])) {
+ return ['status' => 'deviation', 'mapping' => self::$deviation[$codePoint]];
+ }
+
+ if (isset(self::$disallowed[$codePoint]) || DisallowedRanges::inRange($codePoint)) {
+ return ['status' => 'disallowed'];
+ }
+
+ $isDisallowedMapped = isset(self::$disallowed_STD3_mapped[$codePoint]);
+
+ if ($isDisallowedMapped || isset(self::$disallowed_STD3_valid[$codePoint])) {
+ $status = 'disallowed';
+
+ if (!$useSTD3ASCIIRules) {
+ $status = $isDisallowedMapped ? 'mapped' : 'valid';
+ }
+
+ if ($isDisallowedMapped) {
+ return ['status' => $status, 'mapping' => self::$disallowed_STD3_mapped[$codePoint]];
+ }
+
+ return ['status' => $status];
+ }
+
+ return ['status' => 'valid'];
+ }
+}
diff --git a/vendor/symfony/polyfill-intl-idn/Info.php b/vendor/symfony/polyfill-intl-idn/Info.php
new file mode 100644
index 0000000..25c3582
--- /dev/null
+++ b/vendor/symfony/polyfill-intl-idn/Info.php
@@ -0,0 +1,23 @@
+ and Trevor Rowbotham
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Polyfill\Intl\Idn;
+
+/**
+ * @internal
+ */
+class Info
+{
+ public $bidiDomain = false;
+ public $errors = 0;
+ public $validBidiDomain = true;
+ public $transitionalDifferent = false;
+}
diff --git a/vendor/symfony/polyfill-intl-idn/LICENSE b/vendor/symfony/polyfill-intl-idn/LICENSE
new file mode 100644
index 0000000..03c5e25
--- /dev/null
+++ b/vendor/symfony/polyfill-intl-idn/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2018-2019 Fabien Potencier and Trevor Rowbotham
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/symfony/polyfill-intl-idn/README.md b/vendor/symfony/polyfill-intl-idn/README.md
new file mode 100644
index 0000000..cae5517
--- /dev/null
+++ b/vendor/symfony/polyfill-intl-idn/README.md
@@ -0,0 +1,12 @@
+Symfony Polyfill / Intl: Idn
+============================
+
+This component provides [`idn_to_ascii`](https://php.net/idn-to-ascii) and [`idn_to_utf8`](https://php.net/idn-to-utf8) functions to users who run php versions without the [Intl](https://php.net/intl) 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/vendor/symfony/polyfill-intl-idn/Resources/unidata/DisallowedRanges.php b/vendor/symfony/polyfill-intl-idn/Resources/unidata/DisallowedRanges.php
new file mode 100644
index 0000000..5bb70e4
--- /dev/null
+++ b/vendor/symfony/polyfill-intl-idn/Resources/unidata/DisallowedRanges.php
@@ -0,0 +1,375 @@
+= 128 && $codePoint <= 159) {
+ return true;
+ }
+
+ if ($codePoint >= 2155 && $codePoint <= 2207) {
+ return true;
+ }
+
+ if ($codePoint >= 3676 && $codePoint <= 3712) {
+ return true;
+ }
+
+ if ($codePoint >= 3808 && $codePoint <= 3839) {
+ return true;
+ }
+
+ if ($codePoint >= 4059 && $codePoint <= 4095) {
+ return true;
+ }
+
+ if ($codePoint >= 4256 && $codePoint <= 4293) {
+ return true;
+ }
+
+ if ($codePoint >= 6849 && $codePoint <= 6911) {
+ return true;
+ }
+
+ if ($codePoint >= 11859 && $codePoint <= 11903) {
+ return true;
+ }
+
+ if ($codePoint >= 42955 && $codePoint <= 42996) {
+ return true;
+ }
+
+ if ($codePoint >= 55296 && $codePoint <= 57343) {
+ return true;
+ }
+
+ if ($codePoint >= 57344 && $codePoint <= 63743) {
+ return true;
+ }
+
+ if ($codePoint >= 64218 && $codePoint <= 64255) {
+ return true;
+ }
+
+ if ($codePoint >= 64976 && $codePoint <= 65007) {
+ return true;
+ }
+
+ if ($codePoint >= 65630 && $codePoint <= 65663) {
+ return true;
+ }
+
+ if ($codePoint >= 65953 && $codePoint <= 65999) {
+ return true;
+ }
+
+ if ($codePoint >= 66046 && $codePoint <= 66175) {
+ return true;
+ }
+
+ if ($codePoint >= 66518 && $codePoint <= 66559) {
+ return true;
+ }
+
+ if ($codePoint >= 66928 && $codePoint <= 67071) {
+ return true;
+ }
+
+ if ($codePoint >= 67432 && $codePoint <= 67583) {
+ return true;
+ }
+
+ if ($codePoint >= 67760 && $codePoint <= 67807) {
+ return true;
+ }
+
+ if ($codePoint >= 67904 && $codePoint <= 67967) {
+ return true;
+ }
+
+ if ($codePoint >= 68256 && $codePoint <= 68287) {
+ return true;
+ }
+
+ if ($codePoint >= 68528 && $codePoint <= 68607) {
+ return true;
+ }
+
+ if ($codePoint >= 68681 && $codePoint <= 68735) {
+ return true;
+ }
+
+ if ($codePoint >= 68922 && $codePoint <= 69215) {
+ return true;
+ }
+
+ if ($codePoint >= 69298 && $codePoint <= 69375) {
+ return true;
+ }
+
+ if ($codePoint >= 69466 && $codePoint <= 69551) {
+ return true;
+ }
+
+ if ($codePoint >= 70207 && $codePoint <= 70271) {
+ return true;
+ }
+
+ if ($codePoint >= 70517 && $codePoint <= 70655) {
+ return true;
+ }
+
+ if ($codePoint >= 70874 && $codePoint <= 71039) {
+ return true;
+ }
+
+ if ($codePoint >= 71134 && $codePoint <= 71167) {
+ return true;
+ }
+
+ if ($codePoint >= 71370 && $codePoint <= 71423) {
+ return true;
+ }
+
+ if ($codePoint >= 71488 && $codePoint <= 71679) {
+ return true;
+ }
+
+ if ($codePoint >= 71740 && $codePoint <= 71839) {
+ return true;
+ }
+
+ if ($codePoint >= 72026 && $codePoint <= 72095) {
+ return true;
+ }
+
+ if ($codePoint >= 72441 && $codePoint <= 72703) {
+ return true;
+ }
+
+ if ($codePoint >= 72887 && $codePoint <= 72959) {
+ return true;
+ }
+
+ if ($codePoint >= 73130 && $codePoint <= 73439) {
+ return true;
+ }
+
+ if ($codePoint >= 73465 && $codePoint <= 73647) {
+ return true;
+ }
+
+ if ($codePoint >= 74650 && $codePoint <= 74751) {
+ return true;
+ }
+
+ if ($codePoint >= 75076 && $codePoint <= 77823) {
+ return true;
+ }
+
+ if ($codePoint >= 78905 && $codePoint <= 82943) {
+ return true;
+ }
+
+ if ($codePoint >= 83527 && $codePoint <= 92159) {
+ return true;
+ }
+
+ if ($codePoint >= 92784 && $codePoint <= 92879) {
+ return true;
+ }
+
+ if ($codePoint >= 93072 && $codePoint <= 93759) {
+ return true;
+ }
+
+ if ($codePoint >= 93851 && $codePoint <= 93951) {
+ return true;
+ }
+
+ if ($codePoint >= 94112 && $codePoint <= 94175) {
+ return true;
+ }
+
+ if ($codePoint >= 101590 && $codePoint <= 101631) {
+ return true;
+ }
+
+ if ($codePoint >= 101641 && $codePoint <= 110591) {
+ return true;
+ }
+
+ if ($codePoint >= 110879 && $codePoint <= 110927) {
+ return true;
+ }
+
+ if ($codePoint >= 111356 && $codePoint <= 113663) {
+ return true;
+ }
+
+ if ($codePoint >= 113828 && $codePoint <= 118783) {
+ return true;
+ }
+
+ if ($codePoint >= 119366 && $codePoint <= 119519) {
+ return true;
+ }
+
+ if ($codePoint >= 119673 && $codePoint <= 119807) {
+ return true;
+ }
+
+ if ($codePoint >= 121520 && $codePoint <= 122879) {
+ return true;
+ }
+
+ if ($codePoint >= 122923 && $codePoint <= 123135) {
+ return true;
+ }
+
+ if ($codePoint >= 123216 && $codePoint <= 123583) {
+ return true;
+ }
+
+ if ($codePoint >= 123648 && $codePoint <= 124927) {
+ return true;
+ }
+
+ if ($codePoint >= 125143 && $codePoint <= 125183) {
+ return true;
+ }
+
+ if ($codePoint >= 125280 && $codePoint <= 126064) {
+ return true;
+ }
+
+ if ($codePoint >= 126133 && $codePoint <= 126208) {
+ return true;
+ }
+
+ if ($codePoint >= 126270 && $codePoint <= 126463) {
+ return true;
+ }
+
+ if ($codePoint >= 126652 && $codePoint <= 126703) {
+ return true;
+ }
+
+ if ($codePoint >= 126706 && $codePoint <= 126975) {
+ return true;
+ }
+
+ if ($codePoint >= 127406 && $codePoint <= 127461) {
+ return true;
+ }
+
+ if ($codePoint >= 127590 && $codePoint <= 127743) {
+ return true;
+ }
+
+ if ($codePoint >= 129202 && $codePoint <= 129279) {
+ return true;
+ }
+
+ if ($codePoint >= 129751 && $codePoint <= 129791) {
+ return true;
+ }
+
+ if ($codePoint >= 129995 && $codePoint <= 130031) {
+ return true;
+ }
+
+ if ($codePoint >= 130042 && $codePoint <= 131069) {
+ return true;
+ }
+
+ if ($codePoint >= 173790 && $codePoint <= 173823) {
+ return true;
+ }
+
+ if ($codePoint >= 191457 && $codePoint <= 194559) {
+ return true;
+ }
+
+ if ($codePoint >= 195102 && $codePoint <= 196605) {
+ return true;
+ }
+
+ if ($codePoint >= 201547 && $codePoint <= 262141) {
+ return true;
+ }
+
+ if ($codePoint >= 262144 && $codePoint <= 327677) {
+ return true;
+ }
+
+ if ($codePoint >= 327680 && $codePoint <= 393213) {
+ return true;
+ }
+
+ if ($codePoint >= 393216 && $codePoint <= 458749) {
+ return true;
+ }
+
+ if ($codePoint >= 458752 && $codePoint <= 524285) {
+ return true;
+ }
+
+ if ($codePoint >= 524288 && $codePoint <= 589821) {
+ return true;
+ }
+
+ if ($codePoint >= 589824 && $codePoint <= 655357) {
+ return true;
+ }
+
+ if ($codePoint >= 655360 && $codePoint <= 720893) {
+ return true;
+ }
+
+ if ($codePoint >= 720896 && $codePoint <= 786429) {
+ return true;
+ }
+
+ if ($codePoint >= 786432 && $codePoint <= 851965) {
+ return true;
+ }
+
+ if ($codePoint >= 851968 && $codePoint <= 917501) {
+ return true;
+ }
+
+ if ($codePoint >= 917536 && $codePoint <= 917631) {
+ return true;
+ }
+
+ if ($codePoint >= 917632 && $codePoint <= 917759) {
+ return true;
+ }
+
+ if ($codePoint >= 918000 && $codePoint <= 983037) {
+ return true;
+ }
+
+ if ($codePoint >= 983040 && $codePoint <= 1048573) {
+ return true;
+ }
+
+ if ($codePoint >= 1048576 && $codePoint <= 1114109) {
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/vendor/symfony/polyfill-intl-idn/Resources/unidata/Regex.php b/vendor/symfony/polyfill-intl-idn/Resources/unidata/Regex.php
new file mode 100644
index 0000000..5c1c51d
--- /dev/null
+++ b/vendor/symfony/polyfill-intl-idn/Resources/unidata/Regex.php
@@ -0,0 +1,24 @@
+ 'ss',
+ 962 => 'σ',
+ 8204 => '',
+ 8205 => '',
+);
diff --git a/vendor/symfony/polyfill-intl-idn/Resources/unidata/disallowed.php b/vendor/symfony/polyfill-intl-idn/Resources/unidata/disallowed.php
new file mode 100644
index 0000000..25a5f56
--- /dev/null
+++ b/vendor/symfony/polyfill-intl-idn/Resources/unidata/disallowed.php
@@ -0,0 +1,2638 @@
+ true,
+ 889 => true,
+ 896 => true,
+ 897 => true,
+ 898 => true,
+ 899 => true,
+ 907 => true,
+ 909 => true,
+ 930 => true,
+ 1216 => true,
+ 1328 => true,
+ 1367 => true,
+ 1368 => true,
+ 1419 => true,
+ 1420 => true,
+ 1424 => true,
+ 1480 => true,
+ 1481 => true,
+ 1482 => true,
+ 1483 => true,
+ 1484 => true,
+ 1485 => true,
+ 1486 => true,
+ 1487 => true,
+ 1515 => true,
+ 1516 => true,
+ 1517 => true,
+ 1518 => true,
+ 1525 => true,
+ 1526 => true,
+ 1527 => true,
+ 1528 => true,
+ 1529 => true,
+ 1530 => true,
+ 1531 => true,
+ 1532 => true,
+ 1533 => true,
+ 1534 => true,
+ 1535 => true,
+ 1536 => true,
+ 1537 => true,
+ 1538 => true,
+ 1539 => true,
+ 1540 => true,
+ 1541 => true,
+ 1564 => true,
+ 1565 => true,
+ 1757 => true,
+ 1806 => true,
+ 1807 => true,
+ 1867 => true,
+ 1868 => true,
+ 1970 => true,
+ 1971 => true,
+ 1972 => true,
+ 1973 => true,
+ 1974 => true,
+ 1975 => true,
+ 1976 => true,
+ 1977 => true,
+ 1978 => true,
+ 1979 => true,
+ 1980 => true,
+ 1981 => true,
+ 1982 => true,
+ 1983 => true,
+ 2043 => true,
+ 2044 => true,
+ 2094 => true,
+ 2095 => true,
+ 2111 => true,
+ 2140 => true,
+ 2141 => true,
+ 2143 => true,
+ 2229 => true,
+ 2248 => true,
+ 2249 => true,
+ 2250 => true,
+ 2251 => true,
+ 2252 => true,
+ 2253 => true,
+ 2254 => true,
+ 2255 => true,
+ 2256 => true,
+ 2257 => true,
+ 2258 => true,
+ 2274 => true,
+ 2436 => true,
+ 2445 => true,
+ 2446 => true,
+ 2449 => true,
+ 2450 => true,
+ 2473 => true,
+ 2481 => true,
+ 2483 => true,
+ 2484 => true,
+ 2485 => true,
+ 2490 => true,
+ 2491 => true,
+ 2501 => true,
+ 2502 => true,
+ 2505 => true,
+ 2506 => true,
+ 2511 => true,
+ 2512 => true,
+ 2513 => true,
+ 2514 => true,
+ 2515 => true,
+ 2516 => true,
+ 2517 => true,
+ 2518 => true,
+ 2520 => true,
+ 2521 => true,
+ 2522 => true,
+ 2523 => true,
+ 2526 => true,
+ 2532 => true,
+ 2533 => true,
+ 2559 => true,
+ 2560 => true,
+ 2564 => true,
+ 2571 => true,
+ 2572 => true,
+ 2573 => true,
+ 2574 => true,
+ 2577 => true,
+ 2578 => true,
+ 2601 => true,
+ 2609 => true,
+ 2612 => true,
+ 2615 => true,
+ 2618 => true,
+ 2619 => true,
+ 2621 => true,
+ 2627 => true,
+ 2628 => true,
+ 2629 => true,
+ 2630 => true,
+ 2633 => true,
+ 2634 => true,
+ 2638 => true,
+ 2639 => true,
+ 2640 => true,
+ 2642 => true,
+ 2643 => true,
+ 2644 => true,
+ 2645 => true,
+ 2646 => true,
+ 2647 => true,
+ 2648 => true,
+ 2653 => true,
+ 2655 => true,
+ 2656 => true,
+ 2657 => true,
+ 2658 => true,
+ 2659 => true,
+ 2660 => true,
+ 2661 => true,
+ 2679 => true,
+ 2680 => true,
+ 2681 => true,
+ 2682 => true,
+ 2683 => true,
+ 2684 => true,
+ 2685 => true,
+ 2686 => true,
+ 2687 => true,
+ 2688 => true,
+ 2692 => true,
+ 2702 => true,
+ 2706 => true,
+ 2729 => true,
+ 2737 => true,
+ 2740 => true,
+ 2746 => true,
+ 2747 => true,
+ 2758 => true,
+ 2762 => true,
+ 2766 => true,
+ 2767 => true,
+ 2769 => true,
+ 2770 => true,
+ 2771 => true,
+ 2772 => true,
+ 2773 => true,
+ 2774 => true,
+ 2775 => true,
+ 2776 => true,
+ 2777 => true,
+ 2778 => true,
+ 2779 => true,
+ 2780 => true,
+ 2781 => true,
+ 2782 => true,
+ 2783 => true,
+ 2788 => true,
+ 2789 => true,
+ 2802 => true,
+ 2803 => true,
+ 2804 => true,
+ 2805 => true,
+ 2806 => true,
+ 2807 => true,
+ 2808 => true,
+ 2816 => true,
+ 2820 => true,
+ 2829 => true,
+ 2830 => true,
+ 2833 => true,
+ 2834 => true,
+ 2857 => true,
+ 2865 => true,
+ 2868 => true,
+ 2874 => true,
+ 2875 => true,
+ 2885 => true,
+ 2886 => true,
+ 2889 => true,
+ 2890 => true,
+ 2894 => true,
+ 2895 => true,
+ 2896 => true,
+ 2897 => true,
+ 2898 => true,
+ 2899 => true,
+ 2900 => true,
+ 2904 => true,
+ 2905 => true,
+ 2906 => true,
+ 2907 => true,
+ 2910 => true,
+ 2916 => true,
+ 2917 => true,
+ 2936 => true,
+ 2937 => true,
+ 2938 => true,
+ 2939 => true,
+ 2940 => true,
+ 2941 => true,
+ 2942 => true,
+ 2943 => true,
+ 2944 => true,
+ 2945 => true,
+ 2948 => true,
+ 2955 => true,
+ 2956 => true,
+ 2957 => true,
+ 2961 => true,
+ 2966 => true,
+ 2967 => true,
+ 2968 => true,
+ 2971 => true,
+ 2973 => true,
+ 2976 => true,
+ 2977 => true,
+ 2978 => true,
+ 2981 => true,
+ 2982 => true,
+ 2983 => true,
+ 2987 => true,
+ 2988 => true,
+ 2989 => true,
+ 3002 => true,
+ 3003 => true,
+ 3004 => true,
+ 3005 => true,
+ 3011 => true,
+ 3012 => true,
+ 3013 => true,
+ 3017 => true,
+ 3022 => true,
+ 3023 => true,
+ 3025 => true,
+ 3026 => true,
+ 3027 => true,
+ 3028 => true,
+ 3029 => true,
+ 3030 => true,
+ 3032 => true,
+ 3033 => true,
+ 3034 => true,
+ 3035 => true,
+ 3036 => true,
+ 3037 => true,
+ 3038 => true,
+ 3039 => true,
+ 3040 => true,
+ 3041 => true,
+ 3042 => true,
+ 3043 => true,
+ 3044 => true,
+ 3045 => true,
+ 3067 => true,
+ 3068 => true,
+ 3069 => true,
+ 3070 => true,
+ 3071 => true,
+ 3085 => true,
+ 3089 => true,
+ 3113 => true,
+ 3130 => true,
+ 3131 => true,
+ 3132 => true,
+ 3141 => true,
+ 3145 => true,
+ 3150 => true,
+ 3151 => true,
+ 3152 => true,
+ 3153 => true,
+ 3154 => true,
+ 3155 => true,
+ 3156 => true,
+ 3159 => true,
+ 3163 => true,
+ 3164 => true,
+ 3165 => true,
+ 3166 => true,
+ 3167 => true,
+ 3172 => true,
+ 3173 => true,
+ 3184 => true,
+ 3185 => true,
+ 3186 => true,
+ 3187 => true,
+ 3188 => true,
+ 3189 => true,
+ 3190 => true,
+ 3213 => true,
+ 3217 => true,
+ 3241 => true,
+ 3252 => true,
+ 3258 => true,
+ 3259 => true,
+ 3269 => true,
+ 3273 => true,
+ 3278 => true,
+ 3279 => true,
+ 3280 => true,
+ 3281 => true,
+ 3282 => true,
+ 3283 => true,
+ 3284 => true,
+ 3287 => true,
+ 3288 => true,
+ 3289 => true,
+ 3290 => true,
+ 3291 => true,
+ 3292 => true,
+ 3293 => true,
+ 3295 => true,
+ 3300 => true,
+ 3301 => true,
+ 3312 => true,
+ 3315 => true,
+ 3316 => true,
+ 3317 => true,
+ 3318 => true,
+ 3319 => true,
+ 3320 => true,
+ 3321 => true,
+ 3322 => true,
+ 3323 => true,
+ 3324 => true,
+ 3325 => true,
+ 3326 => true,
+ 3327 => true,
+ 3341 => true,
+ 3345 => true,
+ 3397 => true,
+ 3401 => true,
+ 3408 => true,
+ 3409 => true,
+ 3410 => true,
+ 3411 => true,
+ 3428 => true,
+ 3429 => true,
+ 3456 => true,
+ 3460 => true,
+ 3479 => true,
+ 3480 => true,
+ 3481 => true,
+ 3506 => true,
+ 3516 => true,
+ 3518 => true,
+ 3519 => true,
+ 3527 => true,
+ 3528 => true,
+ 3529 => true,
+ 3531 => true,
+ 3532 => true,
+ 3533 => true,
+ 3534 => true,
+ 3541 => true,
+ 3543 => true,
+ 3552 => true,
+ 3553 => true,
+ 3554 => true,
+ 3555 => true,
+ 3556 => true,
+ 3557 => true,
+ 3568 => true,
+ 3569 => true,
+ 3573 => true,
+ 3574 => true,
+ 3575 => true,
+ 3576 => true,
+ 3577 => true,
+ 3578 => true,
+ 3579 => true,
+ 3580 => true,
+ 3581 => true,
+ 3582 => true,
+ 3583 => true,
+ 3584 => true,
+ 3643 => true,
+ 3644 => true,
+ 3645 => true,
+ 3646 => true,
+ 3715 => true,
+ 3717 => true,
+ 3723 => true,
+ 3748 => true,
+ 3750 => true,
+ 3774 => true,
+ 3775 => true,
+ 3781 => true,
+ 3783 => true,
+ 3790 => true,
+ 3791 => true,
+ 3802 => true,
+ 3803 => true,
+ 3912 => true,
+ 3949 => true,
+ 3950 => true,
+ 3951 => true,
+ 3952 => true,
+ 3992 => true,
+ 4029 => true,
+ 4045 => true,
+ 4294 => true,
+ 4296 => true,
+ 4297 => true,
+ 4298 => true,
+ 4299 => true,
+ 4300 => true,
+ 4302 => true,
+ 4303 => true,
+ 4447 => true,
+ 4448 => true,
+ 4681 => true,
+ 4686 => true,
+ 4687 => true,
+ 4695 => true,
+ 4697 => true,
+ 4702 => true,
+ 4703 => true,
+ 4745 => true,
+ 4750 => true,
+ 4751 => true,
+ 4785 => true,
+ 4790 => true,
+ 4791 => true,
+ 4799 => true,
+ 4801 => true,
+ 4806 => true,
+ 4807 => true,
+ 4823 => true,
+ 4881 => true,
+ 4886 => true,
+ 4887 => true,
+ 4955 => true,
+ 4956 => true,
+ 4989 => true,
+ 4990 => true,
+ 4991 => true,
+ 5018 => true,
+ 5019 => true,
+ 5020 => true,
+ 5021 => true,
+ 5022 => true,
+ 5023 => true,
+ 5110 => true,
+ 5111 => true,
+ 5118 => true,
+ 5119 => true,
+ 5760 => true,
+ 5789 => true,
+ 5790 => true,
+ 5791 => true,
+ 5881 => true,
+ 5882 => true,
+ 5883 => true,
+ 5884 => true,
+ 5885 => true,
+ 5886 => true,
+ 5887 => true,
+ 5901 => true,
+ 5909 => true,
+ 5910 => true,
+ 5911 => true,
+ 5912 => true,
+ 5913 => true,
+ 5914 => true,
+ 5915 => true,
+ 5916 => true,
+ 5917 => true,
+ 5918 => true,
+ 5919 => true,
+ 5943 => true,
+ 5944 => true,
+ 5945 => true,
+ 5946 => true,
+ 5947 => true,
+ 5948 => true,
+ 5949 => true,
+ 5950 => true,
+ 5951 => true,
+ 5972 => true,
+ 5973 => true,
+ 5974 => true,
+ 5975 => true,
+ 5976 => true,
+ 5977 => true,
+ 5978 => true,
+ 5979 => true,
+ 5980 => true,
+ 5981 => true,
+ 5982 => true,
+ 5983 => true,
+ 5997 => true,
+ 6001 => true,
+ 6004 => true,
+ 6005 => true,
+ 6006 => true,
+ 6007 => true,
+ 6008 => true,
+ 6009 => true,
+ 6010 => true,
+ 6011 => true,
+ 6012 => true,
+ 6013 => true,
+ 6014 => true,
+ 6015 => true,
+ 6068 => true,
+ 6069 => true,
+ 6110 => true,
+ 6111 => true,
+ 6122 => true,
+ 6123 => true,
+ 6124 => true,
+ 6125 => true,
+ 6126 => true,
+ 6127 => true,
+ 6138 => true,
+ 6139 => true,
+ 6140 => true,
+ 6141 => true,
+ 6142 => true,
+ 6143 => true,
+ 6150 => true,
+ 6158 => true,
+ 6159 => true,
+ 6170 => true,
+ 6171 => true,
+ 6172 => true,
+ 6173 => true,
+ 6174 => true,
+ 6175 => true,
+ 6265 => true,
+ 6266 => true,
+ 6267 => true,
+ 6268 => true,
+ 6269 => true,
+ 6270 => true,
+ 6271 => true,
+ 6315 => true,
+ 6316 => true,
+ 6317 => true,
+ 6318 => true,
+ 6319 => true,
+ 6390 => true,
+ 6391 => true,
+ 6392 => true,
+ 6393 => true,
+ 6394 => true,
+ 6395 => true,
+ 6396 => true,
+ 6397 => true,
+ 6398 => true,
+ 6399 => true,
+ 6431 => true,
+ 6444 => true,
+ 6445 => true,
+ 6446 => true,
+ 6447 => true,
+ 6460 => true,
+ 6461 => true,
+ 6462 => true,
+ 6463 => true,
+ 6465 => true,
+ 6466 => true,
+ 6467 => true,
+ 6510 => true,
+ 6511 => true,
+ 6517 => true,
+ 6518 => true,
+ 6519 => true,
+ 6520 => true,
+ 6521 => true,
+ 6522 => true,
+ 6523 => true,
+ 6524 => true,
+ 6525 => true,
+ 6526 => true,
+ 6527 => true,
+ 6572 => true,
+ 6573 => true,
+ 6574 => true,
+ 6575 => true,
+ 6602 => true,
+ 6603 => true,
+ 6604 => true,
+ 6605 => true,
+ 6606 => true,
+ 6607 => true,
+ 6619 => true,
+ 6620 => true,
+ 6621 => true,
+ 6684 => true,
+ 6685 => true,
+ 6751 => true,
+ 6781 => true,
+ 6782 => true,
+ 6794 => true,
+ 6795 => true,
+ 6796 => true,
+ 6797 => true,
+ 6798 => true,
+ 6799 => true,
+ 6810 => true,
+ 6811 => true,
+ 6812 => true,
+ 6813 => true,
+ 6814 => true,
+ 6815 => true,
+ 6830 => true,
+ 6831 => true,
+ 6988 => true,
+ 6989 => true,
+ 6990 => true,
+ 6991 => true,
+ 7037 => true,
+ 7038 => true,
+ 7039 => true,
+ 7156 => true,
+ 7157 => true,
+ 7158 => true,
+ 7159 => true,
+ 7160 => true,
+ 7161 => true,
+ 7162 => true,
+ 7163 => true,
+ 7224 => true,
+ 7225 => true,
+ 7226 => true,
+ 7242 => true,
+ 7243 => true,
+ 7244 => true,
+ 7305 => true,
+ 7306 => true,
+ 7307 => true,
+ 7308 => true,
+ 7309 => true,
+ 7310 => true,
+ 7311 => true,
+ 7355 => true,
+ 7356 => true,
+ 7368 => true,
+ 7369 => true,
+ 7370 => true,
+ 7371 => true,
+ 7372 => true,
+ 7373 => true,
+ 7374 => true,
+ 7375 => true,
+ 7419 => true,
+ 7420 => true,
+ 7421 => true,
+ 7422 => true,
+ 7423 => true,
+ 7674 => true,
+ 7958 => true,
+ 7959 => true,
+ 7966 => true,
+ 7967 => true,
+ 8006 => true,
+ 8007 => true,
+ 8014 => true,
+ 8015 => true,
+ 8024 => true,
+ 8026 => true,
+ 8028 => true,
+ 8030 => true,
+ 8062 => true,
+ 8063 => true,
+ 8117 => true,
+ 8133 => true,
+ 8148 => true,
+ 8149 => true,
+ 8156 => true,
+ 8176 => true,
+ 8177 => true,
+ 8181 => true,
+ 8191 => true,
+ 8206 => true,
+ 8207 => true,
+ 8228 => true,
+ 8229 => true,
+ 8230 => true,
+ 8232 => true,
+ 8233 => true,
+ 8234 => true,
+ 8235 => true,
+ 8236 => true,
+ 8237 => true,
+ 8238 => true,
+ 8289 => true,
+ 8290 => true,
+ 8291 => true,
+ 8293 => true,
+ 8294 => true,
+ 8295 => true,
+ 8296 => true,
+ 8297 => true,
+ 8298 => true,
+ 8299 => true,
+ 8300 => true,
+ 8301 => true,
+ 8302 => true,
+ 8303 => true,
+ 8306 => true,
+ 8307 => true,
+ 8335 => true,
+ 8349 => true,
+ 8350 => true,
+ 8351 => true,
+ 8384 => true,
+ 8385 => true,
+ 8386 => true,
+ 8387 => true,
+ 8388 => true,
+ 8389 => true,
+ 8390 => true,
+ 8391 => true,
+ 8392 => true,
+ 8393 => true,
+ 8394 => true,
+ 8395 => true,
+ 8396 => true,
+ 8397 => true,
+ 8398 => true,
+ 8399 => true,
+ 8433 => true,
+ 8434 => true,
+ 8435 => true,
+ 8436 => true,
+ 8437 => true,
+ 8438 => true,
+ 8439 => true,
+ 8440 => true,
+ 8441 => true,
+ 8442 => true,
+ 8443 => true,
+ 8444 => true,
+ 8445 => true,
+ 8446 => true,
+ 8447 => true,
+ 8498 => true,
+ 8579 => true,
+ 8588 => true,
+ 8589 => true,
+ 8590 => true,
+ 8591 => true,
+ 9255 => true,
+ 9256 => true,
+ 9257 => true,
+ 9258 => true,
+ 9259 => true,
+ 9260 => true,
+ 9261 => true,
+ 9262 => true,
+ 9263 => true,
+ 9264 => true,
+ 9265 => true,
+ 9266 => true,
+ 9267 => true,
+ 9268 => true,
+ 9269 => true,
+ 9270 => true,
+ 9271 => true,
+ 9272 => true,
+ 9273 => true,
+ 9274 => true,
+ 9275 => true,
+ 9276 => true,
+ 9277 => true,
+ 9278 => true,
+ 9279 => true,
+ 9291 => true,
+ 9292 => true,
+ 9293 => true,
+ 9294 => true,
+ 9295 => true,
+ 9296 => true,
+ 9297 => true,
+ 9298 => true,
+ 9299 => true,
+ 9300 => true,
+ 9301 => true,
+ 9302 => true,
+ 9303 => true,
+ 9304 => true,
+ 9305 => true,
+ 9306 => true,
+ 9307 => true,
+ 9308 => true,
+ 9309 => true,
+ 9310 => true,
+ 9311 => true,
+ 9352 => true,
+ 9353 => true,
+ 9354 => true,
+ 9355 => true,
+ 9356 => true,
+ 9357 => true,
+ 9358 => true,
+ 9359 => true,
+ 9360 => true,
+ 9361 => true,
+ 9362 => true,
+ 9363 => true,
+ 9364 => true,
+ 9365 => true,
+ 9366 => true,
+ 9367 => true,
+ 9368 => true,
+ 9369 => true,
+ 9370 => true,
+ 9371 => true,
+ 11124 => true,
+ 11125 => true,
+ 11158 => true,
+ 11311 => true,
+ 11359 => true,
+ 11508 => true,
+ 11509 => true,
+ 11510 => true,
+ 11511 => true,
+ 11512 => true,
+ 11558 => true,
+ 11560 => true,
+ 11561 => true,
+ 11562 => true,
+ 11563 => true,
+ 11564 => true,
+ 11566 => true,
+ 11567 => true,
+ 11624 => true,
+ 11625 => true,
+ 11626 => true,
+ 11627 => true,
+ 11628 => true,
+ 11629 => true,
+ 11630 => true,
+ 11633 => true,
+ 11634 => true,
+ 11635 => true,
+ 11636 => true,
+ 11637 => true,
+ 11638 => true,
+ 11639 => true,
+ 11640 => true,
+ 11641 => true,
+ 11642 => true,
+ 11643 => true,
+ 11644 => true,
+ 11645 => true,
+ 11646 => true,
+ 11671 => true,
+ 11672 => true,
+ 11673 => true,
+ 11674 => true,
+ 11675 => true,
+ 11676 => true,
+ 11677 => true,
+ 11678 => true,
+ 11679 => true,
+ 11687 => true,
+ 11695 => true,
+ 11703 => true,
+ 11711 => true,
+ 11719 => true,
+ 11727 => true,
+ 11735 => true,
+ 11743 => true,
+ 11930 => true,
+ 12020 => true,
+ 12021 => true,
+ 12022 => true,
+ 12023 => true,
+ 12024 => true,
+ 12025 => true,
+ 12026 => true,
+ 12027 => true,
+ 12028 => true,
+ 12029 => true,
+ 12030 => true,
+ 12031 => true,
+ 12246 => true,
+ 12247 => true,
+ 12248 => true,
+ 12249 => true,
+ 12250 => true,
+ 12251 => true,
+ 12252 => true,
+ 12253 => true,
+ 12254 => true,
+ 12255 => true,
+ 12256 => true,
+ 12257 => true,
+ 12258 => true,
+ 12259 => true,
+ 12260 => true,
+ 12261 => true,
+ 12262 => true,
+ 12263 => true,
+ 12264 => true,
+ 12265 => true,
+ 12266 => true,
+ 12267 => true,
+ 12268 => true,
+ 12269 => true,
+ 12270 => true,
+ 12271 => true,
+ 12272 => true,
+ 12273 => true,
+ 12274 => true,
+ 12275 => true,
+ 12276 => true,
+ 12277 => true,
+ 12278 => true,
+ 12279 => true,
+ 12280 => true,
+ 12281 => true,
+ 12282 => true,
+ 12283 => true,
+ 12284 => true,
+ 12285 => true,
+ 12286 => true,
+ 12287 => true,
+ 12352 => true,
+ 12439 => true,
+ 12440 => true,
+ 12544 => true,
+ 12545 => true,
+ 12546 => true,
+ 12547 => true,
+ 12548 => true,
+ 12592 => true,
+ 12644 => true,
+ 12687 => true,
+ 12772 => true,
+ 12773 => true,
+ 12774 => true,
+ 12775 => true,
+ 12776 => true,
+ 12777 => true,
+ 12778 => true,
+ 12779 => true,
+ 12780 => true,
+ 12781 => true,
+ 12782 => true,
+ 12783 => true,
+ 12831 => true,
+ 13250 => true,
+ 13255 => true,
+ 13272 => true,
+ 40957 => true,
+ 40958 => true,
+ 40959 => true,
+ 42125 => true,
+ 42126 => true,
+ 42127 => true,
+ 42183 => true,
+ 42184 => true,
+ 42185 => true,
+ 42186 => true,
+ 42187 => true,
+ 42188 => true,
+ 42189 => true,
+ 42190 => true,
+ 42191 => true,
+ 42540 => true,
+ 42541 => true,
+ 42542 => true,
+ 42543 => true,
+ 42544 => true,
+ 42545 => true,
+ 42546 => true,
+ 42547 => true,
+ 42548 => true,
+ 42549 => true,
+ 42550 => true,
+ 42551 => true,
+ 42552 => true,
+ 42553 => true,
+ 42554 => true,
+ 42555 => true,
+ 42556 => true,
+ 42557 => true,
+ 42558 => true,
+ 42559 => true,
+ 42744 => true,
+ 42745 => true,
+ 42746 => true,
+ 42747 => true,
+ 42748 => true,
+ 42749 => true,
+ 42750 => true,
+ 42751 => true,
+ 42944 => true,
+ 42945 => true,
+ 43053 => true,
+ 43054 => true,
+ 43055 => true,
+ 43066 => true,
+ 43067 => true,
+ 43068 => true,
+ 43069 => true,
+ 43070 => true,
+ 43071 => true,
+ 43128 => true,
+ 43129 => true,
+ 43130 => true,
+ 43131 => true,
+ 43132 => true,
+ 43133 => true,
+ 43134 => true,
+ 43135 => true,
+ 43206 => true,
+ 43207 => true,
+ 43208 => true,
+ 43209 => true,
+ 43210 => true,
+ 43211 => true,
+ 43212 => true,
+ 43213 => true,
+ 43226 => true,
+ 43227 => true,
+ 43228 => true,
+ 43229 => true,
+ 43230 => true,
+ 43231 => true,
+ 43348 => true,
+ 43349 => true,
+ 43350 => true,
+ 43351 => true,
+ 43352 => true,
+ 43353 => true,
+ 43354 => true,
+ 43355 => true,
+ 43356 => true,
+ 43357 => true,
+ 43358 => true,
+ 43389 => true,
+ 43390 => true,
+ 43391 => true,
+ 43470 => true,
+ 43482 => true,
+ 43483 => true,
+ 43484 => true,
+ 43485 => true,
+ 43519 => true,
+ 43575 => true,
+ 43576 => true,
+ 43577 => true,
+ 43578 => true,
+ 43579 => true,
+ 43580 => true,
+ 43581 => true,
+ 43582 => true,
+ 43583 => true,
+ 43598 => true,
+ 43599 => true,
+ 43610 => true,
+ 43611 => true,
+ 43715 => true,
+ 43716 => true,
+ 43717 => true,
+ 43718 => true,
+ 43719 => true,
+ 43720 => true,
+ 43721 => true,
+ 43722 => true,
+ 43723 => true,
+ 43724 => true,
+ 43725 => true,
+ 43726 => true,
+ 43727 => true,
+ 43728 => true,
+ 43729 => true,
+ 43730 => true,
+ 43731 => true,
+ 43732 => true,
+ 43733 => true,
+ 43734 => true,
+ 43735 => true,
+ 43736 => true,
+ 43737 => true,
+ 43738 => true,
+ 43767 => true,
+ 43768 => true,
+ 43769 => true,
+ 43770 => true,
+ 43771 => true,
+ 43772 => true,
+ 43773 => true,
+ 43774 => true,
+ 43775 => true,
+ 43776 => true,
+ 43783 => true,
+ 43784 => true,
+ 43791 => true,
+ 43792 => true,
+ 43799 => true,
+ 43800 => true,
+ 43801 => true,
+ 43802 => true,
+ 43803 => true,
+ 43804 => true,
+ 43805 => true,
+ 43806 => true,
+ 43807 => true,
+ 43815 => true,
+ 43823 => true,
+ 43884 => true,
+ 43885 => true,
+ 43886 => true,
+ 43887 => true,
+ 44014 => true,
+ 44015 => true,
+ 44026 => true,
+ 44027 => true,
+ 44028 => true,
+ 44029 => true,
+ 44030 => true,
+ 44031 => true,
+ 55204 => true,
+ 55205 => true,
+ 55206 => true,
+ 55207 => true,
+ 55208 => true,
+ 55209 => true,
+ 55210 => true,
+ 55211 => true,
+ 55212 => true,
+ 55213 => true,
+ 55214 => true,
+ 55215 => true,
+ 55239 => true,
+ 55240 => true,
+ 55241 => true,
+ 55242 => true,
+ 55292 => true,
+ 55293 => true,
+ 55294 => true,
+ 55295 => true,
+ 64110 => true,
+ 64111 => true,
+ 64263 => true,
+ 64264 => true,
+ 64265 => true,
+ 64266 => true,
+ 64267 => true,
+ 64268 => true,
+ 64269 => true,
+ 64270 => true,
+ 64271 => true,
+ 64272 => true,
+ 64273 => true,
+ 64274 => true,
+ 64280 => true,
+ 64281 => true,
+ 64282 => true,
+ 64283 => true,
+ 64284 => true,
+ 64311 => true,
+ 64317 => true,
+ 64319 => true,
+ 64322 => true,
+ 64325 => true,
+ 64450 => true,
+ 64451 => true,
+ 64452 => true,
+ 64453 => true,
+ 64454 => true,
+ 64455 => true,
+ 64456 => true,
+ 64457 => true,
+ 64458 => true,
+ 64459 => true,
+ 64460 => true,
+ 64461 => true,
+ 64462 => true,
+ 64463 => true,
+ 64464 => true,
+ 64465 => true,
+ 64466 => true,
+ 64832 => true,
+ 64833 => true,
+ 64834 => true,
+ 64835 => true,
+ 64836 => true,
+ 64837 => true,
+ 64838 => true,
+ 64839 => true,
+ 64840 => true,
+ 64841 => true,
+ 64842 => true,
+ 64843 => true,
+ 64844 => true,
+ 64845 => true,
+ 64846 => true,
+ 64847 => true,
+ 64912 => true,
+ 64913 => true,
+ 64968 => true,
+ 64969 => true,
+ 64970 => true,
+ 64971 => true,
+ 64972 => true,
+ 64973 => true,
+ 64974 => true,
+ 64975 => true,
+ 65022 => true,
+ 65023 => true,
+ 65042 => true,
+ 65049 => true,
+ 65050 => true,
+ 65051 => true,
+ 65052 => true,
+ 65053 => true,
+ 65054 => true,
+ 65055 => true,
+ 65072 => true,
+ 65106 => true,
+ 65107 => true,
+ 65127 => true,
+ 65132 => true,
+ 65133 => true,
+ 65134 => true,
+ 65135 => true,
+ 65141 => true,
+ 65277 => true,
+ 65278 => true,
+ 65280 => true,
+ 65440 => true,
+ 65471 => true,
+ 65472 => true,
+ 65473 => true,
+ 65480 => true,
+ 65481 => true,
+ 65488 => true,
+ 65489 => true,
+ 65496 => true,
+ 65497 => true,
+ 65501 => true,
+ 65502 => true,
+ 65503 => true,
+ 65511 => true,
+ 65519 => true,
+ 65520 => true,
+ 65521 => true,
+ 65522 => true,
+ 65523 => true,
+ 65524 => true,
+ 65525 => true,
+ 65526 => true,
+ 65527 => true,
+ 65528 => true,
+ 65529 => true,
+ 65530 => true,
+ 65531 => true,
+ 65532 => true,
+ 65533 => true,
+ 65534 => true,
+ 65535 => true,
+ 65548 => true,
+ 65575 => true,
+ 65595 => true,
+ 65598 => true,
+ 65614 => true,
+ 65615 => true,
+ 65787 => true,
+ 65788 => true,
+ 65789 => true,
+ 65790 => true,
+ 65791 => true,
+ 65795 => true,
+ 65796 => true,
+ 65797 => true,
+ 65798 => true,
+ 65844 => true,
+ 65845 => true,
+ 65846 => true,
+ 65935 => true,
+ 65949 => true,
+ 65950 => true,
+ 65951 => true,
+ 66205 => true,
+ 66206 => true,
+ 66207 => true,
+ 66257 => true,
+ 66258 => true,
+ 66259 => true,
+ 66260 => true,
+ 66261 => true,
+ 66262 => true,
+ 66263 => true,
+ 66264 => true,
+ 66265 => true,
+ 66266 => true,
+ 66267 => true,
+ 66268 => true,
+ 66269 => true,
+ 66270 => true,
+ 66271 => true,
+ 66300 => true,
+ 66301 => true,
+ 66302 => true,
+ 66303 => true,
+ 66340 => true,
+ 66341 => true,
+ 66342 => true,
+ 66343 => true,
+ 66344 => true,
+ 66345 => true,
+ 66346 => true,
+ 66347 => true,
+ 66348 => true,
+ 66379 => true,
+ 66380 => true,
+ 66381 => true,
+ 66382 => true,
+ 66383 => true,
+ 66427 => true,
+ 66428 => true,
+ 66429 => true,
+ 66430 => true,
+ 66431 => true,
+ 66462 => true,
+ 66500 => true,
+ 66501 => true,
+ 66502 => true,
+ 66503 => true,
+ 66718 => true,
+ 66719 => true,
+ 66730 => true,
+ 66731 => true,
+ 66732 => true,
+ 66733 => true,
+ 66734 => true,
+ 66735 => true,
+ 66772 => true,
+ 66773 => true,
+ 66774 => true,
+ 66775 => true,
+ 66812 => true,
+ 66813 => true,
+ 66814 => true,
+ 66815 => true,
+ 66856 => true,
+ 66857 => true,
+ 66858 => true,
+ 66859 => true,
+ 66860 => true,
+ 66861 => true,
+ 66862 => true,
+ 66863 => true,
+ 66916 => true,
+ 66917 => true,
+ 66918 => true,
+ 66919 => true,
+ 66920 => true,
+ 66921 => true,
+ 66922 => true,
+ 66923 => true,
+ 66924 => true,
+ 66925 => true,
+ 66926 => true,
+ 67383 => true,
+ 67384 => true,
+ 67385 => true,
+ 67386 => true,
+ 67387 => true,
+ 67388 => true,
+ 67389 => true,
+ 67390 => true,
+ 67391 => true,
+ 67414 => true,
+ 67415 => true,
+ 67416 => true,
+ 67417 => true,
+ 67418 => true,
+ 67419 => true,
+ 67420 => true,
+ 67421 => true,
+ 67422 => true,
+ 67423 => true,
+ 67590 => true,
+ 67591 => true,
+ 67593 => true,
+ 67638 => true,
+ 67641 => true,
+ 67642 => true,
+ 67643 => true,
+ 67645 => true,
+ 67646 => true,
+ 67670 => true,
+ 67743 => true,
+ 67744 => true,
+ 67745 => true,
+ 67746 => true,
+ 67747 => true,
+ 67748 => true,
+ 67749 => true,
+ 67750 => true,
+ 67827 => true,
+ 67830 => true,
+ 67831 => true,
+ 67832 => true,
+ 67833 => true,
+ 67834 => true,
+ 67868 => true,
+ 67869 => true,
+ 67870 => true,
+ 67898 => true,
+ 67899 => true,
+ 67900 => true,
+ 67901 => true,
+ 67902 => true,
+ 68024 => true,
+ 68025 => true,
+ 68026 => true,
+ 68027 => true,
+ 68048 => true,
+ 68049 => true,
+ 68100 => true,
+ 68103 => true,
+ 68104 => true,
+ 68105 => true,
+ 68106 => true,
+ 68107 => true,
+ 68116 => true,
+ 68120 => true,
+ 68150 => true,
+ 68151 => true,
+ 68155 => true,
+ 68156 => true,
+ 68157 => true,
+ 68158 => true,
+ 68169 => true,
+ 68170 => true,
+ 68171 => true,
+ 68172 => true,
+ 68173 => true,
+ 68174 => true,
+ 68175 => true,
+ 68185 => true,
+ 68186 => true,
+ 68187 => true,
+ 68188 => true,
+ 68189 => true,
+ 68190 => true,
+ 68191 => true,
+ 68327 => true,
+ 68328 => true,
+ 68329 => true,
+ 68330 => true,
+ 68343 => true,
+ 68344 => true,
+ 68345 => true,
+ 68346 => true,
+ 68347 => true,
+ 68348 => true,
+ 68349 => true,
+ 68350 => true,
+ 68351 => true,
+ 68406 => true,
+ 68407 => true,
+ 68408 => true,
+ 68438 => true,
+ 68439 => true,
+ 68467 => true,
+ 68468 => true,
+ 68469 => true,
+ 68470 => true,
+ 68471 => true,
+ 68498 => true,
+ 68499 => true,
+ 68500 => true,
+ 68501 => true,
+ 68502 => true,
+ 68503 => true,
+ 68504 => true,
+ 68509 => true,
+ 68510 => true,
+ 68511 => true,
+ 68512 => true,
+ 68513 => true,
+ 68514 => true,
+ 68515 => true,
+ 68516 => true,
+ 68517 => true,
+ 68518 => true,
+ 68519 => true,
+ 68520 => true,
+ 68787 => true,
+ 68788 => true,
+ 68789 => true,
+ 68790 => true,
+ 68791 => true,
+ 68792 => true,
+ 68793 => true,
+ 68794 => true,
+ 68795 => true,
+ 68796 => true,
+ 68797 => true,
+ 68798 => true,
+ 68799 => true,
+ 68851 => true,
+ 68852 => true,
+ 68853 => true,
+ 68854 => true,
+ 68855 => true,
+ 68856 => true,
+ 68857 => true,
+ 68904 => true,
+ 68905 => true,
+ 68906 => true,
+ 68907 => true,
+ 68908 => true,
+ 68909 => true,
+ 68910 => true,
+ 68911 => true,
+ 69247 => true,
+ 69290 => true,
+ 69294 => true,
+ 69295 => true,
+ 69416 => true,
+ 69417 => true,
+ 69418 => true,
+ 69419 => true,
+ 69420 => true,
+ 69421 => true,
+ 69422 => true,
+ 69423 => true,
+ 69580 => true,
+ 69581 => true,
+ 69582 => true,
+ 69583 => true,
+ 69584 => true,
+ 69585 => true,
+ 69586 => true,
+ 69587 => true,
+ 69588 => true,
+ 69589 => true,
+ 69590 => true,
+ 69591 => true,
+ 69592 => true,
+ 69593 => true,
+ 69594 => true,
+ 69595 => true,
+ 69596 => true,
+ 69597 => true,
+ 69598 => true,
+ 69599 => true,
+ 69623 => true,
+ 69624 => true,
+ 69625 => true,
+ 69626 => true,
+ 69627 => true,
+ 69628 => true,
+ 69629 => true,
+ 69630 => true,
+ 69631 => true,
+ 69710 => true,
+ 69711 => true,
+ 69712 => true,
+ 69713 => true,
+ 69744 => true,
+ 69745 => true,
+ 69746 => true,
+ 69747 => true,
+ 69748 => true,
+ 69749 => true,
+ 69750 => true,
+ 69751 => true,
+ 69752 => true,
+ 69753 => true,
+ 69754 => true,
+ 69755 => true,
+ 69756 => true,
+ 69757 => true,
+ 69758 => true,
+ 69821 => true,
+ 69826 => true,
+ 69827 => true,
+ 69828 => true,
+ 69829 => true,
+ 69830 => true,
+ 69831 => true,
+ 69832 => true,
+ 69833 => true,
+ 69834 => true,
+ 69835 => true,
+ 69836 => true,
+ 69837 => true,
+ 69838 => true,
+ 69839 => true,
+ 69865 => true,
+ 69866 => true,
+ 69867 => true,
+ 69868 => true,
+ 69869 => true,
+ 69870 => true,
+ 69871 => true,
+ 69882 => true,
+ 69883 => true,
+ 69884 => true,
+ 69885 => true,
+ 69886 => true,
+ 69887 => true,
+ 69941 => true,
+ 69960 => true,
+ 69961 => true,
+ 69962 => true,
+ 69963 => true,
+ 69964 => true,
+ 69965 => true,
+ 69966 => true,
+ 69967 => true,
+ 70007 => true,
+ 70008 => true,
+ 70009 => true,
+ 70010 => true,
+ 70011 => true,
+ 70012 => true,
+ 70013 => true,
+ 70014 => true,
+ 70015 => true,
+ 70112 => true,
+ 70133 => true,
+ 70134 => true,
+ 70135 => true,
+ 70136 => true,
+ 70137 => true,
+ 70138 => true,
+ 70139 => true,
+ 70140 => true,
+ 70141 => true,
+ 70142 => true,
+ 70143 => true,
+ 70162 => true,
+ 70279 => true,
+ 70281 => true,
+ 70286 => true,
+ 70302 => true,
+ 70314 => true,
+ 70315 => true,
+ 70316 => true,
+ 70317 => true,
+ 70318 => true,
+ 70319 => true,
+ 70379 => true,
+ 70380 => true,
+ 70381 => true,
+ 70382 => true,
+ 70383 => true,
+ 70394 => true,
+ 70395 => true,
+ 70396 => true,
+ 70397 => true,
+ 70398 => true,
+ 70399 => true,
+ 70404 => true,
+ 70413 => true,
+ 70414 => true,
+ 70417 => true,
+ 70418 => true,
+ 70441 => true,
+ 70449 => true,
+ 70452 => true,
+ 70458 => true,
+ 70469 => true,
+ 70470 => true,
+ 70473 => true,
+ 70474 => true,
+ 70478 => true,
+ 70479 => true,
+ 70481 => true,
+ 70482 => true,
+ 70483 => true,
+ 70484 => true,
+ 70485 => true,
+ 70486 => true,
+ 70488 => true,
+ 70489 => true,
+ 70490 => true,
+ 70491 => true,
+ 70492 => true,
+ 70500 => true,
+ 70501 => true,
+ 70509 => true,
+ 70510 => true,
+ 70511 => true,
+ 70748 => true,
+ 70754 => true,
+ 70755 => true,
+ 70756 => true,
+ 70757 => true,
+ 70758 => true,
+ 70759 => true,
+ 70760 => true,
+ 70761 => true,
+ 70762 => true,
+ 70763 => true,
+ 70764 => true,
+ 70765 => true,
+ 70766 => true,
+ 70767 => true,
+ 70768 => true,
+ 70769 => true,
+ 70770 => true,
+ 70771 => true,
+ 70772 => true,
+ 70773 => true,
+ 70774 => true,
+ 70775 => true,
+ 70776 => true,
+ 70777 => true,
+ 70778 => true,
+ 70779 => true,
+ 70780 => true,
+ 70781 => true,
+ 70782 => true,
+ 70783 => true,
+ 70856 => true,
+ 70857 => true,
+ 70858 => true,
+ 70859 => true,
+ 70860 => true,
+ 70861 => true,
+ 70862 => true,
+ 70863 => true,
+ 71094 => true,
+ 71095 => true,
+ 71237 => true,
+ 71238 => true,
+ 71239 => true,
+ 71240 => true,
+ 71241 => true,
+ 71242 => true,
+ 71243 => true,
+ 71244 => true,
+ 71245 => true,
+ 71246 => true,
+ 71247 => true,
+ 71258 => true,
+ 71259 => true,
+ 71260 => true,
+ 71261 => true,
+ 71262 => true,
+ 71263 => true,
+ 71277 => true,
+ 71278 => true,
+ 71279 => true,
+ 71280 => true,
+ 71281 => true,
+ 71282 => true,
+ 71283 => true,
+ 71284 => true,
+ 71285 => true,
+ 71286 => true,
+ 71287 => true,
+ 71288 => true,
+ 71289 => true,
+ 71290 => true,
+ 71291 => true,
+ 71292 => true,
+ 71293 => true,
+ 71294 => true,
+ 71295 => true,
+ 71353 => true,
+ 71354 => true,
+ 71355 => true,
+ 71356 => true,
+ 71357 => true,
+ 71358 => true,
+ 71359 => true,
+ 71451 => true,
+ 71452 => true,
+ 71468 => true,
+ 71469 => true,
+ 71470 => true,
+ 71471 => true,
+ 71923 => true,
+ 71924 => true,
+ 71925 => true,
+ 71926 => true,
+ 71927 => true,
+ 71928 => true,
+ 71929 => true,
+ 71930 => true,
+ 71931 => true,
+ 71932 => true,
+ 71933 => true,
+ 71934 => true,
+ 71943 => true,
+ 71944 => true,
+ 71946 => true,
+ 71947 => true,
+ 71956 => true,
+ 71959 => true,
+ 71990 => true,
+ 71993 => true,
+ 71994 => true,
+ 72007 => true,
+ 72008 => true,
+ 72009 => true,
+ 72010 => true,
+ 72011 => true,
+ 72012 => true,
+ 72013 => true,
+ 72014 => true,
+ 72015 => true,
+ 72104 => true,
+ 72105 => true,
+ 72152 => true,
+ 72153 => true,
+ 72165 => true,
+ 72166 => true,
+ 72167 => true,
+ 72168 => true,
+ 72169 => true,
+ 72170 => true,
+ 72171 => true,
+ 72172 => true,
+ 72173 => true,
+ 72174 => true,
+ 72175 => true,
+ 72176 => true,
+ 72177 => true,
+ 72178 => true,
+ 72179 => true,
+ 72180 => true,
+ 72181 => true,
+ 72182 => true,
+ 72183 => true,
+ 72184 => true,
+ 72185 => true,
+ 72186 => true,
+ 72187 => true,
+ 72188 => true,
+ 72189 => true,
+ 72190 => true,
+ 72191 => true,
+ 72264 => true,
+ 72265 => true,
+ 72266 => true,
+ 72267 => true,
+ 72268 => true,
+ 72269 => true,
+ 72270 => true,
+ 72271 => true,
+ 72355 => true,
+ 72356 => true,
+ 72357 => true,
+ 72358 => true,
+ 72359 => true,
+ 72360 => true,
+ 72361 => true,
+ 72362 => true,
+ 72363 => true,
+ 72364 => true,
+ 72365 => true,
+ 72366 => true,
+ 72367 => true,
+ 72368 => true,
+ 72369 => true,
+ 72370 => true,
+ 72371 => true,
+ 72372 => true,
+ 72373 => true,
+ 72374 => true,
+ 72375 => true,
+ 72376 => true,
+ 72377 => true,
+ 72378 => true,
+ 72379 => true,
+ 72380 => true,
+ 72381 => true,
+ 72382 => true,
+ 72383 => true,
+ 72713 => true,
+ 72759 => true,
+ 72774 => true,
+ 72775 => true,
+ 72776 => true,
+ 72777 => true,
+ 72778 => true,
+ 72779 => true,
+ 72780 => true,
+ 72781 => true,
+ 72782 => true,
+ 72783 => true,
+ 72813 => true,
+ 72814 => true,
+ 72815 => true,
+ 72848 => true,
+ 72849 => true,
+ 72872 => true,
+ 72967 => true,
+ 72970 => true,
+ 73015 => true,
+ 73016 => true,
+ 73017 => true,
+ 73019 => true,
+ 73022 => true,
+ 73032 => true,
+ 73033 => true,
+ 73034 => true,
+ 73035 => true,
+ 73036 => true,
+ 73037 => true,
+ 73038 => true,
+ 73039 => true,
+ 73050 => true,
+ 73051 => true,
+ 73052 => true,
+ 73053 => true,
+ 73054 => true,
+ 73055 => true,
+ 73062 => true,
+ 73065 => true,
+ 73103 => true,
+ 73106 => true,
+ 73113 => true,
+ 73114 => true,
+ 73115 => true,
+ 73116 => true,
+ 73117 => true,
+ 73118 => true,
+ 73119 => true,
+ 73649 => true,
+ 73650 => true,
+ 73651 => true,
+ 73652 => true,
+ 73653 => true,
+ 73654 => true,
+ 73655 => true,
+ 73656 => true,
+ 73657 => true,
+ 73658 => true,
+ 73659 => true,
+ 73660 => true,
+ 73661 => true,
+ 73662 => true,
+ 73663 => true,
+ 73714 => true,
+ 73715 => true,
+ 73716 => true,
+ 73717 => true,
+ 73718 => true,
+ 73719 => true,
+ 73720 => true,
+ 73721 => true,
+ 73722 => true,
+ 73723 => true,
+ 73724 => true,
+ 73725 => true,
+ 73726 => true,
+ 74863 => true,
+ 74869 => true,
+ 74870 => true,
+ 74871 => true,
+ 74872 => true,
+ 74873 => true,
+ 74874 => true,
+ 74875 => true,
+ 74876 => true,
+ 74877 => true,
+ 74878 => true,
+ 74879 => true,
+ 78895 => true,
+ 78896 => true,
+ 78897 => true,
+ 78898 => true,
+ 78899 => true,
+ 78900 => true,
+ 78901 => true,
+ 78902 => true,
+ 78903 => true,
+ 78904 => true,
+ 92729 => true,
+ 92730 => true,
+ 92731 => true,
+ 92732 => true,
+ 92733 => true,
+ 92734 => true,
+ 92735 => true,
+ 92767 => true,
+ 92778 => true,
+ 92779 => true,
+ 92780 => true,
+ 92781 => true,
+ 92910 => true,
+ 92911 => true,
+ 92918 => true,
+ 92919 => true,
+ 92920 => true,
+ 92921 => true,
+ 92922 => true,
+ 92923 => true,
+ 92924 => true,
+ 92925 => true,
+ 92926 => true,
+ 92927 => true,
+ 92998 => true,
+ 92999 => true,
+ 93000 => true,
+ 93001 => true,
+ 93002 => true,
+ 93003 => true,
+ 93004 => true,
+ 93005 => true,
+ 93006 => true,
+ 93007 => true,
+ 93018 => true,
+ 93026 => true,
+ 93048 => true,
+ 93049 => true,
+ 93050 => true,
+ 93051 => true,
+ 93052 => true,
+ 94027 => true,
+ 94028 => true,
+ 94029 => true,
+ 94030 => true,
+ 94088 => true,
+ 94089 => true,
+ 94090 => true,
+ 94091 => true,
+ 94092 => true,
+ 94093 => true,
+ 94094 => true,
+ 94181 => true,
+ 94182 => true,
+ 94183 => true,
+ 94184 => true,
+ 94185 => true,
+ 94186 => true,
+ 94187 => true,
+ 94188 => true,
+ 94189 => true,
+ 94190 => true,
+ 94191 => true,
+ 94194 => true,
+ 94195 => true,
+ 94196 => true,
+ 94197 => true,
+ 94198 => true,
+ 94199 => true,
+ 94200 => true,
+ 94201 => true,
+ 94202 => true,
+ 94203 => true,
+ 94204 => true,
+ 94205 => true,
+ 94206 => true,
+ 94207 => true,
+ 100344 => true,
+ 100345 => true,
+ 100346 => true,
+ 100347 => true,
+ 100348 => true,
+ 100349 => true,
+ 100350 => true,
+ 100351 => true,
+ 110931 => true,
+ 110932 => true,
+ 110933 => true,
+ 110934 => true,
+ 110935 => true,
+ 110936 => true,
+ 110937 => true,
+ 110938 => true,
+ 110939 => true,
+ 110940 => true,
+ 110941 => true,
+ 110942 => true,
+ 110943 => true,
+ 110944 => true,
+ 110945 => true,
+ 110946 => true,
+ 110947 => true,
+ 110952 => true,
+ 110953 => true,
+ 110954 => true,
+ 110955 => true,
+ 110956 => true,
+ 110957 => true,
+ 110958 => true,
+ 110959 => true,
+ 113771 => true,
+ 113772 => true,
+ 113773 => true,
+ 113774 => true,
+ 113775 => true,
+ 113789 => true,
+ 113790 => true,
+ 113791 => true,
+ 113801 => true,
+ 113802 => true,
+ 113803 => true,
+ 113804 => true,
+ 113805 => true,
+ 113806 => true,
+ 113807 => true,
+ 113818 => true,
+ 113819 => true,
+ 119030 => true,
+ 119031 => true,
+ 119032 => true,
+ 119033 => true,
+ 119034 => true,
+ 119035 => true,
+ 119036 => true,
+ 119037 => true,
+ 119038 => true,
+ 119039 => true,
+ 119079 => true,
+ 119080 => true,
+ 119155 => true,
+ 119156 => true,
+ 119157 => true,
+ 119158 => true,
+ 119159 => true,
+ 119160 => true,
+ 119161 => true,
+ 119162 => true,
+ 119273 => true,
+ 119274 => true,
+ 119275 => true,
+ 119276 => true,
+ 119277 => true,
+ 119278 => true,
+ 119279 => true,
+ 119280 => true,
+ 119281 => true,
+ 119282 => true,
+ 119283 => true,
+ 119284 => true,
+ 119285 => true,
+ 119286 => true,
+ 119287 => true,
+ 119288 => true,
+ 119289 => true,
+ 119290 => true,
+ 119291 => true,
+ 119292 => true,
+ 119293 => true,
+ 119294 => true,
+ 119295 => true,
+ 119540 => true,
+ 119541 => true,
+ 119542 => true,
+ 119543 => true,
+ 119544 => true,
+ 119545 => true,
+ 119546 => true,
+ 119547 => true,
+ 119548 => true,
+ 119549 => true,
+ 119550 => true,
+ 119551 => true,
+ 119639 => true,
+ 119640 => true,
+ 119641 => true,
+ 119642 => true,
+ 119643 => true,
+ 119644 => true,
+ 119645 => true,
+ 119646 => true,
+ 119647 => true,
+ 119893 => true,
+ 119965 => true,
+ 119968 => true,
+ 119969 => true,
+ 119971 => true,
+ 119972 => true,
+ 119975 => true,
+ 119976 => true,
+ 119981 => true,
+ 119994 => true,
+ 119996 => true,
+ 120004 => true,
+ 120070 => true,
+ 120075 => true,
+ 120076 => true,
+ 120085 => true,
+ 120093 => true,
+ 120122 => true,
+ 120127 => true,
+ 120133 => true,
+ 120135 => true,
+ 120136 => true,
+ 120137 => true,
+ 120145 => true,
+ 120486 => true,
+ 120487 => true,
+ 120780 => true,
+ 120781 => true,
+ 121484 => true,
+ 121485 => true,
+ 121486 => true,
+ 121487 => true,
+ 121488 => true,
+ 121489 => true,
+ 121490 => true,
+ 121491 => true,
+ 121492 => true,
+ 121493 => true,
+ 121494 => true,
+ 121495 => true,
+ 121496 => true,
+ 121497 => true,
+ 121498 => true,
+ 121504 => true,
+ 122887 => true,
+ 122905 => true,
+ 122906 => true,
+ 122914 => true,
+ 122917 => true,
+ 123181 => true,
+ 123182 => true,
+ 123183 => true,
+ 123198 => true,
+ 123199 => true,
+ 123210 => true,
+ 123211 => true,
+ 123212 => true,
+ 123213 => true,
+ 123642 => true,
+ 123643 => true,
+ 123644 => true,
+ 123645 => true,
+ 123646 => true,
+ 125125 => true,
+ 125126 => true,
+ 125260 => true,
+ 125261 => true,
+ 125262 => true,
+ 125263 => true,
+ 125274 => true,
+ 125275 => true,
+ 125276 => true,
+ 125277 => true,
+ 126468 => true,
+ 126496 => true,
+ 126499 => true,
+ 126501 => true,
+ 126502 => true,
+ 126504 => true,
+ 126515 => true,
+ 126520 => true,
+ 126522 => true,
+ 126524 => true,
+ 126525 => true,
+ 126526 => true,
+ 126527 => true,
+ 126528 => true,
+ 126529 => true,
+ 126531 => true,
+ 126532 => true,
+ 126533 => true,
+ 126534 => true,
+ 126536 => true,
+ 126538 => true,
+ 126540 => true,
+ 126544 => true,
+ 126547 => true,
+ 126549 => true,
+ 126550 => true,
+ 126552 => true,
+ 126554 => true,
+ 126556 => true,
+ 126558 => true,
+ 126560 => true,
+ 126563 => true,
+ 126565 => true,
+ 126566 => true,
+ 126571 => true,
+ 126579 => true,
+ 126584 => true,
+ 126589 => true,
+ 126591 => true,
+ 126602 => true,
+ 126620 => true,
+ 126621 => true,
+ 126622 => true,
+ 126623 => true,
+ 126624 => true,
+ 126628 => true,
+ 126634 => true,
+ 127020 => true,
+ 127021 => true,
+ 127022 => true,
+ 127023 => true,
+ 127124 => true,
+ 127125 => true,
+ 127126 => true,
+ 127127 => true,
+ 127128 => true,
+ 127129 => true,
+ 127130 => true,
+ 127131 => true,
+ 127132 => true,
+ 127133 => true,
+ 127134 => true,
+ 127135 => true,
+ 127151 => true,
+ 127152 => true,
+ 127168 => true,
+ 127184 => true,
+ 127222 => true,
+ 127223 => true,
+ 127224 => true,
+ 127225 => true,
+ 127226 => true,
+ 127227 => true,
+ 127228 => true,
+ 127229 => true,
+ 127230 => true,
+ 127231 => true,
+ 127232 => true,
+ 127491 => true,
+ 127492 => true,
+ 127493 => true,
+ 127494 => true,
+ 127495 => true,
+ 127496 => true,
+ 127497 => true,
+ 127498 => true,
+ 127499 => true,
+ 127500 => true,
+ 127501 => true,
+ 127502 => true,
+ 127503 => true,
+ 127548 => true,
+ 127549 => true,
+ 127550 => true,
+ 127551 => true,
+ 127561 => true,
+ 127562 => true,
+ 127563 => true,
+ 127564 => true,
+ 127565 => true,
+ 127566 => true,
+ 127567 => true,
+ 127570 => true,
+ 127571 => true,
+ 127572 => true,
+ 127573 => true,
+ 127574 => true,
+ 127575 => true,
+ 127576 => true,
+ 127577 => true,
+ 127578 => true,
+ 127579 => true,
+ 127580 => true,
+ 127581 => true,
+ 127582 => true,
+ 127583 => true,
+ 128728 => true,
+ 128729 => true,
+ 128730 => true,
+ 128731 => true,
+ 128732 => true,
+ 128733 => true,
+ 128734 => true,
+ 128735 => true,
+ 128749 => true,
+ 128750 => true,
+ 128751 => true,
+ 128765 => true,
+ 128766 => true,
+ 128767 => true,
+ 128884 => true,
+ 128885 => true,
+ 128886 => true,
+ 128887 => true,
+ 128888 => true,
+ 128889 => true,
+ 128890 => true,
+ 128891 => true,
+ 128892 => true,
+ 128893 => true,
+ 128894 => true,
+ 128895 => true,
+ 128985 => true,
+ 128986 => true,
+ 128987 => true,
+ 128988 => true,
+ 128989 => true,
+ 128990 => true,
+ 128991 => true,
+ 129004 => true,
+ 129005 => true,
+ 129006 => true,
+ 129007 => true,
+ 129008 => true,
+ 129009 => true,
+ 129010 => true,
+ 129011 => true,
+ 129012 => true,
+ 129013 => true,
+ 129014 => true,
+ 129015 => true,
+ 129016 => true,
+ 129017 => true,
+ 129018 => true,
+ 129019 => true,
+ 129020 => true,
+ 129021 => true,
+ 129022 => true,
+ 129023 => true,
+ 129036 => true,
+ 129037 => true,
+ 129038 => true,
+ 129039 => true,
+ 129096 => true,
+ 129097 => true,
+ 129098 => true,
+ 129099 => true,
+ 129100 => true,
+ 129101 => true,
+ 129102 => true,
+ 129103 => true,
+ 129114 => true,
+ 129115 => true,
+ 129116 => true,
+ 129117 => true,
+ 129118 => true,
+ 129119 => true,
+ 129160 => true,
+ 129161 => true,
+ 129162 => true,
+ 129163 => true,
+ 129164 => true,
+ 129165 => true,
+ 129166 => true,
+ 129167 => true,
+ 129198 => true,
+ 129199 => true,
+ 129401 => true,
+ 129484 => true,
+ 129620 => true,
+ 129621 => true,
+ 129622 => true,
+ 129623 => true,
+ 129624 => true,
+ 129625 => true,
+ 129626 => true,
+ 129627 => true,
+ 129628 => true,
+ 129629 => true,
+ 129630 => true,
+ 129631 => true,
+ 129646 => true,
+ 129647 => true,
+ 129653 => true,
+ 129654 => true,
+ 129655 => true,
+ 129659 => true,
+ 129660 => true,
+ 129661 => true,
+ 129662 => true,
+ 129663 => true,
+ 129671 => true,
+ 129672 => true,
+ 129673 => true,
+ 129674 => true,
+ 129675 => true,
+ 129676 => true,
+ 129677 => true,
+ 129678 => true,
+ 129679 => true,
+ 129705 => true,
+ 129706 => true,
+ 129707 => true,
+ 129708 => true,
+ 129709 => true,
+ 129710 => true,
+ 129711 => true,
+ 129719 => true,
+ 129720 => true,
+ 129721 => true,
+ 129722 => true,
+ 129723 => true,
+ 129724 => true,
+ 129725 => true,
+ 129726 => true,
+ 129727 => true,
+ 129731 => true,
+ 129732 => true,
+ 129733 => true,
+ 129734 => true,
+ 129735 => true,
+ 129736 => true,
+ 129737 => true,
+ 129738 => true,
+ 129739 => true,
+ 129740 => true,
+ 129741 => true,
+ 129742 => true,
+ 129743 => true,
+ 129939 => true,
+ 131070 => true,
+ 131071 => true,
+ 177973 => true,
+ 177974 => true,
+ 177975 => true,
+ 177976 => true,
+ 177977 => true,
+ 177978 => true,
+ 177979 => true,
+ 177980 => true,
+ 177981 => true,
+ 177982 => true,
+ 177983 => true,
+ 178206 => true,
+ 178207 => true,
+ 183970 => true,
+ 183971 => true,
+ 183972 => true,
+ 183973 => true,
+ 183974 => true,
+ 183975 => true,
+ 183976 => true,
+ 183977 => true,
+ 183978 => true,
+ 183979 => true,
+ 183980 => true,
+ 183981 => true,
+ 183982 => true,
+ 183983 => true,
+ 194664 => true,
+ 194676 => true,
+ 194847 => true,
+ 194911 => true,
+ 195007 => true,
+ 196606 => true,
+ 196607 => true,
+ 262142 => true,
+ 262143 => true,
+ 327678 => true,
+ 327679 => true,
+ 393214 => true,
+ 393215 => true,
+ 458750 => true,
+ 458751 => true,
+ 524286 => true,
+ 524287 => true,
+ 589822 => true,
+ 589823 => true,
+ 655358 => true,
+ 655359 => true,
+ 720894 => true,
+ 720895 => true,
+ 786430 => true,
+ 786431 => true,
+ 851966 => true,
+ 851967 => true,
+ 917502 => true,
+ 917503 => true,
+ 917504 => true,
+ 917505 => true,
+ 917506 => true,
+ 917507 => true,
+ 917508 => true,
+ 917509 => true,
+ 917510 => true,
+ 917511 => true,
+ 917512 => true,
+ 917513 => true,
+ 917514 => true,
+ 917515 => true,
+ 917516 => true,
+ 917517 => true,
+ 917518 => true,
+ 917519 => true,
+ 917520 => true,
+ 917521 => true,
+ 917522 => true,
+ 917523 => true,
+ 917524 => true,
+ 917525 => true,
+ 917526 => true,
+ 917527 => true,
+ 917528 => true,
+ 917529 => true,
+ 917530 => true,
+ 917531 => true,
+ 917532 => true,
+ 917533 => true,
+ 917534 => true,
+ 917535 => true,
+ 983038 => true,
+ 983039 => true,
+ 1048574 => true,
+ 1048575 => true,
+ 1114110 => true,
+ 1114111 => true,
+);
diff --git a/vendor/symfony/polyfill-intl-idn/Resources/unidata/disallowed_STD3_mapped.php b/vendor/symfony/polyfill-intl-idn/Resources/unidata/disallowed_STD3_mapped.php
new file mode 100644
index 0000000..54f21cc
--- /dev/null
+++ b/vendor/symfony/polyfill-intl-idn/Resources/unidata/disallowed_STD3_mapped.php
@@ -0,0 +1,308 @@
+ ' ',
+ 168 => ' ̈',
+ 175 => ' ̄',
+ 180 => ' ́',
+ 184 => ' ̧',
+ 728 => ' ̆',
+ 729 => ' ̇',
+ 730 => ' ̊',
+ 731 => ' ̨',
+ 732 => ' ̃',
+ 733 => ' ̋',
+ 890 => ' ι',
+ 894 => ';',
+ 900 => ' ́',
+ 901 => ' ̈́',
+ 8125 => ' ̓',
+ 8127 => ' ̓',
+ 8128 => ' ͂',
+ 8129 => ' ̈͂',
+ 8141 => ' ̓̀',
+ 8142 => ' ̓́',
+ 8143 => ' ̓͂',
+ 8157 => ' ̔̀',
+ 8158 => ' ̔́',
+ 8159 => ' ̔͂',
+ 8173 => ' ̈̀',
+ 8174 => ' ̈́',
+ 8175 => '`',
+ 8189 => ' ́',
+ 8190 => ' ̔',
+ 8192 => ' ',
+ 8193 => ' ',
+ 8194 => ' ',
+ 8195 => ' ',
+ 8196 => ' ',
+ 8197 => ' ',
+ 8198 => ' ',
+ 8199 => ' ',
+ 8200 => ' ',
+ 8201 => ' ',
+ 8202 => ' ',
+ 8215 => ' ̳',
+ 8239 => ' ',
+ 8252 => '!!',
+ 8254 => ' ̅',
+ 8263 => '??',
+ 8264 => '?!',
+ 8265 => '!?',
+ 8287 => ' ',
+ 8314 => '+',
+ 8316 => '=',
+ 8317 => '(',
+ 8318 => ')',
+ 8330 => '+',
+ 8332 => '=',
+ 8333 => '(',
+ 8334 => ')',
+ 8448 => 'a/c',
+ 8449 => 'a/s',
+ 8453 => 'c/o',
+ 8454 => 'c/u',
+ 9332 => '(1)',
+ 9333 => '(2)',
+ 9334 => '(3)',
+ 9335 => '(4)',
+ 9336 => '(5)',
+ 9337 => '(6)',
+ 9338 => '(7)',
+ 9339 => '(8)',
+ 9340 => '(9)',
+ 9341 => '(10)',
+ 9342 => '(11)',
+ 9343 => '(12)',
+ 9344 => '(13)',
+ 9345 => '(14)',
+ 9346 => '(15)',
+ 9347 => '(16)',
+ 9348 => '(17)',
+ 9349 => '(18)',
+ 9350 => '(19)',
+ 9351 => '(20)',
+ 9372 => '(a)',
+ 9373 => '(b)',
+ 9374 => '(c)',
+ 9375 => '(d)',
+ 9376 => '(e)',
+ 9377 => '(f)',
+ 9378 => '(g)',
+ 9379 => '(h)',
+ 9380 => '(i)',
+ 9381 => '(j)',
+ 9382 => '(k)',
+ 9383 => '(l)',
+ 9384 => '(m)',
+ 9385 => '(n)',
+ 9386 => '(o)',
+ 9387 => '(p)',
+ 9388 => '(q)',
+ 9389 => '(r)',
+ 9390 => '(s)',
+ 9391 => '(t)',
+ 9392 => '(u)',
+ 9393 => '(v)',
+ 9394 => '(w)',
+ 9395 => '(x)',
+ 9396 => '(y)',
+ 9397 => '(z)',
+ 10868 => '::=',
+ 10869 => '==',
+ 10870 => '===',
+ 12288 => ' ',
+ 12443 => ' ゙',
+ 12444 => ' ゚',
+ 12800 => '(ᄀ)',
+ 12801 => '(ᄂ)',
+ 12802 => '(ᄃ)',
+ 12803 => '(ᄅ)',
+ 12804 => '(ᄆ)',
+ 12805 => '(ᄇ)',
+ 12806 => '(ᄉ)',
+ 12807 => '(ᄋ)',
+ 12808 => '(ᄌ)',
+ 12809 => '(ᄎ)',
+ 12810 => '(ᄏ)',
+ 12811 => '(ᄐ)',
+ 12812 => '(ᄑ)',
+ 12813 => '(ᄒ)',
+ 12814 => '(가)',
+ 12815 => '(나)',
+ 12816 => '(다)',
+ 12817 => '(라)',
+ 12818 => '(마)',
+ 12819 => '(바)',
+ 12820 => '(사)',
+ 12821 => '(아)',
+ 12822 => '(자)',
+ 12823 => '(차)',
+ 12824 => '(카)',
+ 12825 => '(타)',
+ 12826 => '(파)',
+ 12827 => '(하)',
+ 12828 => '(주)',
+ 12829 => '(오전)',
+ 12830 => '(오후)',
+ 12832 => '(一)',
+ 12833 => '(二)',
+ 12834 => '(三)',
+ 12835 => '(四)',
+ 12836 => '(五)',
+ 12837 => '(六)',
+ 12838 => '(七)',
+ 12839 => '(八)',
+ 12840 => '(九)',
+ 12841 => '(十)',
+ 12842 => '(月)',
+ 12843 => '(火)',
+ 12844 => '(水)',
+ 12845 => '(木)',
+ 12846 => '(金)',
+ 12847 => '(土)',
+ 12848 => '(日)',
+ 12849 => '(株)',
+ 12850 => '(有)',
+ 12851 => '(社)',
+ 12852 => '(名)',
+ 12853 => '(特)',
+ 12854 => '(財)',
+ 12855 => '(祝)',
+ 12856 => '(労)',
+ 12857 => '(代)',
+ 12858 => '(呼)',
+ 12859 => '(学)',
+ 12860 => '(監)',
+ 12861 => '(企)',
+ 12862 => '(資)',
+ 12863 => '(協)',
+ 12864 => '(祭)',
+ 12865 => '(休)',
+ 12866 => '(自)',
+ 12867 => '(至)',
+ 64297 => '+',
+ 64606 => ' ٌّ',
+ 64607 => ' ٍّ',
+ 64608 => ' َّ',
+ 64609 => ' ُّ',
+ 64610 => ' ِّ',
+ 64611 => ' ّٰ',
+ 65018 => 'صلى الله عليه وسلم',
+ 65019 => 'جل جلاله',
+ 65040 => ',',
+ 65043 => ':',
+ 65044 => ';',
+ 65045 => '!',
+ 65046 => '?',
+ 65075 => '_',
+ 65076 => '_',
+ 65077 => '(',
+ 65078 => ')',
+ 65079 => '{',
+ 65080 => '}',
+ 65095 => '[',
+ 65096 => ']',
+ 65097 => ' ̅',
+ 65098 => ' ̅',
+ 65099 => ' ̅',
+ 65100 => ' ̅',
+ 65101 => '_',
+ 65102 => '_',
+ 65103 => '_',
+ 65104 => ',',
+ 65108 => ';',
+ 65109 => ':',
+ 65110 => '?',
+ 65111 => '!',
+ 65113 => '(',
+ 65114 => ')',
+ 65115 => '{',
+ 65116 => '}',
+ 65119 => '#',
+ 65120 => '&',
+ 65121 => '*',
+ 65122 => '+',
+ 65124 => '<',
+ 65125 => '>',
+ 65126 => '=',
+ 65128 => '\\',
+ 65129 => '$',
+ 65130 => '%',
+ 65131 => '@',
+ 65136 => ' ً',
+ 65138 => ' ٌ',
+ 65140 => ' ٍ',
+ 65142 => ' َ',
+ 65144 => ' ُ',
+ 65146 => ' ِ',
+ 65148 => ' ّ',
+ 65150 => ' ْ',
+ 65281 => '!',
+ 65282 => '"',
+ 65283 => '#',
+ 65284 => '$',
+ 65285 => '%',
+ 65286 => '&',
+ 65287 => '\'',
+ 65288 => '(',
+ 65289 => ')',
+ 65290 => '*',
+ 65291 => '+',
+ 65292 => ',',
+ 65295 => '/',
+ 65306 => ':',
+ 65307 => ';',
+ 65308 => '<',
+ 65309 => '=',
+ 65310 => '>',
+ 65311 => '?',
+ 65312 => '@',
+ 65339 => '[',
+ 65340 => '\\',
+ 65341 => ']',
+ 65342 => '^',
+ 65343 => '_',
+ 65344 => '`',
+ 65371 => '{',
+ 65372 => '|',
+ 65373 => '}',
+ 65374 => '~',
+ 65507 => ' ̄',
+ 127233 => '0,',
+ 127234 => '1,',
+ 127235 => '2,',
+ 127236 => '3,',
+ 127237 => '4,',
+ 127238 => '5,',
+ 127239 => '6,',
+ 127240 => '7,',
+ 127241 => '8,',
+ 127242 => '9,',
+ 127248 => '(a)',
+ 127249 => '(b)',
+ 127250 => '(c)',
+ 127251 => '(d)',
+ 127252 => '(e)',
+ 127253 => '(f)',
+ 127254 => '(g)',
+ 127255 => '(h)',
+ 127256 => '(i)',
+ 127257 => '(j)',
+ 127258 => '(k)',
+ 127259 => '(l)',
+ 127260 => '(m)',
+ 127261 => '(n)',
+ 127262 => '(o)',
+ 127263 => '(p)',
+ 127264 => '(q)',
+ 127265 => '(r)',
+ 127266 => '(s)',
+ 127267 => '(t)',
+ 127268 => '(u)',
+ 127269 => '(v)',
+ 127270 => '(w)',
+ 127271 => '(x)',
+ 127272 => '(y)',
+ 127273 => '(z)',
+);
diff --git a/vendor/symfony/polyfill-intl-idn/Resources/unidata/disallowed_STD3_valid.php b/vendor/symfony/polyfill-intl-idn/Resources/unidata/disallowed_STD3_valid.php
new file mode 100644
index 0000000..223396e
--- /dev/null
+++ b/vendor/symfony/polyfill-intl-idn/Resources/unidata/disallowed_STD3_valid.php
@@ -0,0 +1,71 @@
+ true,
+ 1 => true,
+ 2 => true,
+ 3 => true,
+ 4 => true,
+ 5 => true,
+ 6 => true,
+ 7 => true,
+ 8 => true,
+ 9 => true,
+ 10 => true,
+ 11 => true,
+ 12 => true,
+ 13 => true,
+ 14 => true,
+ 15 => true,
+ 16 => true,
+ 17 => true,
+ 18 => true,
+ 19 => true,
+ 20 => true,
+ 21 => true,
+ 22 => true,
+ 23 => true,
+ 24 => true,
+ 25 => true,
+ 26 => true,
+ 27 => true,
+ 28 => true,
+ 29 => true,
+ 30 => true,
+ 31 => true,
+ 32 => true,
+ 33 => true,
+ 34 => true,
+ 35 => true,
+ 36 => true,
+ 37 => true,
+ 38 => true,
+ 39 => true,
+ 40 => true,
+ 41 => true,
+ 42 => true,
+ 43 => true,
+ 44 => true,
+ 47 => true,
+ 58 => true,
+ 59 => true,
+ 60 => true,
+ 61 => true,
+ 62 => true,
+ 63 => true,
+ 64 => true,
+ 91 => true,
+ 92 => true,
+ 93 => true,
+ 94 => true,
+ 95 => true,
+ 96 => true,
+ 123 => true,
+ 124 => true,
+ 125 => true,
+ 126 => true,
+ 127 => true,
+ 8800 => true,
+ 8814 => true,
+ 8815 => true,
+);
diff --git a/vendor/symfony/polyfill-intl-idn/Resources/unidata/ignored.php b/vendor/symfony/polyfill-intl-idn/Resources/unidata/ignored.php
new file mode 100644
index 0000000..b377844
--- /dev/null
+++ b/vendor/symfony/polyfill-intl-idn/Resources/unidata/ignored.php
@@ -0,0 +1,273 @@
+ true,
+ 847 => true,
+ 6155 => true,
+ 6156 => true,
+ 6157 => true,
+ 8203 => true,
+ 8288 => true,
+ 8292 => true,
+ 65024 => true,
+ 65025 => true,
+ 65026 => true,
+ 65027 => true,
+ 65028 => true,
+ 65029 => true,
+ 65030 => true,
+ 65031 => true,
+ 65032 => true,
+ 65033 => true,
+ 65034 => true,
+ 65035 => true,
+ 65036 => true,
+ 65037 => true,
+ 65038 => true,
+ 65039 => true,
+ 65279 => true,
+ 113824 => true,
+ 113825 => true,
+ 113826 => true,
+ 113827 => true,
+ 917760 => true,
+ 917761 => true,
+ 917762 => true,
+ 917763 => true,
+ 917764 => true,
+ 917765 => true,
+ 917766 => true,
+ 917767 => true,
+ 917768 => true,
+ 917769 => true,
+ 917770 => true,
+ 917771 => true,
+ 917772 => true,
+ 917773 => true,
+ 917774 => true,
+ 917775 => true,
+ 917776 => true,
+ 917777 => true,
+ 917778 => true,
+ 917779 => true,
+ 917780 => true,
+ 917781 => true,
+ 917782 => true,
+ 917783 => true,
+ 917784 => true,
+ 917785 => true,
+ 917786 => true,
+ 917787 => true,
+ 917788 => true,
+ 917789 => true,
+ 917790 => true,
+ 917791 => true,
+ 917792 => true,
+ 917793 => true,
+ 917794 => true,
+ 917795 => true,
+ 917796 => true,
+ 917797 => true,
+ 917798 => true,
+ 917799 => true,
+ 917800 => true,
+ 917801 => true,
+ 917802 => true,
+ 917803 => true,
+ 917804 => true,
+ 917805 => true,
+ 917806 => true,
+ 917807 => true,
+ 917808 => true,
+ 917809 => true,
+ 917810 => true,
+ 917811 => true,
+ 917812 => true,
+ 917813 => true,
+ 917814 => true,
+ 917815 => true,
+ 917816 => true,
+ 917817 => true,
+ 917818 => true,
+ 917819 => true,
+ 917820 => true,
+ 917821 => true,
+ 917822 => true,
+ 917823 => true,
+ 917824 => true,
+ 917825 => true,
+ 917826 => true,
+ 917827 => true,
+ 917828 => true,
+ 917829 => true,
+ 917830 => true,
+ 917831 => true,
+ 917832 => true,
+ 917833 => true,
+ 917834 => true,
+ 917835 => true,
+ 917836 => true,
+ 917837 => true,
+ 917838 => true,
+ 917839 => true,
+ 917840 => true,
+ 917841 => true,
+ 917842 => true,
+ 917843 => true,
+ 917844 => true,
+ 917845 => true,
+ 917846 => true,
+ 917847 => true,
+ 917848 => true,
+ 917849 => true,
+ 917850 => true,
+ 917851 => true,
+ 917852 => true,
+ 917853 => true,
+ 917854 => true,
+ 917855 => true,
+ 917856 => true,
+ 917857 => true,
+ 917858 => true,
+ 917859 => true,
+ 917860 => true,
+ 917861 => true,
+ 917862 => true,
+ 917863 => true,
+ 917864 => true,
+ 917865 => true,
+ 917866 => true,
+ 917867 => true,
+ 917868 => true,
+ 917869 => true,
+ 917870 => true,
+ 917871 => true,
+ 917872 => true,
+ 917873 => true,
+ 917874 => true,
+ 917875 => true,
+ 917876 => true,
+ 917877 => true,
+ 917878 => true,
+ 917879 => true,
+ 917880 => true,
+ 917881 => true,
+ 917882 => true,
+ 917883 => true,
+ 917884 => true,
+ 917885 => true,
+ 917886 => true,
+ 917887 => true,
+ 917888 => true,
+ 917889 => true,
+ 917890 => true,
+ 917891 => true,
+ 917892 => true,
+ 917893 => true,
+ 917894 => true,
+ 917895 => true,
+ 917896 => true,
+ 917897 => true,
+ 917898 => true,
+ 917899 => true,
+ 917900 => true,
+ 917901 => true,
+ 917902 => true,
+ 917903 => true,
+ 917904 => true,
+ 917905 => true,
+ 917906 => true,
+ 917907 => true,
+ 917908 => true,
+ 917909 => true,
+ 917910 => true,
+ 917911 => true,
+ 917912 => true,
+ 917913 => true,
+ 917914 => true,
+ 917915 => true,
+ 917916 => true,
+ 917917 => true,
+ 917918 => true,
+ 917919 => true,
+ 917920 => true,
+ 917921 => true,
+ 917922 => true,
+ 917923 => true,
+ 917924 => true,
+ 917925 => true,
+ 917926 => true,
+ 917927 => true,
+ 917928 => true,
+ 917929 => true,
+ 917930 => true,
+ 917931 => true,
+ 917932 => true,
+ 917933 => true,
+ 917934 => true,
+ 917935 => true,
+ 917936 => true,
+ 917937 => true,
+ 917938 => true,
+ 917939 => true,
+ 917940 => true,
+ 917941 => true,
+ 917942 => true,
+ 917943 => true,
+ 917944 => true,
+ 917945 => true,
+ 917946 => true,
+ 917947 => true,
+ 917948 => true,
+ 917949 => true,
+ 917950 => true,
+ 917951 => true,
+ 917952 => true,
+ 917953 => true,
+ 917954 => true,
+ 917955 => true,
+ 917956 => true,
+ 917957 => true,
+ 917958 => true,
+ 917959 => true,
+ 917960 => true,
+ 917961 => true,
+ 917962 => true,
+ 917963 => true,
+ 917964 => true,
+ 917965 => true,
+ 917966 => true,
+ 917967 => true,
+ 917968 => true,
+ 917969 => true,
+ 917970 => true,
+ 917971 => true,
+ 917972 => true,
+ 917973 => true,
+ 917974 => true,
+ 917975 => true,
+ 917976 => true,
+ 917977 => true,
+ 917978 => true,
+ 917979 => true,
+ 917980 => true,
+ 917981 => true,
+ 917982 => true,
+ 917983 => true,
+ 917984 => true,
+ 917985 => true,
+ 917986 => true,
+ 917987 => true,
+ 917988 => true,
+ 917989 => true,
+ 917990 => true,
+ 917991 => true,
+ 917992 => true,
+ 917993 => true,
+ 917994 => true,
+ 917995 => true,
+ 917996 => true,
+ 917997 => true,
+ 917998 => true,
+ 917999 => true,
+);
diff --git a/vendor/symfony/polyfill-intl-idn/Resources/unidata/mapped.php b/vendor/symfony/polyfill-intl-idn/Resources/unidata/mapped.php
new file mode 100644
index 0000000..9b85fe9
--- /dev/null
+++ b/vendor/symfony/polyfill-intl-idn/Resources/unidata/mapped.php
@@ -0,0 +1,5778 @@
+ 'a',
+ 66 => 'b',
+ 67 => 'c',
+ 68 => 'd',
+ 69 => 'e',
+ 70 => 'f',
+ 71 => 'g',
+ 72 => 'h',
+ 73 => 'i',
+ 74 => 'j',
+ 75 => 'k',
+ 76 => 'l',
+ 77 => 'm',
+ 78 => 'n',
+ 79 => 'o',
+ 80 => 'p',
+ 81 => 'q',
+ 82 => 'r',
+ 83 => 's',
+ 84 => 't',
+ 85 => 'u',
+ 86 => 'v',
+ 87 => 'w',
+ 88 => 'x',
+ 89 => 'y',
+ 90 => 'z',
+ 170 => 'a',
+ 178 => '2',
+ 179 => '3',
+ 181 => 'μ',
+ 185 => '1',
+ 186 => 'o',
+ 188 => '1⁄4',
+ 189 => '1⁄2',
+ 190 => '3⁄4',
+ 192 => 'à',
+ 193 => 'á',
+ 194 => 'â',
+ 195 => 'ã',
+ 196 => 'ä',
+ 197 => 'å',
+ 198 => 'æ',
+ 199 => 'ç',
+ 200 => 'è',
+ 201 => 'é',
+ 202 => 'ê',
+ 203 => 'ë',
+ 204 => 'ì',
+ 205 => 'í',
+ 206 => 'î',
+ 207 => 'ï',
+ 208 => 'ð',
+ 209 => 'ñ',
+ 210 => 'ò',
+ 211 => 'ó',
+ 212 => 'ô',
+ 213 => 'õ',
+ 214 => 'ö',
+ 216 => 'ø',
+ 217 => 'ù',
+ 218 => 'ú',
+ 219 => 'û',
+ 220 => 'ü',
+ 221 => 'ý',
+ 222 => 'þ',
+ 256 => 'ā',
+ 258 => 'ă',
+ 260 => 'ą',
+ 262 => 'ć',
+ 264 => 'ĉ',
+ 266 => 'ċ',
+ 268 => 'č',
+ 270 => 'ď',
+ 272 => 'đ',
+ 274 => 'ē',
+ 276 => 'ĕ',
+ 278 => 'ė',
+ 280 => 'ę',
+ 282 => 'ě',
+ 284 => 'ĝ',
+ 286 => 'ğ',
+ 288 => 'ġ',
+ 290 => 'ģ',
+ 292 => 'ĥ',
+ 294 => 'ħ',
+ 296 => 'ĩ',
+ 298 => 'ī',
+ 300 => 'ĭ',
+ 302 => 'į',
+ 304 => 'i̇',
+ 306 => 'ij',
+ 307 => 'ij',
+ 308 => 'ĵ',
+ 310 => 'ķ',
+ 313 => 'ĺ',
+ 315 => 'ļ',
+ 317 => 'ľ',
+ 319 => 'l·',
+ 320 => 'l·',
+ 321 => 'ł',
+ 323 => 'ń',
+ 325 => 'ņ',
+ 327 => 'ň',
+ 329 => 'ʼn',
+ 330 => 'ŋ',
+ 332 => 'ō',
+ 334 => 'ŏ',
+ 336 => 'ő',
+ 338 => 'œ',
+ 340 => 'ŕ',
+ 342 => 'ŗ',
+ 344 => 'ř',
+ 346 => 'ś',
+ 348 => 'ŝ',
+ 350 => 'ş',
+ 352 => 'š',
+ 354 => 'ţ',
+ 356 => 'ť',
+ 358 => 'ŧ',
+ 360 => 'ũ',
+ 362 => 'ū',
+ 364 => 'ŭ',
+ 366 => 'ů',
+ 368 => 'ű',
+ 370 => 'ų',
+ 372 => 'ŵ',
+ 374 => 'ŷ',
+ 376 => 'ÿ',
+ 377 => 'ź',
+ 379 => 'ż',
+ 381 => 'ž',
+ 383 => 's',
+ 385 => 'ɓ',
+ 386 => 'ƃ',
+ 388 => 'ƅ',
+ 390 => 'ɔ',
+ 391 => 'ƈ',
+ 393 => 'ɖ',
+ 394 => 'ɗ',
+ 395 => 'ƌ',
+ 398 => 'ǝ',
+ 399 => 'ə',
+ 400 => 'ɛ',
+ 401 => 'ƒ',
+ 403 => 'ɠ',
+ 404 => 'ɣ',
+ 406 => 'ɩ',
+ 407 => 'ɨ',
+ 408 => 'ƙ',
+ 412 => 'ɯ',
+ 413 => 'ɲ',
+ 415 => 'ɵ',
+ 416 => 'ơ',
+ 418 => 'ƣ',
+ 420 => 'ƥ',
+ 422 => 'ʀ',
+ 423 => 'ƨ',
+ 425 => 'ʃ',
+ 428 => 'ƭ',
+ 430 => 'ʈ',
+ 431 => 'ư',
+ 433 => 'ʊ',
+ 434 => 'ʋ',
+ 435 => 'ƴ',
+ 437 => 'ƶ',
+ 439 => 'ʒ',
+ 440 => 'ƹ',
+ 444 => 'ƽ',
+ 452 => 'dž',
+ 453 => 'dž',
+ 454 => 'dž',
+ 455 => 'lj',
+ 456 => 'lj',
+ 457 => 'lj',
+ 458 => 'nj',
+ 459 => 'nj',
+ 460 => 'nj',
+ 461 => 'ǎ',
+ 463 => 'ǐ',
+ 465 => 'ǒ',
+ 467 => 'ǔ',
+ 469 => 'ǖ',
+ 471 => 'ǘ',
+ 473 => 'ǚ',
+ 475 => 'ǜ',
+ 478 => 'ǟ',
+ 480 => 'ǡ',
+ 482 => 'ǣ',
+ 484 => 'ǥ',
+ 486 => 'ǧ',
+ 488 => 'ǩ',
+ 490 => 'ǫ',
+ 492 => 'ǭ',
+ 494 => 'ǯ',
+ 497 => 'dz',
+ 498 => 'dz',
+ 499 => 'dz',
+ 500 => 'ǵ',
+ 502 => 'ƕ',
+ 503 => 'ƿ',
+ 504 => 'ǹ',
+ 506 => 'ǻ',
+ 508 => 'ǽ',
+ 510 => 'ǿ',
+ 512 => 'ȁ',
+ 514 => 'ȃ',
+ 516 => 'ȅ',
+ 518 => 'ȇ',
+ 520 => 'ȉ',
+ 522 => 'ȋ',
+ 524 => 'ȍ',
+ 526 => 'ȏ',
+ 528 => 'ȑ',
+ 530 => 'ȓ',
+ 532 => 'ȕ',
+ 534 => 'ȗ',
+ 536 => 'ș',
+ 538 => 'ț',
+ 540 => 'ȝ',
+ 542 => 'ȟ',
+ 544 => 'ƞ',
+ 546 => 'ȣ',
+ 548 => 'ȥ',
+ 550 => 'ȧ',
+ 552 => 'ȩ',
+ 554 => 'ȫ',
+ 556 => 'ȭ',
+ 558 => 'ȯ',
+ 560 => 'ȱ',
+ 562 => 'ȳ',
+ 570 => 'ⱥ',
+ 571 => 'ȼ',
+ 573 => 'ƚ',
+ 574 => 'ⱦ',
+ 577 => 'ɂ',
+ 579 => 'ƀ',
+ 580 => 'ʉ',
+ 581 => 'ʌ',
+ 582 => 'ɇ',
+ 584 => 'ɉ',
+ 586 => 'ɋ',
+ 588 => 'ɍ',
+ 590 => 'ɏ',
+ 688 => 'h',
+ 689 => 'ɦ',
+ 690 => 'j',
+ 691 => 'r',
+ 692 => 'ɹ',
+ 693 => 'ɻ',
+ 694 => 'ʁ',
+ 695 => 'w',
+ 696 => 'y',
+ 736 => 'ɣ',
+ 737 => 'l',
+ 738 => 's',
+ 739 => 'x',
+ 740 => 'ʕ',
+ 832 => '̀',
+ 833 => '́',
+ 835 => '̓',
+ 836 => '̈́',
+ 837 => 'ι',
+ 880 => 'ͱ',
+ 882 => 'ͳ',
+ 884 => 'ʹ',
+ 886 => 'ͷ',
+ 895 => 'ϳ',
+ 902 => 'ά',
+ 903 => '·',
+ 904 => 'έ',
+ 905 => 'ή',
+ 906 => 'ί',
+ 908 => 'ό',
+ 910 => 'ύ',
+ 911 => 'ώ',
+ 913 => 'α',
+ 914 => 'β',
+ 915 => 'γ',
+ 916 => 'δ',
+ 917 => 'ε',
+ 918 => 'ζ',
+ 919 => 'η',
+ 920 => 'θ',
+ 921 => 'ι',
+ 922 => 'κ',
+ 923 => 'λ',
+ 924 => 'μ',
+ 925 => 'ν',
+ 926 => 'ξ',
+ 927 => 'ο',
+ 928 => 'π',
+ 929 => 'ρ',
+ 931 => 'σ',
+ 932 => 'τ',
+ 933 => 'υ',
+ 934 => 'φ',
+ 935 => 'χ',
+ 936 => 'ψ',
+ 937 => 'ω',
+ 938 => 'ϊ',
+ 939 => 'ϋ',
+ 975 => 'ϗ',
+ 976 => 'β',
+ 977 => 'θ',
+ 978 => 'υ',
+ 979 => 'ύ',
+ 980 => 'ϋ',
+ 981 => 'φ',
+ 982 => 'π',
+ 984 => 'ϙ',
+ 986 => 'ϛ',
+ 988 => 'ϝ',
+ 990 => 'ϟ',
+ 992 => 'ϡ',
+ 994 => 'ϣ',
+ 996 => 'ϥ',
+ 998 => 'ϧ',
+ 1000 => 'ϩ',
+ 1002 => 'ϫ',
+ 1004 => 'ϭ',
+ 1006 => 'ϯ',
+ 1008 => 'κ',
+ 1009 => 'ρ',
+ 1010 => 'σ',
+ 1012 => 'θ',
+ 1013 => 'ε',
+ 1015 => 'ϸ',
+ 1017 => 'σ',
+ 1018 => 'ϻ',
+ 1021 => 'ͻ',
+ 1022 => 'ͼ',
+ 1023 => 'ͽ',
+ 1024 => 'ѐ',
+ 1025 => 'ё',
+ 1026 => 'ђ',
+ 1027 => 'ѓ',
+ 1028 => 'є',
+ 1029 => 'ѕ',
+ 1030 => 'і',
+ 1031 => 'ї',
+ 1032 => 'ј',
+ 1033 => 'љ',
+ 1034 => 'њ',
+ 1035 => 'ћ',
+ 1036 => 'ќ',
+ 1037 => 'ѝ',
+ 1038 => 'ў',
+ 1039 => 'џ',
+ 1040 => 'а',
+ 1041 => 'б',
+ 1042 => 'в',
+ 1043 => 'г',
+ 1044 => 'д',
+ 1045 => 'е',
+ 1046 => 'ж',
+ 1047 => 'з',
+ 1048 => 'и',
+ 1049 => 'й',
+ 1050 => 'к',
+ 1051 => 'л',
+ 1052 => 'м',
+ 1053 => 'н',
+ 1054 => 'о',
+ 1055 => 'п',
+ 1056 => 'р',
+ 1057 => 'с',
+ 1058 => 'т',
+ 1059 => 'у',
+ 1060 => 'ф',
+ 1061 => 'х',
+ 1062 => 'ц',
+ 1063 => 'ч',
+ 1064 => 'ш',
+ 1065 => 'щ',
+ 1066 => 'ъ',
+ 1067 => 'ы',
+ 1068 => 'ь',
+ 1069 => 'э',
+ 1070 => 'ю',
+ 1071 => 'я',
+ 1120 => 'ѡ',
+ 1122 => 'ѣ',
+ 1124 => 'ѥ',
+ 1126 => 'ѧ',
+ 1128 => 'ѩ',
+ 1130 => 'ѫ',
+ 1132 => 'ѭ',
+ 1134 => 'ѯ',
+ 1136 => 'ѱ',
+ 1138 => 'ѳ',
+ 1140 => 'ѵ',
+ 1142 => 'ѷ',
+ 1144 => 'ѹ',
+ 1146 => 'ѻ',
+ 1148 => 'ѽ',
+ 1150 => 'ѿ',
+ 1152 => 'ҁ',
+ 1162 => 'ҋ',
+ 1164 => 'ҍ',
+ 1166 => 'ҏ',
+ 1168 => 'ґ',
+ 1170 => 'ғ',
+ 1172 => 'ҕ',
+ 1174 => 'җ',
+ 1176 => 'ҙ',
+ 1178 => 'қ',
+ 1180 => 'ҝ',
+ 1182 => 'ҟ',
+ 1184 => 'ҡ',
+ 1186 => 'ң',
+ 1188 => 'ҥ',
+ 1190 => 'ҧ',
+ 1192 => 'ҩ',
+ 1194 => 'ҫ',
+ 1196 => 'ҭ',
+ 1198 => 'ү',
+ 1200 => 'ұ',
+ 1202 => 'ҳ',
+ 1204 => 'ҵ',
+ 1206 => 'ҷ',
+ 1208 => 'ҹ',
+ 1210 => 'һ',
+ 1212 => 'ҽ',
+ 1214 => 'ҿ',
+ 1217 => 'ӂ',
+ 1219 => 'ӄ',
+ 1221 => 'ӆ',
+ 1223 => 'ӈ',
+ 1225 => 'ӊ',
+ 1227 => 'ӌ',
+ 1229 => 'ӎ',
+ 1232 => 'ӑ',
+ 1234 => 'ӓ',
+ 1236 => 'ӕ',
+ 1238 => 'ӗ',
+ 1240 => 'ә',
+ 1242 => 'ӛ',
+ 1244 => 'ӝ',
+ 1246 => 'ӟ',
+ 1248 => 'ӡ',
+ 1250 => 'ӣ',
+ 1252 => 'ӥ',
+ 1254 => 'ӧ',
+ 1256 => 'ө',
+ 1258 => 'ӫ',
+ 1260 => 'ӭ',
+ 1262 => 'ӯ',
+ 1264 => 'ӱ',
+ 1266 => 'ӳ',
+ 1268 => 'ӵ',
+ 1270 => 'ӷ',
+ 1272 => 'ӹ',
+ 1274 => 'ӻ',
+ 1276 => 'ӽ',
+ 1278 => 'ӿ',
+ 1280 => 'ԁ',
+ 1282 => 'ԃ',
+ 1284 => 'ԅ',
+ 1286 => 'ԇ',
+ 1288 => 'ԉ',
+ 1290 => 'ԋ',
+ 1292 => 'ԍ',
+ 1294 => 'ԏ',
+ 1296 => 'ԑ',
+ 1298 => 'ԓ',
+ 1300 => 'ԕ',
+ 1302 => 'ԗ',
+ 1304 => 'ԙ',
+ 1306 => 'ԛ',
+ 1308 => 'ԝ',
+ 1310 => 'ԟ',
+ 1312 => 'ԡ',
+ 1314 => 'ԣ',
+ 1316 => 'ԥ',
+ 1318 => 'ԧ',
+ 1320 => 'ԩ',
+ 1322 => 'ԫ',
+ 1324 => 'ԭ',
+ 1326 => 'ԯ',
+ 1329 => 'ա',
+ 1330 => 'բ',
+ 1331 => 'գ',
+ 1332 => 'դ',
+ 1333 => 'ե',
+ 1334 => 'զ',
+ 1335 => 'է',
+ 1336 => 'ը',
+ 1337 => 'թ',
+ 1338 => 'ժ',
+ 1339 => 'ի',
+ 1340 => 'լ',
+ 1341 => 'խ',
+ 1342 => 'ծ',
+ 1343 => 'կ',
+ 1344 => 'հ',
+ 1345 => 'ձ',
+ 1346 => 'ղ',
+ 1347 => 'ճ',
+ 1348 => 'մ',
+ 1349 => 'յ',
+ 1350 => 'ն',
+ 1351 => 'շ',
+ 1352 => 'ո',
+ 1353 => 'չ',
+ 1354 => 'պ',
+ 1355 => 'ջ',
+ 1356 => 'ռ',
+ 1357 => 'ս',
+ 1358 => 'վ',
+ 1359 => 'տ',
+ 1360 => 'ր',
+ 1361 => 'ց',
+ 1362 => 'ւ',
+ 1363 => 'փ',
+ 1364 => 'ք',
+ 1365 => 'օ',
+ 1366 => 'ֆ',
+ 1415 => 'եւ',
+ 1653 => 'اٴ',
+ 1654 => 'وٴ',
+ 1655 => 'ۇٴ',
+ 1656 => 'يٴ',
+ 2392 => 'क़',
+ 2393 => 'ख़',
+ 2394 => 'ग़',
+ 2395 => 'ज़',
+ 2396 => 'ड़',
+ 2397 => 'ढ़',
+ 2398 => 'फ़',
+ 2399 => 'य़',
+ 2524 => 'ড়',
+ 2525 => 'ঢ়',
+ 2527 => 'য়',
+ 2611 => 'ਲ਼',
+ 2614 => 'ਸ਼',
+ 2649 => 'ਖ਼',
+ 2650 => 'ਗ਼',
+ 2651 => 'ਜ਼',
+ 2654 => 'ਫ਼',
+ 2908 => 'ଡ଼',
+ 2909 => 'ଢ଼',
+ 3635 => 'ํา',
+ 3763 => 'ໍາ',
+ 3804 => 'ຫນ',
+ 3805 => 'ຫມ',
+ 3852 => '་',
+ 3907 => 'གྷ',
+ 3917 => 'ཌྷ',
+ 3922 => 'དྷ',
+ 3927 => 'བྷ',
+ 3932 => 'ཛྷ',
+ 3945 => 'ཀྵ',
+ 3955 => 'ཱི',
+ 3957 => 'ཱུ',
+ 3958 => 'ྲྀ',
+ 3959 => 'ྲཱྀ',
+ 3960 => 'ླྀ',
+ 3961 => 'ླཱྀ',
+ 3969 => 'ཱྀ',
+ 3987 => 'ྒྷ',
+ 3997 => 'ྜྷ',
+ 4002 => 'ྡྷ',
+ 4007 => 'ྦྷ',
+ 4012 => 'ྫྷ',
+ 4025 => 'ྐྵ',
+ 4295 => 'ⴧ',
+ 4301 => 'ⴭ',
+ 4348 => 'ნ',
+ 5112 => 'Ᏸ',
+ 5113 => 'Ᏹ',
+ 5114 => 'Ᏺ',
+ 5115 => 'Ᏻ',
+ 5116 => 'Ᏼ',
+ 5117 => 'Ᏽ',
+ 7296 => 'в',
+ 7297 => 'д',
+ 7298 => 'о',
+ 7299 => 'с',
+ 7300 => 'т',
+ 7301 => 'т',
+ 7302 => 'ъ',
+ 7303 => 'ѣ',
+ 7304 => 'ꙋ',
+ 7312 => 'ა',
+ 7313 => 'ბ',
+ 7314 => 'გ',
+ 7315 => 'დ',
+ 7316 => 'ე',
+ 7317 => 'ვ',
+ 7318 => 'ზ',
+ 7319 => 'თ',
+ 7320 => 'ი',
+ 7321 => 'კ',
+ 7322 => 'ლ',
+ 7323 => 'მ',
+ 7324 => 'ნ',
+ 7325 => 'ო',
+ 7326 => 'პ',
+ 7327 => 'ჟ',
+ 7328 => 'რ',
+ 7329 => 'ს',
+ 7330 => 'ტ',
+ 7331 => 'უ',
+ 7332 => 'ფ',
+ 7333 => 'ქ',
+ 7334 => 'ღ',
+ 7335 => 'ყ',
+ 7336 => 'შ',
+ 7337 => 'ჩ',
+ 7338 => 'ც',
+ 7339 => 'ძ',
+ 7340 => 'წ',
+ 7341 => 'ჭ',
+ 7342 => 'ხ',
+ 7343 => 'ჯ',
+ 7344 => 'ჰ',
+ 7345 => 'ჱ',
+ 7346 => 'ჲ',
+ 7347 => 'ჳ',
+ 7348 => 'ჴ',
+ 7349 => 'ჵ',
+ 7350 => 'ჶ',
+ 7351 => 'ჷ',
+ 7352 => 'ჸ',
+ 7353 => 'ჹ',
+ 7354 => 'ჺ',
+ 7357 => 'ჽ',
+ 7358 => 'ჾ',
+ 7359 => 'ჿ',
+ 7468 => 'a',
+ 7469 => 'æ',
+ 7470 => 'b',
+ 7472 => 'd',
+ 7473 => 'e',
+ 7474 => 'ǝ',
+ 7475 => 'g',
+ 7476 => 'h',
+ 7477 => 'i',
+ 7478 => 'j',
+ 7479 => 'k',
+ 7480 => 'l',
+ 7481 => 'm',
+ 7482 => 'n',
+ 7484 => 'o',
+ 7485 => 'ȣ',
+ 7486 => 'p',
+ 7487 => 'r',
+ 7488 => 't',
+ 7489 => 'u',
+ 7490 => 'w',
+ 7491 => 'a',
+ 7492 => 'ɐ',
+ 7493 => 'ɑ',
+ 7494 => 'ᴂ',
+ 7495 => 'b',
+ 7496 => 'd',
+ 7497 => 'e',
+ 7498 => 'ə',
+ 7499 => 'ɛ',
+ 7500 => 'ɜ',
+ 7501 => 'g',
+ 7503 => 'k',
+ 7504 => 'm',
+ 7505 => 'ŋ',
+ 7506 => 'o',
+ 7507 => 'ɔ',
+ 7508 => 'ᴖ',
+ 7509 => 'ᴗ',
+ 7510 => 'p',
+ 7511 => 't',
+ 7512 => 'u',
+ 7513 => 'ᴝ',
+ 7514 => 'ɯ',
+ 7515 => 'v',
+ 7516 => 'ᴥ',
+ 7517 => 'β',
+ 7518 => 'γ',
+ 7519 => 'δ',
+ 7520 => 'φ',
+ 7521 => 'χ',
+ 7522 => 'i',
+ 7523 => 'r',
+ 7524 => 'u',
+ 7525 => 'v',
+ 7526 => 'β',
+ 7527 => 'γ',
+ 7528 => 'ρ',
+ 7529 => 'φ',
+ 7530 => 'χ',
+ 7544 => 'н',
+ 7579 => 'ɒ',
+ 7580 => 'c',
+ 7581 => 'ɕ',
+ 7582 => 'ð',
+ 7583 => 'ɜ',
+ 7584 => 'f',
+ 7585 => 'ɟ',
+ 7586 => 'ɡ',
+ 7587 => 'ɥ',
+ 7588 => 'ɨ',
+ 7589 => 'ɩ',
+ 7590 => 'ɪ',
+ 7591 => 'ᵻ',
+ 7592 => 'ʝ',
+ 7593 => 'ɭ',
+ 7594 => 'ᶅ',
+ 7595 => 'ʟ',
+ 7596 => 'ɱ',
+ 7597 => 'ɰ',
+ 7598 => 'ɲ',
+ 7599 => 'ɳ',
+ 7600 => 'ɴ',
+ 7601 => 'ɵ',
+ 7602 => 'ɸ',
+ 7603 => 'ʂ',
+ 7604 => 'ʃ',
+ 7605 => 'ƫ',
+ 7606 => 'ʉ',
+ 7607 => 'ʊ',
+ 7608 => 'ᴜ',
+ 7609 => 'ʋ',
+ 7610 => 'ʌ',
+ 7611 => 'z',
+ 7612 => 'ʐ',
+ 7613 => 'ʑ',
+ 7614 => 'ʒ',
+ 7615 => 'θ',
+ 7680 => 'ḁ',
+ 7682 => 'ḃ',
+ 7684 => 'ḅ',
+ 7686 => 'ḇ',
+ 7688 => 'ḉ',
+ 7690 => 'ḋ',
+ 7692 => 'ḍ',
+ 7694 => 'ḏ',
+ 7696 => 'ḑ',
+ 7698 => 'ḓ',
+ 7700 => 'ḕ',
+ 7702 => 'ḗ',
+ 7704 => 'ḙ',
+ 7706 => 'ḛ',
+ 7708 => 'ḝ',
+ 7710 => 'ḟ',
+ 7712 => 'ḡ',
+ 7714 => 'ḣ',
+ 7716 => 'ḥ',
+ 7718 => 'ḧ',
+ 7720 => 'ḩ',
+ 7722 => 'ḫ',
+ 7724 => 'ḭ',
+ 7726 => 'ḯ',
+ 7728 => 'ḱ',
+ 7730 => 'ḳ',
+ 7732 => 'ḵ',
+ 7734 => 'ḷ',
+ 7736 => 'ḹ',
+ 7738 => 'ḻ',
+ 7740 => 'ḽ',
+ 7742 => 'ḿ',
+ 7744 => 'ṁ',
+ 7746 => 'ṃ',
+ 7748 => 'ṅ',
+ 7750 => 'ṇ',
+ 7752 => 'ṉ',
+ 7754 => 'ṋ',
+ 7756 => 'ṍ',
+ 7758 => 'ṏ',
+ 7760 => 'ṑ',
+ 7762 => 'ṓ',
+ 7764 => 'ṕ',
+ 7766 => 'ṗ',
+ 7768 => 'ṙ',
+ 7770 => 'ṛ',
+ 7772 => 'ṝ',
+ 7774 => 'ṟ',
+ 7776 => 'ṡ',
+ 7778 => 'ṣ',
+ 7780 => 'ṥ',
+ 7782 => 'ṧ',
+ 7784 => 'ṩ',
+ 7786 => 'ṫ',
+ 7788 => 'ṭ',
+ 7790 => 'ṯ',
+ 7792 => 'ṱ',
+ 7794 => 'ṳ',
+ 7796 => 'ṵ',
+ 7798 => 'ṷ',
+ 7800 => 'ṹ',
+ 7802 => 'ṻ',
+ 7804 => 'ṽ',
+ 7806 => 'ṿ',
+ 7808 => 'ẁ',
+ 7810 => 'ẃ',
+ 7812 => 'ẅ',
+ 7814 => 'ẇ',
+ 7816 => 'ẉ',
+ 7818 => 'ẋ',
+ 7820 => 'ẍ',
+ 7822 => 'ẏ',
+ 7824 => 'ẑ',
+ 7826 => 'ẓ',
+ 7828 => 'ẕ',
+ 7834 => 'aʾ',
+ 7835 => 'ṡ',
+ 7838 => 'ss',
+ 7840 => 'ạ',
+ 7842 => 'ả',
+ 7844 => 'ấ',
+ 7846 => 'ầ',
+ 7848 => 'ẩ',
+ 7850 => 'ẫ',
+ 7852 => 'ậ',
+ 7854 => 'ắ',
+ 7856 => 'ằ',
+ 7858 => 'ẳ',
+ 7860 => 'ẵ',
+ 7862 => 'ặ',
+ 7864 => 'ẹ',
+ 7866 => 'ẻ',
+ 7868 => 'ẽ',
+ 7870 => 'ế',
+ 7872 => 'ề',
+ 7874 => 'ể',
+ 7876 => 'ễ',
+ 7878 => 'ệ',
+ 7880 => 'ỉ',
+ 7882 => 'ị',
+ 7884 => 'ọ',
+ 7886 => 'ỏ',
+ 7888 => 'ố',
+ 7890 => 'ồ',
+ 7892 => 'ổ',
+ 7894 => 'ỗ',
+ 7896 => 'ộ',
+ 7898 => 'ớ',
+ 7900 => 'ờ',
+ 7902 => 'ở',
+ 7904 => 'ỡ',
+ 7906 => 'ợ',
+ 7908 => 'ụ',
+ 7910 => 'ủ',
+ 7912 => 'ứ',
+ 7914 => 'ừ',
+ 7916 => 'ử',
+ 7918 => 'ữ',
+ 7920 => 'ự',
+ 7922 => 'ỳ',
+ 7924 => 'ỵ',
+ 7926 => 'ỷ',
+ 7928 => 'ỹ',
+ 7930 => 'ỻ',
+ 7932 => 'ỽ',
+ 7934 => 'ỿ',
+ 7944 => 'ἀ',
+ 7945 => 'ἁ',
+ 7946 => 'ἂ',
+ 7947 => 'ἃ',
+ 7948 => 'ἄ',
+ 7949 => 'ἅ',
+ 7950 => 'ἆ',
+ 7951 => 'ἇ',
+ 7960 => 'ἐ',
+ 7961 => 'ἑ',
+ 7962 => 'ἒ',
+ 7963 => 'ἓ',
+ 7964 => 'ἔ',
+ 7965 => 'ἕ',
+ 7976 => 'ἠ',
+ 7977 => 'ἡ',
+ 7978 => 'ἢ',
+ 7979 => 'ἣ',
+ 7980 => 'ἤ',
+ 7981 => 'ἥ',
+ 7982 => 'ἦ',
+ 7983 => 'ἧ',
+ 7992 => 'ἰ',
+ 7993 => 'ἱ',
+ 7994 => 'ἲ',
+ 7995 => 'ἳ',
+ 7996 => 'ἴ',
+ 7997 => 'ἵ',
+ 7998 => 'ἶ',
+ 7999 => 'ἷ',
+ 8008 => 'ὀ',
+ 8009 => 'ὁ',
+ 8010 => 'ὂ',
+ 8011 => 'ὃ',
+ 8012 => 'ὄ',
+ 8013 => 'ὅ',
+ 8025 => 'ὑ',
+ 8027 => 'ὓ',
+ 8029 => 'ὕ',
+ 8031 => 'ὗ',
+ 8040 => 'ὠ',
+ 8041 => 'ὡ',
+ 8042 => 'ὢ',
+ 8043 => 'ὣ',
+ 8044 => 'ὤ',
+ 8045 => 'ὥ',
+ 8046 => 'ὦ',
+ 8047 => 'ὧ',
+ 8049 => 'ά',
+ 8051 => 'έ',
+ 8053 => 'ή',
+ 8055 => 'ί',
+ 8057 => 'ό',
+ 8059 => 'ύ',
+ 8061 => 'ώ',
+ 8064 => 'ἀι',
+ 8065 => 'ἁι',
+ 8066 => 'ἂι',
+ 8067 => 'ἃι',
+ 8068 => 'ἄι',
+ 8069 => 'ἅι',
+ 8070 => 'ἆι',
+ 8071 => 'ἇι',
+ 8072 => 'ἀι',
+ 8073 => 'ἁι',
+ 8074 => 'ἂι',
+ 8075 => 'ἃι',
+ 8076 => 'ἄι',
+ 8077 => 'ἅι',
+ 8078 => 'ἆι',
+ 8079 => 'ἇι',
+ 8080 => 'ἠι',
+ 8081 => 'ἡι',
+ 8082 => 'ἢι',
+ 8083 => 'ἣι',
+ 8084 => 'ἤι',
+ 8085 => 'ἥι',
+ 8086 => 'ἦι',
+ 8087 => 'ἧι',
+ 8088 => 'ἠι',
+ 8089 => 'ἡι',
+ 8090 => 'ἢι',
+ 8091 => 'ἣι',
+ 8092 => 'ἤι',
+ 8093 => 'ἥι',
+ 8094 => 'ἦι',
+ 8095 => 'ἧι',
+ 8096 => 'ὠι',
+ 8097 => 'ὡι',
+ 8098 => 'ὢι',
+ 8099 => 'ὣι',
+ 8100 => 'ὤι',
+ 8101 => 'ὥι',
+ 8102 => 'ὦι',
+ 8103 => 'ὧι',
+ 8104 => 'ὠι',
+ 8105 => 'ὡι',
+ 8106 => 'ὢι',
+ 8107 => 'ὣι',
+ 8108 => 'ὤι',
+ 8109 => 'ὥι',
+ 8110 => 'ὦι',
+ 8111 => 'ὧι',
+ 8114 => 'ὰι',
+ 8115 => 'αι',
+ 8116 => 'άι',
+ 8119 => 'ᾶι',
+ 8120 => 'ᾰ',
+ 8121 => 'ᾱ',
+ 8122 => 'ὰ',
+ 8123 => 'ά',
+ 8124 => 'αι',
+ 8126 => 'ι',
+ 8130 => 'ὴι',
+ 8131 => 'ηι',
+ 8132 => 'ήι',
+ 8135 => 'ῆι',
+ 8136 => 'ὲ',
+ 8137 => 'έ',
+ 8138 => 'ὴ',
+ 8139 => 'ή',
+ 8140 => 'ηι',
+ 8147 => 'ΐ',
+ 8152 => 'ῐ',
+ 8153 => 'ῑ',
+ 8154 => 'ὶ',
+ 8155 => 'ί',
+ 8163 => 'ΰ',
+ 8168 => 'ῠ',
+ 8169 => 'ῡ',
+ 8170 => 'ὺ',
+ 8171 => 'ύ',
+ 8172 => 'ῥ',
+ 8178 => 'ὼι',
+ 8179 => 'ωι',
+ 8180 => 'ώι',
+ 8183 => 'ῶι',
+ 8184 => 'ὸ',
+ 8185 => 'ό',
+ 8186 => 'ὼ',
+ 8187 => 'ώ',
+ 8188 => 'ωι',
+ 8209 => '‐',
+ 8243 => '′′',
+ 8244 => '′′′',
+ 8246 => '‵‵',
+ 8247 => '‵‵‵',
+ 8279 => '′′′′',
+ 8304 => '0',
+ 8305 => 'i',
+ 8308 => '4',
+ 8309 => '5',
+ 8310 => '6',
+ 8311 => '7',
+ 8312 => '8',
+ 8313 => '9',
+ 8315 => '−',
+ 8319 => 'n',
+ 8320 => '0',
+ 8321 => '1',
+ 8322 => '2',
+ 8323 => '3',
+ 8324 => '4',
+ 8325 => '5',
+ 8326 => '6',
+ 8327 => '7',
+ 8328 => '8',
+ 8329 => '9',
+ 8331 => '−',
+ 8336 => 'a',
+ 8337 => 'e',
+ 8338 => 'o',
+ 8339 => 'x',
+ 8340 => 'ə',
+ 8341 => 'h',
+ 8342 => 'k',
+ 8343 => 'l',
+ 8344 => 'm',
+ 8345 => 'n',
+ 8346 => 'p',
+ 8347 => 's',
+ 8348 => 't',
+ 8360 => 'rs',
+ 8450 => 'c',
+ 8451 => '°c',
+ 8455 => 'ɛ',
+ 8457 => '°f',
+ 8458 => 'g',
+ 8459 => 'h',
+ 8460 => 'h',
+ 8461 => 'h',
+ 8462 => 'h',
+ 8463 => 'ħ',
+ 8464 => 'i',
+ 8465 => 'i',
+ 8466 => 'l',
+ 8467 => 'l',
+ 8469 => 'n',
+ 8470 => 'no',
+ 8473 => 'p',
+ 8474 => 'q',
+ 8475 => 'r',
+ 8476 => 'r',
+ 8477 => 'r',
+ 8480 => 'sm',
+ 8481 => 'tel',
+ 8482 => 'tm',
+ 8484 => 'z',
+ 8486 => 'ω',
+ 8488 => 'z',
+ 8490 => 'k',
+ 8491 => 'å',
+ 8492 => 'b',
+ 8493 => 'c',
+ 8495 => 'e',
+ 8496 => 'e',
+ 8497 => 'f',
+ 8499 => 'm',
+ 8500 => 'o',
+ 8501 => 'א',
+ 8502 => 'ב',
+ 8503 => 'ג',
+ 8504 => 'ד',
+ 8505 => 'i',
+ 8507 => 'fax',
+ 8508 => 'π',
+ 8509 => 'γ',
+ 8510 => 'γ',
+ 8511 => 'π',
+ 8512 => '∑',
+ 8517 => 'd',
+ 8518 => 'd',
+ 8519 => 'e',
+ 8520 => 'i',
+ 8521 => 'j',
+ 8528 => '1⁄7',
+ 8529 => '1⁄9',
+ 8530 => '1⁄10',
+ 8531 => '1⁄3',
+ 8532 => '2⁄3',
+ 8533 => '1⁄5',
+ 8534 => '2⁄5',
+ 8535 => '3⁄5',
+ 8536 => '4⁄5',
+ 8537 => '1⁄6',
+ 8538 => '5⁄6',
+ 8539 => '1⁄8',
+ 8540 => '3⁄8',
+ 8541 => '5⁄8',
+ 8542 => '7⁄8',
+ 8543 => '1⁄',
+ 8544 => 'i',
+ 8545 => 'ii',
+ 8546 => 'iii',
+ 8547 => 'iv',
+ 8548 => 'v',
+ 8549 => 'vi',
+ 8550 => 'vii',
+ 8551 => 'viii',
+ 8552 => 'ix',
+ 8553 => 'x',
+ 8554 => 'xi',
+ 8555 => 'xii',
+ 8556 => 'l',
+ 8557 => 'c',
+ 8558 => 'd',
+ 8559 => 'm',
+ 8560 => 'i',
+ 8561 => 'ii',
+ 8562 => 'iii',
+ 8563 => 'iv',
+ 8564 => 'v',
+ 8565 => 'vi',
+ 8566 => 'vii',
+ 8567 => 'viii',
+ 8568 => 'ix',
+ 8569 => 'x',
+ 8570 => 'xi',
+ 8571 => 'xii',
+ 8572 => 'l',
+ 8573 => 'c',
+ 8574 => 'd',
+ 8575 => 'm',
+ 8585 => '0⁄3',
+ 8748 => '∫∫',
+ 8749 => '∫∫∫',
+ 8751 => '∮∮',
+ 8752 => '∮∮∮',
+ 9001 => '〈',
+ 9002 => '〉',
+ 9312 => '1',
+ 9313 => '2',
+ 9314 => '3',
+ 9315 => '4',
+ 9316 => '5',
+ 9317 => '6',
+ 9318 => '7',
+ 9319 => '8',
+ 9320 => '9',
+ 9321 => '10',
+ 9322 => '11',
+ 9323 => '12',
+ 9324 => '13',
+ 9325 => '14',
+ 9326 => '15',
+ 9327 => '16',
+ 9328 => '17',
+ 9329 => '18',
+ 9330 => '19',
+ 9331 => '20',
+ 9398 => 'a',
+ 9399 => 'b',
+ 9400 => 'c',
+ 9401 => 'd',
+ 9402 => 'e',
+ 9403 => 'f',
+ 9404 => 'g',
+ 9405 => 'h',
+ 9406 => 'i',
+ 9407 => 'j',
+ 9408 => 'k',
+ 9409 => 'l',
+ 9410 => 'm',
+ 9411 => 'n',
+ 9412 => 'o',
+ 9413 => 'p',
+ 9414 => 'q',
+ 9415 => 'r',
+ 9416 => 's',
+ 9417 => 't',
+ 9418 => 'u',
+ 9419 => 'v',
+ 9420 => 'w',
+ 9421 => 'x',
+ 9422 => 'y',
+ 9423 => 'z',
+ 9424 => 'a',
+ 9425 => 'b',
+ 9426 => 'c',
+ 9427 => 'd',
+ 9428 => 'e',
+ 9429 => 'f',
+ 9430 => 'g',
+ 9431 => 'h',
+ 9432 => 'i',
+ 9433 => 'j',
+ 9434 => 'k',
+ 9435 => 'l',
+ 9436 => 'm',
+ 9437 => 'n',
+ 9438 => 'o',
+ 9439 => 'p',
+ 9440 => 'q',
+ 9441 => 'r',
+ 9442 => 's',
+ 9443 => 't',
+ 9444 => 'u',
+ 9445 => 'v',
+ 9446 => 'w',
+ 9447 => 'x',
+ 9448 => 'y',
+ 9449 => 'z',
+ 9450 => '0',
+ 10764 => '∫∫∫∫',
+ 10972 => '⫝̸',
+ 11264 => 'ⰰ',
+ 11265 => 'ⰱ',
+ 11266 => 'ⰲ',
+ 11267 => 'ⰳ',
+ 11268 => 'ⰴ',
+ 11269 => 'ⰵ',
+ 11270 => 'ⰶ',
+ 11271 => 'ⰷ',
+ 11272 => 'ⰸ',
+ 11273 => 'ⰹ',
+ 11274 => 'ⰺ',
+ 11275 => 'ⰻ',
+ 11276 => 'ⰼ',
+ 11277 => 'ⰽ',
+ 11278 => 'ⰾ',
+ 11279 => 'ⰿ',
+ 11280 => 'ⱀ',
+ 11281 => 'ⱁ',
+ 11282 => 'ⱂ',
+ 11283 => 'ⱃ',
+ 11284 => 'ⱄ',
+ 11285 => 'ⱅ',
+ 11286 => 'ⱆ',
+ 11287 => 'ⱇ',
+ 11288 => 'ⱈ',
+ 11289 => 'ⱉ',
+ 11290 => 'ⱊ',
+ 11291 => 'ⱋ',
+ 11292 => 'ⱌ',
+ 11293 => 'ⱍ',
+ 11294 => 'ⱎ',
+ 11295 => 'ⱏ',
+ 11296 => 'ⱐ',
+ 11297 => 'ⱑ',
+ 11298 => 'ⱒ',
+ 11299 => 'ⱓ',
+ 11300 => 'ⱔ',
+ 11301 => 'ⱕ',
+ 11302 => 'ⱖ',
+ 11303 => 'ⱗ',
+ 11304 => 'ⱘ',
+ 11305 => 'ⱙ',
+ 11306 => 'ⱚ',
+ 11307 => 'ⱛ',
+ 11308 => 'ⱜ',
+ 11309 => 'ⱝ',
+ 11310 => 'ⱞ',
+ 11360 => 'ⱡ',
+ 11362 => 'ɫ',
+ 11363 => 'ᵽ',
+ 11364 => 'ɽ',
+ 11367 => 'ⱨ',
+ 11369 => 'ⱪ',
+ 11371 => 'ⱬ',
+ 11373 => 'ɑ',
+ 11374 => 'ɱ',
+ 11375 => 'ɐ',
+ 11376 => 'ɒ',
+ 11378 => 'ⱳ',
+ 11381 => 'ⱶ',
+ 11388 => 'j',
+ 11389 => 'v',
+ 11390 => 'ȿ',
+ 11391 => 'ɀ',
+ 11392 => 'ⲁ',
+ 11394 => 'ⲃ',
+ 11396 => 'ⲅ',
+ 11398 => 'ⲇ',
+ 11400 => 'ⲉ',
+ 11402 => 'ⲋ',
+ 11404 => 'ⲍ',
+ 11406 => 'ⲏ',
+ 11408 => 'ⲑ',
+ 11410 => 'ⲓ',
+ 11412 => 'ⲕ',
+ 11414 => 'ⲗ',
+ 11416 => 'ⲙ',
+ 11418 => 'ⲛ',
+ 11420 => 'ⲝ',
+ 11422 => 'ⲟ',
+ 11424 => 'ⲡ',
+ 11426 => 'ⲣ',
+ 11428 => 'ⲥ',
+ 11430 => 'ⲧ',
+ 11432 => 'ⲩ',
+ 11434 => 'ⲫ',
+ 11436 => 'ⲭ',
+ 11438 => 'ⲯ',
+ 11440 => 'ⲱ',
+ 11442 => 'ⲳ',
+ 11444 => 'ⲵ',
+ 11446 => 'ⲷ',
+ 11448 => 'ⲹ',
+ 11450 => 'ⲻ',
+ 11452 => 'ⲽ',
+ 11454 => 'ⲿ',
+ 11456 => 'ⳁ',
+ 11458 => 'ⳃ',
+ 11460 => 'ⳅ',
+ 11462 => 'ⳇ',
+ 11464 => 'ⳉ',
+ 11466 => 'ⳋ',
+ 11468 => 'ⳍ',
+ 11470 => 'ⳏ',
+ 11472 => 'ⳑ',
+ 11474 => 'ⳓ',
+ 11476 => 'ⳕ',
+ 11478 => 'ⳗ',
+ 11480 => 'ⳙ',
+ 11482 => 'ⳛ',
+ 11484 => 'ⳝ',
+ 11486 => 'ⳟ',
+ 11488 => 'ⳡ',
+ 11490 => 'ⳣ',
+ 11499 => 'ⳬ',
+ 11501 => 'ⳮ',
+ 11506 => 'ⳳ',
+ 11631 => 'ⵡ',
+ 11935 => '母',
+ 12019 => '龟',
+ 12032 => '一',
+ 12033 => '丨',
+ 12034 => '丶',
+ 12035 => '丿',
+ 12036 => '乙',
+ 12037 => '亅',
+ 12038 => '二',
+ 12039 => '亠',
+ 12040 => '人',
+ 12041 => '儿',
+ 12042 => '入',
+ 12043 => '八',
+ 12044 => '冂',
+ 12045 => '冖',
+ 12046 => '冫',
+ 12047 => '几',
+ 12048 => '凵',
+ 12049 => '刀',
+ 12050 => '力',
+ 12051 => '勹',
+ 12052 => '匕',
+ 12053 => '匚',
+ 12054 => '匸',
+ 12055 => '十',
+ 12056 => '卜',
+ 12057 => '卩',
+ 12058 => '厂',
+ 12059 => '厶',
+ 12060 => '又',
+ 12061 => '口',
+ 12062 => '囗',
+ 12063 => '土',
+ 12064 => '士',
+ 12065 => '夂',
+ 12066 => '夊',
+ 12067 => '夕',
+ 12068 => '大',
+ 12069 => '女',
+ 12070 => '子',
+ 12071 => '宀',
+ 12072 => '寸',
+ 12073 => '小',
+ 12074 => '尢',
+ 12075 => '尸',
+ 12076 => '屮',
+ 12077 => '山',
+ 12078 => '巛',
+ 12079 => '工',
+ 12080 => '己',
+ 12081 => '巾',
+ 12082 => '干',
+ 12083 => '幺',
+ 12084 => '广',
+ 12085 => '廴',
+ 12086 => '廾',
+ 12087 => '弋',
+ 12088 => '弓',
+ 12089 => '彐',
+ 12090 => '彡',
+ 12091 => '彳',
+ 12092 => '心',
+ 12093 => '戈',
+ 12094 => '戶',
+ 12095 => '手',
+ 12096 => '支',
+ 12097 => '攴',
+ 12098 => '文',
+ 12099 => '斗',
+ 12100 => '斤',
+ 12101 => '方',
+ 12102 => '无',
+ 12103 => '日',
+ 12104 => '曰',
+ 12105 => '月',
+ 12106 => '木',
+ 12107 => '欠',
+ 12108 => '止',
+ 12109 => '歹',
+ 12110 => '殳',
+ 12111 => '毋',
+ 12112 => '比',
+ 12113 => '毛',
+ 12114 => '氏',
+ 12115 => '气',
+ 12116 => '水',
+ 12117 => '火',
+ 12118 => '爪',
+ 12119 => '父',
+ 12120 => '爻',
+ 12121 => '爿',
+ 12122 => '片',
+ 12123 => '牙',
+ 12124 => '牛',
+ 12125 => '犬',
+ 12126 => '玄',
+ 12127 => '玉',
+ 12128 => '瓜',
+ 12129 => '瓦',
+ 12130 => '甘',
+ 12131 => '生',
+ 12132 => '用',
+ 12133 => '田',
+ 12134 => '疋',
+ 12135 => '疒',
+ 12136 => '癶',
+ 12137 => '白',
+ 12138 => '皮',
+ 12139 => '皿',
+ 12140 => '目',
+ 12141 => '矛',
+ 12142 => '矢',
+ 12143 => '石',
+ 12144 => '示',
+ 12145 => '禸',
+ 12146 => '禾',
+ 12147 => '穴',
+ 12148 => '立',
+ 12149 => '竹',
+ 12150 => '米',
+ 12151 => '糸',
+ 12152 => '缶',
+ 12153 => '网',
+ 12154 => '羊',
+ 12155 => '羽',
+ 12156 => '老',
+ 12157 => '而',
+ 12158 => '耒',
+ 12159 => '耳',
+ 12160 => '聿',
+ 12161 => '肉',
+ 12162 => '臣',
+ 12163 => '自',
+ 12164 => '至',
+ 12165 => '臼',
+ 12166 => '舌',
+ 12167 => '舛',
+ 12168 => '舟',
+ 12169 => '艮',
+ 12170 => '色',
+ 12171 => '艸',
+ 12172 => '虍',
+ 12173 => '虫',
+ 12174 => '血',
+ 12175 => '行',
+ 12176 => '衣',
+ 12177 => '襾',
+ 12178 => '見',
+ 12179 => '角',
+ 12180 => '言',
+ 12181 => '谷',
+ 12182 => '豆',
+ 12183 => '豕',
+ 12184 => '豸',
+ 12185 => '貝',
+ 12186 => '赤',
+ 12187 => '走',
+ 12188 => '足',
+ 12189 => '身',
+ 12190 => '車',
+ 12191 => '辛',
+ 12192 => '辰',
+ 12193 => '辵',
+ 12194 => '邑',
+ 12195 => '酉',
+ 12196 => '釆',
+ 12197 => '里',
+ 12198 => '金',
+ 12199 => '長',
+ 12200 => '門',
+ 12201 => '阜',
+ 12202 => '隶',
+ 12203 => '隹',
+ 12204 => '雨',
+ 12205 => '靑',
+ 12206 => '非',
+ 12207 => '面',
+ 12208 => '革',
+ 12209 => '韋',
+ 12210 => '韭',
+ 12211 => '音',
+ 12212 => '頁',
+ 12213 => '風',
+ 12214 => '飛',
+ 12215 => '食',
+ 12216 => '首',
+ 12217 => '香',
+ 12218 => '馬',
+ 12219 => '骨',
+ 12220 => '高',
+ 12221 => '髟',
+ 12222 => '鬥',
+ 12223 => '鬯',
+ 12224 => '鬲',
+ 12225 => '鬼',
+ 12226 => '魚',
+ 12227 => '鳥',
+ 12228 => '鹵',
+ 12229 => '鹿',
+ 12230 => '麥',
+ 12231 => '麻',
+ 12232 => '黃',
+ 12233 => '黍',
+ 12234 => '黑',
+ 12235 => '黹',
+ 12236 => '黽',
+ 12237 => '鼎',
+ 12238 => '鼓',
+ 12239 => '鼠',
+ 12240 => '鼻',
+ 12241 => '齊',
+ 12242 => '齒',
+ 12243 => '龍',
+ 12244 => '龜',
+ 12245 => '龠',
+ 12290 => '.',
+ 12342 => '〒',
+ 12344 => '十',
+ 12345 => '卄',
+ 12346 => '卅',
+ 12447 => 'より',
+ 12543 => 'コト',
+ 12593 => 'ᄀ',
+ 12594 => 'ᄁ',
+ 12595 => 'ᆪ',
+ 12596 => 'ᄂ',
+ 12597 => 'ᆬ',
+ 12598 => 'ᆭ',
+ 12599 => 'ᄃ',
+ 12600 => 'ᄄ',
+ 12601 => 'ᄅ',
+ 12602 => 'ᆰ',
+ 12603 => 'ᆱ',
+ 12604 => 'ᆲ',
+ 12605 => 'ᆳ',
+ 12606 => 'ᆴ',
+ 12607 => 'ᆵ',
+ 12608 => 'ᄚ',
+ 12609 => 'ᄆ',
+ 12610 => 'ᄇ',
+ 12611 => 'ᄈ',
+ 12612 => 'ᄡ',
+ 12613 => 'ᄉ',
+ 12614 => 'ᄊ',
+ 12615 => 'ᄋ',
+ 12616 => 'ᄌ',
+ 12617 => 'ᄍ',
+ 12618 => 'ᄎ',
+ 12619 => 'ᄏ',
+ 12620 => 'ᄐ',
+ 12621 => 'ᄑ',
+ 12622 => 'ᄒ',
+ 12623 => 'ᅡ',
+ 12624 => 'ᅢ',
+ 12625 => 'ᅣ',
+ 12626 => 'ᅤ',
+ 12627 => 'ᅥ',
+ 12628 => 'ᅦ',
+ 12629 => 'ᅧ',
+ 12630 => 'ᅨ',
+ 12631 => 'ᅩ',
+ 12632 => 'ᅪ',
+ 12633 => 'ᅫ',
+ 12634 => 'ᅬ',
+ 12635 => 'ᅭ',
+ 12636 => 'ᅮ',
+ 12637 => 'ᅯ',
+ 12638 => 'ᅰ',
+ 12639 => 'ᅱ',
+ 12640 => 'ᅲ',
+ 12641 => 'ᅳ',
+ 12642 => 'ᅴ',
+ 12643 => 'ᅵ',
+ 12645 => 'ᄔ',
+ 12646 => 'ᄕ',
+ 12647 => 'ᇇ',
+ 12648 => 'ᇈ',
+ 12649 => 'ᇌ',
+ 12650 => 'ᇎ',
+ 12651 => 'ᇓ',
+ 12652 => 'ᇗ',
+ 12653 => 'ᇙ',
+ 12654 => 'ᄜ',
+ 12655 => 'ᇝ',
+ 12656 => 'ᇟ',
+ 12657 => 'ᄝ',
+ 12658 => 'ᄞ',
+ 12659 => 'ᄠ',
+ 12660 => 'ᄢ',
+ 12661 => 'ᄣ',
+ 12662 => 'ᄧ',
+ 12663 => 'ᄩ',
+ 12664 => 'ᄫ',
+ 12665 => 'ᄬ',
+ 12666 => 'ᄭ',
+ 12667 => 'ᄮ',
+ 12668 => 'ᄯ',
+ 12669 => 'ᄲ',
+ 12670 => 'ᄶ',
+ 12671 => 'ᅀ',
+ 12672 => 'ᅇ',
+ 12673 => 'ᅌ',
+ 12674 => 'ᇱ',
+ 12675 => 'ᇲ',
+ 12676 => 'ᅗ',
+ 12677 => 'ᅘ',
+ 12678 => 'ᅙ',
+ 12679 => 'ᆄ',
+ 12680 => 'ᆅ',
+ 12681 => 'ᆈ',
+ 12682 => 'ᆑ',
+ 12683 => 'ᆒ',
+ 12684 => 'ᆔ',
+ 12685 => 'ᆞ',
+ 12686 => 'ᆡ',
+ 12690 => '一',
+ 12691 => '二',
+ 12692 => '三',
+ 12693 => '四',
+ 12694 => '上',
+ 12695 => '中',
+ 12696 => '下',
+ 12697 => '甲',
+ 12698 => '乙',
+ 12699 => '丙',
+ 12700 => '丁',
+ 12701 => '天',
+ 12702 => '地',
+ 12703 => '人',
+ 12868 => '問',
+ 12869 => '幼',
+ 12870 => '文',
+ 12871 => '箏',
+ 12880 => 'pte',
+ 12881 => '21',
+ 12882 => '22',
+ 12883 => '23',
+ 12884 => '24',
+ 12885 => '25',
+ 12886 => '26',
+ 12887 => '27',
+ 12888 => '28',
+ 12889 => '29',
+ 12890 => '30',
+ 12891 => '31',
+ 12892 => '32',
+ 12893 => '33',
+ 12894 => '34',
+ 12895 => '35',
+ 12896 => 'ᄀ',
+ 12897 => 'ᄂ',
+ 12898 => 'ᄃ',
+ 12899 => 'ᄅ',
+ 12900 => 'ᄆ',
+ 12901 => 'ᄇ',
+ 12902 => 'ᄉ',
+ 12903 => 'ᄋ',
+ 12904 => 'ᄌ',
+ 12905 => 'ᄎ',
+ 12906 => 'ᄏ',
+ 12907 => 'ᄐ',
+ 12908 => 'ᄑ',
+ 12909 => 'ᄒ',
+ 12910 => '가',
+ 12911 => '나',
+ 12912 => '다',
+ 12913 => '라',
+ 12914 => '마',
+ 12915 => '바',
+ 12916 => '사',
+ 12917 => '아',
+ 12918 => '자',
+ 12919 => '차',
+ 12920 => '카',
+ 12921 => '타',
+ 12922 => '파',
+ 12923 => '하',
+ 12924 => '참고',
+ 12925 => '주의',
+ 12926 => '우',
+ 12928 => '一',
+ 12929 => '二',
+ 12930 => '三',
+ 12931 => '四',
+ 12932 => '五',
+ 12933 => '六',
+ 12934 => '七',
+ 12935 => '八',
+ 12936 => '九',
+ 12937 => '十',
+ 12938 => '月',
+ 12939 => '火',
+ 12940 => '水',
+ 12941 => '木',
+ 12942 => '金',
+ 12943 => '土',
+ 12944 => '日',
+ 12945 => '株',
+ 12946 => '有',
+ 12947 => '社',
+ 12948 => '名',
+ 12949 => '特',
+ 12950 => '財',
+ 12951 => '祝',
+ 12952 => '労',
+ 12953 => '秘',
+ 12954 => '男',
+ 12955 => '女',
+ 12956 => '適',
+ 12957 => '優',
+ 12958 => '印',
+ 12959 => '注',
+ 12960 => '項',
+ 12961 => '休',
+ 12962 => '写',
+ 12963 => '正',
+ 12964 => '上',
+ 12965 => '中',
+ 12966 => '下',
+ 12967 => '左',
+ 12968 => '右',
+ 12969 => '医',
+ 12970 => '宗',
+ 12971 => '学',
+ 12972 => '監',
+ 12973 => '企',
+ 12974 => '資',
+ 12975 => '協',
+ 12976 => '夜',
+ 12977 => '36',
+ 12978 => '37',
+ 12979 => '38',
+ 12980 => '39',
+ 12981 => '40',
+ 12982 => '41',
+ 12983 => '42',
+ 12984 => '43',
+ 12985 => '44',
+ 12986 => '45',
+ 12987 => '46',
+ 12988 => '47',
+ 12989 => '48',
+ 12990 => '49',
+ 12991 => '50',
+ 12992 => '1月',
+ 12993 => '2月',
+ 12994 => '3月',
+ 12995 => '4月',
+ 12996 => '5月',
+ 12997 => '6月',
+ 12998 => '7月',
+ 12999 => '8月',
+ 13000 => '9月',
+ 13001 => '10月',
+ 13002 => '11月',
+ 13003 => '12月',
+ 13004 => 'hg',
+ 13005 => 'erg',
+ 13006 => 'ev',
+ 13007 => 'ltd',
+ 13008 => 'ア',
+ 13009 => 'イ',
+ 13010 => 'ウ',
+ 13011 => 'エ',
+ 13012 => 'オ',
+ 13013 => 'カ',
+ 13014 => 'キ',
+ 13015 => 'ク',
+ 13016 => 'ケ',
+ 13017 => 'コ',
+ 13018 => 'サ',
+ 13019 => 'シ',
+ 13020 => 'ス',
+ 13021 => 'セ',
+ 13022 => 'ソ',
+ 13023 => 'タ',
+ 13024 => 'チ',
+ 13025 => 'ツ',
+ 13026 => 'テ',
+ 13027 => 'ト',
+ 13028 => 'ナ',
+ 13029 => 'ニ',
+ 13030 => 'ヌ',
+ 13031 => 'ネ',
+ 13032 => 'ノ',
+ 13033 => 'ハ',
+ 13034 => 'ヒ',
+ 13035 => 'フ',
+ 13036 => 'ヘ',
+ 13037 => 'ホ',
+ 13038 => 'マ',
+ 13039 => 'ミ',
+ 13040 => 'ム',
+ 13041 => 'メ',
+ 13042 => 'モ',
+ 13043 => 'ヤ',
+ 13044 => 'ユ',
+ 13045 => 'ヨ',
+ 13046 => 'ラ',
+ 13047 => 'リ',
+ 13048 => 'ル',
+ 13049 => 'レ',
+ 13050 => 'ロ',
+ 13051 => 'ワ',
+ 13052 => 'ヰ',
+ 13053 => 'ヱ',
+ 13054 => 'ヲ',
+ 13055 => '令和',
+ 13056 => 'アパート',
+ 13057 => 'アルファ',
+ 13058 => 'アンペア',
+ 13059 => 'アール',
+ 13060 => 'イニング',
+ 13061 => 'インチ',
+ 13062 => 'ウォン',
+ 13063 => 'エスクード',
+ 13064 => 'エーカー',
+ 13065 => 'オンス',
+ 13066 => 'オーム',
+ 13067 => 'カイリ',
+ 13068 => 'カラット',
+ 13069 => 'カロリー',
+ 13070 => 'ガロン',
+ 13071 => 'ガンマ',
+ 13072 => 'ギガ',
+ 13073 => 'ギニー',
+ 13074 => 'キュリー',
+ 13075 => 'ギルダー',
+ 13076 => 'キロ',
+ 13077 => 'キログラム',
+ 13078 => 'キロメートル',
+ 13079 => 'キロワット',
+ 13080 => 'グラム',
+ 13081 => 'グラムトン',
+ 13082 => 'クルゼイロ',
+ 13083 => 'クローネ',
+ 13084 => 'ケース',
+ 13085 => 'コルナ',
+ 13086 => 'コーポ',
+ 13087 => 'サイクル',
+ 13088 => 'サンチーム',
+ 13089 => 'シリング',
+ 13090 => 'センチ',
+ 13091 => 'セント',
+ 13092 => 'ダース',
+ 13093 => 'デシ',
+ 13094 => 'ドル',
+ 13095 => 'トン',
+ 13096 => 'ナノ',
+ 13097 => 'ノット',
+ 13098 => 'ハイツ',
+ 13099 => 'パーセント',
+ 13100 => 'パーツ',
+ 13101 => 'バーレル',
+ 13102 => 'ピアストル',
+ 13103 => 'ピクル',
+ 13104 => 'ピコ',
+ 13105 => 'ビル',
+ 13106 => 'ファラッド',
+ 13107 => 'フィート',
+ 13108 => 'ブッシェル',
+ 13109 => 'フラン',
+ 13110 => 'ヘクタール',
+ 13111 => 'ペソ',
+ 13112 => 'ペニヒ',
+ 13113 => 'ヘルツ',
+ 13114 => 'ペンス',
+ 13115 => 'ページ',
+ 13116 => 'ベータ',
+ 13117 => 'ポイント',
+ 13118 => 'ボルト',
+ 13119 => 'ホン',
+ 13120 => 'ポンド',
+ 13121 => 'ホール',
+ 13122 => 'ホーン',
+ 13123 => 'マイクロ',
+ 13124 => 'マイル',
+ 13125 => 'マッハ',
+ 13126 => 'マルク',
+ 13127 => 'マンション',
+ 13128 => 'ミクロン',
+ 13129 => 'ミリ',
+ 13130 => 'ミリバール',
+ 13131 => 'メガ',
+ 13132 => 'メガトン',
+ 13133 => 'メートル',
+ 13134 => 'ヤード',
+ 13135 => 'ヤール',
+ 13136 => 'ユアン',
+ 13137 => 'リットル',
+ 13138 => 'リラ',
+ 13139 => 'ルピー',
+ 13140 => 'ルーブル',
+ 13141 => 'レム',
+ 13142 => 'レントゲン',
+ 13143 => 'ワット',
+ 13144 => '0点',
+ 13145 => '1点',
+ 13146 => '2点',
+ 13147 => '3点',
+ 13148 => '4点',
+ 13149 => '5点',
+ 13150 => '6点',
+ 13151 => '7点',
+ 13152 => '8点',
+ 13153 => '9点',
+ 13154 => '10点',
+ 13155 => '11点',
+ 13156 => '12点',
+ 13157 => '13点',
+ 13158 => '14点',
+ 13159 => '15点',
+ 13160 => '16点',
+ 13161 => '17点',
+ 13162 => '18点',
+ 13163 => '19点',
+ 13164 => '20点',
+ 13165 => '21点',
+ 13166 => '22点',
+ 13167 => '23点',
+ 13168 => '24点',
+ 13169 => 'hpa',
+ 13170 => 'da',
+ 13171 => 'au',
+ 13172 => 'bar',
+ 13173 => 'ov',
+ 13174 => 'pc',
+ 13175 => 'dm',
+ 13176 => 'dm2',
+ 13177 => 'dm3',
+ 13178 => 'iu',
+ 13179 => '平成',
+ 13180 => '昭和',
+ 13181 => '大正',
+ 13182 => '明治',
+ 13183 => '株式会社',
+ 13184 => 'pa',
+ 13185 => 'na',
+ 13186 => 'μa',
+ 13187 => 'ma',
+ 13188 => 'ka',
+ 13189 => 'kb',
+ 13190 => 'mb',
+ 13191 => 'gb',
+ 13192 => 'cal',
+ 13193 => 'kcal',
+ 13194 => 'pf',
+ 13195 => 'nf',
+ 13196 => 'μf',
+ 13197 => 'μg',
+ 13198 => 'mg',
+ 13199 => 'kg',
+ 13200 => 'hz',
+ 13201 => 'khz',
+ 13202 => 'mhz',
+ 13203 => 'ghz',
+ 13204 => 'thz',
+ 13205 => 'μl',
+ 13206 => 'ml',
+ 13207 => 'dl',
+ 13208 => 'kl',
+ 13209 => 'fm',
+ 13210 => 'nm',
+ 13211 => 'μm',
+ 13212 => 'mm',
+ 13213 => 'cm',
+ 13214 => 'km',
+ 13215 => 'mm2',
+ 13216 => 'cm2',
+ 13217 => 'm2',
+ 13218 => 'km2',
+ 13219 => 'mm3',
+ 13220 => 'cm3',
+ 13221 => 'm3',
+ 13222 => 'km3',
+ 13223 => 'm∕s',
+ 13224 => 'm∕s2',
+ 13225 => 'pa',
+ 13226 => 'kpa',
+ 13227 => 'mpa',
+ 13228 => 'gpa',
+ 13229 => 'rad',
+ 13230 => 'rad∕s',
+ 13231 => 'rad∕s2',
+ 13232 => 'ps',
+ 13233 => 'ns',
+ 13234 => 'μs',
+ 13235 => 'ms',
+ 13236 => 'pv',
+ 13237 => 'nv',
+ 13238 => 'μv',
+ 13239 => 'mv',
+ 13240 => 'kv',
+ 13241 => 'mv',
+ 13242 => 'pw',
+ 13243 => 'nw',
+ 13244 => 'μw',
+ 13245 => 'mw',
+ 13246 => 'kw',
+ 13247 => 'mw',
+ 13248 => 'kω',
+ 13249 => 'mω',
+ 13251 => 'bq',
+ 13252 => 'cc',
+ 13253 => 'cd',
+ 13254 => 'c∕kg',
+ 13256 => 'db',
+ 13257 => 'gy',
+ 13258 => 'ha',
+ 13259 => 'hp',
+ 13260 => 'in',
+ 13261 => 'kk',
+ 13262 => 'km',
+ 13263 => 'kt',
+ 13264 => 'lm',
+ 13265 => 'ln',
+ 13266 => 'log',
+ 13267 => 'lx',
+ 13268 => 'mb',
+ 13269 => 'mil',
+ 13270 => 'mol',
+ 13271 => 'ph',
+ 13273 => 'ppm',
+ 13274 => 'pr',
+ 13275 => 'sr',
+ 13276 => 'sv',
+ 13277 => 'wb',
+ 13278 => 'v∕m',
+ 13279 => 'a∕m',
+ 13280 => '1日',
+ 13281 => '2日',
+ 13282 => '3日',
+ 13283 => '4日',
+ 13284 => '5日',
+ 13285 => '6日',
+ 13286 => '7日',
+ 13287 => '8日',
+ 13288 => '9日',
+ 13289 => '10日',
+ 13290 => '11日',
+ 13291 => '12日',
+ 13292 => '13日',
+ 13293 => '14日',
+ 13294 => '15日',
+ 13295 => '16日',
+ 13296 => '17日',
+ 13297 => '18日',
+ 13298 => '19日',
+ 13299 => '20日',
+ 13300 => '21日',
+ 13301 => '22日',
+ 13302 => '23日',
+ 13303 => '24日',
+ 13304 => '25日',
+ 13305 => '26日',
+ 13306 => '27日',
+ 13307 => '28日',
+ 13308 => '29日',
+ 13309 => '30日',
+ 13310 => '31日',
+ 13311 => 'gal',
+ 42560 => 'ꙁ',
+ 42562 => 'ꙃ',
+ 42564 => 'ꙅ',
+ 42566 => 'ꙇ',
+ 42568 => 'ꙉ',
+ 42570 => 'ꙋ',
+ 42572 => 'ꙍ',
+ 42574 => 'ꙏ',
+ 42576 => 'ꙑ',
+ 42578 => 'ꙓ',
+ 42580 => 'ꙕ',
+ 42582 => 'ꙗ',
+ 42584 => 'ꙙ',
+ 42586 => 'ꙛ',
+ 42588 => 'ꙝ',
+ 42590 => 'ꙟ',
+ 42592 => 'ꙡ',
+ 42594 => 'ꙣ',
+ 42596 => 'ꙥ',
+ 42598 => 'ꙧ',
+ 42600 => 'ꙩ',
+ 42602 => 'ꙫ',
+ 42604 => 'ꙭ',
+ 42624 => 'ꚁ',
+ 42626 => 'ꚃ',
+ 42628 => 'ꚅ',
+ 42630 => 'ꚇ',
+ 42632 => 'ꚉ',
+ 42634 => 'ꚋ',
+ 42636 => 'ꚍ',
+ 42638 => 'ꚏ',
+ 42640 => 'ꚑ',
+ 42642 => 'ꚓ',
+ 42644 => 'ꚕ',
+ 42646 => 'ꚗ',
+ 42648 => 'ꚙ',
+ 42650 => 'ꚛ',
+ 42652 => 'ъ',
+ 42653 => 'ь',
+ 42786 => 'ꜣ',
+ 42788 => 'ꜥ',
+ 42790 => 'ꜧ',
+ 42792 => 'ꜩ',
+ 42794 => 'ꜫ',
+ 42796 => 'ꜭ',
+ 42798 => 'ꜯ',
+ 42802 => 'ꜳ',
+ 42804 => 'ꜵ',
+ 42806 => 'ꜷ',
+ 42808 => 'ꜹ',
+ 42810 => 'ꜻ',
+ 42812 => 'ꜽ',
+ 42814 => 'ꜿ',
+ 42816 => 'ꝁ',
+ 42818 => 'ꝃ',
+ 42820 => 'ꝅ',
+ 42822 => 'ꝇ',
+ 42824 => 'ꝉ',
+ 42826 => 'ꝋ',
+ 42828 => 'ꝍ',
+ 42830 => 'ꝏ',
+ 42832 => 'ꝑ',
+ 42834 => 'ꝓ',
+ 42836 => 'ꝕ',
+ 42838 => 'ꝗ',
+ 42840 => 'ꝙ',
+ 42842 => 'ꝛ',
+ 42844 => 'ꝝ',
+ 42846 => 'ꝟ',
+ 42848 => 'ꝡ',
+ 42850 => 'ꝣ',
+ 42852 => 'ꝥ',
+ 42854 => 'ꝧ',
+ 42856 => 'ꝩ',
+ 42858 => 'ꝫ',
+ 42860 => 'ꝭ',
+ 42862 => 'ꝯ',
+ 42864 => 'ꝯ',
+ 42873 => 'ꝺ',
+ 42875 => 'ꝼ',
+ 42877 => 'ᵹ',
+ 42878 => 'ꝿ',
+ 42880 => 'ꞁ',
+ 42882 => 'ꞃ',
+ 42884 => 'ꞅ',
+ 42886 => 'ꞇ',
+ 42891 => 'ꞌ',
+ 42893 => 'ɥ',
+ 42896 => 'ꞑ',
+ 42898 => 'ꞓ',
+ 42902 => 'ꞗ',
+ 42904 => 'ꞙ',
+ 42906 => 'ꞛ',
+ 42908 => 'ꞝ',
+ 42910 => 'ꞟ',
+ 42912 => 'ꞡ',
+ 42914 => 'ꞣ',
+ 42916 => 'ꞥ',
+ 42918 => 'ꞧ',
+ 42920 => 'ꞩ',
+ 42922 => 'ɦ',
+ 42923 => 'ɜ',
+ 42924 => 'ɡ',
+ 42925 => 'ɬ',
+ 42926 => 'ɪ',
+ 42928 => 'ʞ',
+ 42929 => 'ʇ',
+ 42930 => 'ʝ',
+ 42931 => 'ꭓ',
+ 42932 => 'ꞵ',
+ 42934 => 'ꞷ',
+ 42936 => 'ꞹ',
+ 42938 => 'ꞻ',
+ 42940 => 'ꞽ',
+ 42942 => 'ꞿ',
+ 42946 => 'ꟃ',
+ 42948 => 'ꞔ',
+ 42949 => 'ʂ',
+ 42950 => 'ᶎ',
+ 42951 => 'ꟈ',
+ 42953 => 'ꟊ',
+ 42997 => 'ꟶ',
+ 43000 => 'ħ',
+ 43001 => 'œ',
+ 43868 => 'ꜧ',
+ 43869 => 'ꬷ',
+ 43870 => 'ɫ',
+ 43871 => 'ꭒ',
+ 43881 => 'ʍ',
+ 43888 => 'Ꭰ',
+ 43889 => 'Ꭱ',
+ 43890 => 'Ꭲ',
+ 43891 => 'Ꭳ',
+ 43892 => 'Ꭴ',
+ 43893 => 'Ꭵ',
+ 43894 => 'Ꭶ',
+ 43895 => 'Ꭷ',
+ 43896 => 'Ꭸ',
+ 43897 => 'Ꭹ',
+ 43898 => 'Ꭺ',
+ 43899 => 'Ꭻ',
+ 43900 => 'Ꭼ',
+ 43901 => 'Ꭽ',
+ 43902 => 'Ꭾ',
+ 43903 => 'Ꭿ',
+ 43904 => 'Ꮀ',
+ 43905 => 'Ꮁ',
+ 43906 => 'Ꮂ',
+ 43907 => 'Ꮃ',
+ 43908 => 'Ꮄ',
+ 43909 => 'Ꮅ',
+ 43910 => 'Ꮆ',
+ 43911 => 'Ꮇ',
+ 43912 => 'Ꮈ',
+ 43913 => 'Ꮉ',
+ 43914 => 'Ꮊ',
+ 43915 => 'Ꮋ',
+ 43916 => 'Ꮌ',
+ 43917 => 'Ꮍ',
+ 43918 => 'Ꮎ',
+ 43919 => 'Ꮏ',
+ 43920 => 'Ꮐ',
+ 43921 => 'Ꮑ',
+ 43922 => 'Ꮒ',
+ 43923 => 'Ꮓ',
+ 43924 => 'Ꮔ',
+ 43925 => 'Ꮕ',
+ 43926 => 'Ꮖ',
+ 43927 => 'Ꮗ',
+ 43928 => 'Ꮘ',
+ 43929 => 'Ꮙ',
+ 43930 => 'Ꮚ',
+ 43931 => 'Ꮛ',
+ 43932 => 'Ꮜ',
+ 43933 => 'Ꮝ',
+ 43934 => 'Ꮞ',
+ 43935 => 'Ꮟ',
+ 43936 => 'Ꮠ',
+ 43937 => 'Ꮡ',
+ 43938 => 'Ꮢ',
+ 43939 => 'Ꮣ',
+ 43940 => 'Ꮤ',
+ 43941 => 'Ꮥ',
+ 43942 => 'Ꮦ',
+ 43943 => 'Ꮧ',
+ 43944 => 'Ꮨ',
+ 43945 => 'Ꮩ',
+ 43946 => 'Ꮪ',
+ 43947 => 'Ꮫ',
+ 43948 => 'Ꮬ',
+ 43949 => 'Ꮭ',
+ 43950 => 'Ꮮ',
+ 43951 => 'Ꮯ',
+ 43952 => 'Ꮰ',
+ 43953 => 'Ꮱ',
+ 43954 => 'Ꮲ',
+ 43955 => 'Ꮳ',
+ 43956 => 'Ꮴ',
+ 43957 => 'Ꮵ',
+ 43958 => 'Ꮶ',
+ 43959 => 'Ꮷ',
+ 43960 => 'Ꮸ',
+ 43961 => 'Ꮹ',
+ 43962 => 'Ꮺ',
+ 43963 => 'Ꮻ',
+ 43964 => 'Ꮼ',
+ 43965 => 'Ꮽ',
+ 43966 => 'Ꮾ',
+ 43967 => 'Ꮿ',
+ 63744 => '豈',
+ 63745 => '更',
+ 63746 => '車',
+ 63747 => '賈',
+ 63748 => '滑',
+ 63749 => '串',
+ 63750 => '句',
+ 63751 => '龜',
+ 63752 => '龜',
+ 63753 => '契',
+ 63754 => '金',
+ 63755 => '喇',
+ 63756 => '奈',
+ 63757 => '懶',
+ 63758 => '癩',
+ 63759 => '羅',
+ 63760 => '蘿',
+ 63761 => '螺',
+ 63762 => '裸',
+ 63763 => '邏',
+ 63764 => '樂',
+ 63765 => '洛',
+ 63766 => '烙',
+ 63767 => '珞',
+ 63768 => '落',
+ 63769 => '酪',
+ 63770 => '駱',
+ 63771 => '亂',
+ 63772 => '卵',
+ 63773 => '欄',
+ 63774 => '爛',
+ 63775 => '蘭',
+ 63776 => '鸞',
+ 63777 => '嵐',
+ 63778 => '濫',
+ 63779 => '藍',
+ 63780 => '襤',
+ 63781 => '拉',
+ 63782 => '臘',
+ 63783 => '蠟',
+ 63784 => '廊',
+ 63785 => '朗',
+ 63786 => '浪',
+ 63787 => '狼',
+ 63788 => '郎',
+ 63789 => '來',
+ 63790 => '冷',
+ 63791 => '勞',
+ 63792 => '擄',
+ 63793 => '櫓',
+ 63794 => '爐',
+ 63795 => '盧',
+ 63796 => '老',
+ 63797 => '蘆',
+ 63798 => '虜',
+ 63799 => '路',
+ 63800 => '露',
+ 63801 => '魯',
+ 63802 => '鷺',
+ 63803 => '碌',
+ 63804 => '祿',
+ 63805 => '綠',
+ 63806 => '菉',
+ 63807 => '錄',
+ 63808 => '鹿',
+ 63809 => '論',
+ 63810 => '壟',
+ 63811 => '弄',
+ 63812 => '籠',
+ 63813 => '聾',
+ 63814 => '牢',
+ 63815 => '磊',
+ 63816 => '賂',
+ 63817 => '雷',
+ 63818 => '壘',
+ 63819 => '屢',
+ 63820 => '樓',
+ 63821 => '淚',
+ 63822 => '漏',
+ 63823 => '累',
+ 63824 => '縷',
+ 63825 => '陋',
+ 63826 => '勒',
+ 63827 => '肋',
+ 63828 => '凜',
+ 63829 => '凌',
+ 63830 => '稜',
+ 63831 => '綾',
+ 63832 => '菱',
+ 63833 => '陵',
+ 63834 => '讀',
+ 63835 => '拏',
+ 63836 => '樂',
+ 63837 => '諾',
+ 63838 => '丹',
+ 63839 => '寧',
+ 63840 => '怒',
+ 63841 => '率',
+ 63842 => '異',
+ 63843 => '北',
+ 63844 => '磻',
+ 63845 => '便',
+ 63846 => '復',
+ 63847 => '不',
+ 63848 => '泌',
+ 63849 => '數',
+ 63850 => '索',
+ 63851 => '參',
+ 63852 => '塞',
+ 63853 => '省',
+ 63854 => '葉',
+ 63855 => '說',
+ 63856 => '殺',
+ 63857 => '辰',
+ 63858 => '沈',
+ 63859 => '拾',
+ 63860 => '若',
+ 63861 => '掠',
+ 63862 => '略',
+ 63863 => '亮',
+ 63864 => '兩',
+ 63865 => '凉',
+ 63866 => '梁',
+ 63867 => '糧',
+ 63868 => '良',
+ 63869 => '諒',
+ 63870 => '量',
+ 63871 => '勵',
+ 63872 => '呂',
+ 63873 => '女',
+ 63874 => '廬',
+ 63875 => '旅',
+ 63876 => '濾',
+ 63877 => '礪',
+ 63878 => '閭',
+ 63879 => '驪',
+ 63880 => '麗',
+ 63881 => '黎',
+ 63882 => '力',
+ 63883 => '曆',
+ 63884 => '歷',
+ 63885 => '轢',
+ 63886 => '年',
+ 63887 => '憐',
+ 63888 => '戀',
+ 63889 => '撚',
+ 63890 => '漣',
+ 63891 => '煉',
+ 63892 => '璉',
+ 63893 => '秊',
+ 63894 => '練',
+ 63895 => '聯',
+ 63896 => '輦',
+ 63897 => '蓮',
+ 63898 => '連',
+ 63899 => '鍊',
+ 63900 => '列',
+ 63901 => '劣',
+ 63902 => '咽',
+ 63903 => '烈',
+ 63904 => '裂',
+ 63905 => '說',
+ 63906 => '廉',
+ 63907 => '念',
+ 63908 => '捻',
+ 63909 => '殮',
+ 63910 => '簾',
+ 63911 => '獵',
+ 63912 => '令',
+ 63913 => '囹',
+ 63914 => '寧',
+ 63915 => '嶺',
+ 63916 => '怜',
+ 63917 => '玲',
+ 63918 => '瑩',
+ 63919 => '羚',
+ 63920 => '聆',
+ 63921 => '鈴',
+ 63922 => '零',
+ 63923 => '靈',
+ 63924 => '領',
+ 63925 => '例',
+ 63926 => '禮',
+ 63927 => '醴',
+ 63928 => '隸',
+ 63929 => '惡',
+ 63930 => '了',
+ 63931 => '僚',
+ 63932 => '寮',
+ 63933 => '尿',
+ 63934 => '料',
+ 63935 => '樂',
+ 63936 => '燎',
+ 63937 => '療',
+ 63938 => '蓼',
+ 63939 => '遼',
+ 63940 => '龍',
+ 63941 => '暈',
+ 63942 => '阮',
+ 63943 => '劉',
+ 63944 => '杻',
+ 63945 => '柳',
+ 63946 => '流',
+ 63947 => '溜',
+ 63948 => '琉',
+ 63949 => '留',
+ 63950 => '硫',
+ 63951 => '紐',
+ 63952 => '類',
+ 63953 => '六',
+ 63954 => '戮',
+ 63955 => '陸',
+ 63956 => '倫',
+ 63957 => '崙',
+ 63958 => '淪',
+ 63959 => '輪',
+ 63960 => '律',
+ 63961 => '慄',
+ 63962 => '栗',
+ 63963 => '率',
+ 63964 => '隆',
+ 63965 => '利',
+ 63966 => '吏',
+ 63967 => '履',
+ 63968 => '易',
+ 63969 => '李',
+ 63970 => '梨',
+ 63971 => '泥',
+ 63972 => '理',
+ 63973 => '痢',
+ 63974 => '罹',
+ 63975 => '裏',
+ 63976 => '裡',
+ 63977 => '里',
+ 63978 => '離',
+ 63979 => '匿',
+ 63980 => '溺',
+ 63981 => '吝',
+ 63982 => '燐',
+ 63983 => '璘',
+ 63984 => '藺',
+ 63985 => '隣',
+ 63986 => '鱗',
+ 63987 => '麟',
+ 63988 => '林',
+ 63989 => '淋',
+ 63990 => '臨',
+ 63991 => '立',
+ 63992 => '笠',
+ 63993 => '粒',
+ 63994 => '狀',
+ 63995 => '炙',
+ 63996 => '識',
+ 63997 => '什',
+ 63998 => '茶',
+ 63999 => '刺',
+ 64000 => '切',
+ 64001 => '度',
+ 64002 => '拓',
+ 64003 => '糖',
+ 64004 => '宅',
+ 64005 => '洞',
+ 64006 => '暴',
+ 64007 => '輻',
+ 64008 => '行',
+ 64009 => '降',
+ 64010 => '見',
+ 64011 => '廓',
+ 64012 => '兀',
+ 64013 => '嗀',
+ 64016 => '塚',
+ 64018 => '晴',
+ 64021 => '凞',
+ 64022 => '猪',
+ 64023 => '益',
+ 64024 => '礼',
+ 64025 => '神',
+ 64026 => '祥',
+ 64027 => '福',
+ 64028 => '靖',
+ 64029 => '精',
+ 64030 => '羽',
+ 64032 => '蘒',
+ 64034 => '諸',
+ 64037 => '逸',
+ 64038 => '都',
+ 64042 => '飯',
+ 64043 => '飼',
+ 64044 => '館',
+ 64045 => '鶴',
+ 64046 => '郞',
+ 64047 => '隷',
+ 64048 => '侮',
+ 64049 => '僧',
+ 64050 => '免',
+ 64051 => '勉',
+ 64052 => '勤',
+ 64053 => '卑',
+ 64054 => '喝',
+ 64055 => '嘆',
+ 64056 => '器',
+ 64057 => '塀',
+ 64058 => '墨',
+ 64059 => '層',
+ 64060 => '屮',
+ 64061 => '悔',
+ 64062 => '慨',
+ 64063 => '憎',
+ 64064 => '懲',
+ 64065 => '敏',
+ 64066 => '既',
+ 64067 => '暑',
+ 64068 => '梅',
+ 64069 => '海',
+ 64070 => '渚',
+ 64071 => '漢',
+ 64072 => '煮',
+ 64073 => '爫',
+ 64074 => '琢',
+ 64075 => '碑',
+ 64076 => '社',
+ 64077 => '祉',
+ 64078 => '祈',
+ 64079 => '祐',
+ 64080 => '祖',
+ 64081 => '祝',
+ 64082 => '禍',
+ 64083 => '禎',
+ 64084 => '穀',
+ 64085 => '突',
+ 64086 => '節',
+ 64087 => '練',
+ 64088 => '縉',
+ 64089 => '繁',
+ 64090 => '署',
+ 64091 => '者',
+ 64092 => '臭',
+ 64093 => '艹',
+ 64094 => '艹',
+ 64095 => '著',
+ 64096 => '褐',
+ 64097 => '視',
+ 64098 => '謁',
+ 64099 => '謹',
+ 64100 => '賓',
+ 64101 => '贈',
+ 64102 => '辶',
+ 64103 => '逸',
+ 64104 => '難',
+ 64105 => '響',
+ 64106 => '頻',
+ 64107 => '恵',
+ 64108 => '𤋮',
+ 64109 => '舘',
+ 64112 => '並',
+ 64113 => '况',
+ 64114 => '全',
+ 64115 => '侀',
+ 64116 => '充',
+ 64117 => '冀',
+ 64118 => '勇',
+ 64119 => '勺',
+ 64120 => '喝',
+ 64121 => '啕',
+ 64122 => '喙',
+ 64123 => '嗢',
+ 64124 => '塚',
+ 64125 => '墳',
+ 64126 => '奄',
+ 64127 => '奔',
+ 64128 => '婢',
+ 64129 => '嬨',
+ 64130 => '廒',
+ 64131 => '廙',
+ 64132 => '彩',
+ 64133 => '徭',
+ 64134 => '惘',
+ 64135 => '慎',
+ 64136 => '愈',
+ 64137 => '憎',
+ 64138 => '慠',
+ 64139 => '懲',
+ 64140 => '戴',
+ 64141 => '揄',
+ 64142 => '搜',
+ 64143 => '摒',
+ 64144 => '敖',
+ 64145 => '晴',
+ 64146 => '朗',
+ 64147 => '望',
+ 64148 => '杖',
+ 64149 => '歹',
+ 64150 => '殺',
+ 64151 => '流',
+ 64152 => '滛',
+ 64153 => '滋',
+ 64154 => '漢',
+ 64155 => '瀞',
+ 64156 => '煮',
+ 64157 => '瞧',
+ 64158 => '爵',
+ 64159 => '犯',
+ 64160 => '猪',
+ 64161 => '瑱',
+ 64162 => '甆',
+ 64163 => '画',
+ 64164 => '瘝',
+ 64165 => '瘟',
+ 64166 => '益',
+ 64167 => '盛',
+ 64168 => '直',
+ 64169 => '睊',
+ 64170 => '着',
+ 64171 => '磌',
+ 64172 => '窱',
+ 64173 => '節',
+ 64174 => '类',
+ 64175 => '絛',
+ 64176 => '練',
+ 64177 => '缾',
+ 64178 => '者',
+ 64179 => '荒',
+ 64180 => '華',
+ 64181 => '蝹',
+ 64182 => '襁',
+ 64183 => '覆',
+ 64184 => '視',
+ 64185 => '調',
+ 64186 => '諸',
+ 64187 => '請',
+ 64188 => '謁',
+ 64189 => '諾',
+ 64190 => '諭',
+ 64191 => '謹',
+ 64192 => '變',
+ 64193 => '贈',
+ 64194 => '輸',
+ 64195 => '遲',
+ 64196 => '醙',
+ 64197 => '鉶',
+ 64198 => '陼',
+ 64199 => '難',
+ 64200 => '靖',
+ 64201 => '韛',
+ 64202 => '響',
+ 64203 => '頋',
+ 64204 => '頻',
+ 64205 => '鬒',
+ 64206 => '龜',
+ 64207 => '𢡊',
+ 64208 => '𢡄',
+ 64209 => '𣏕',
+ 64210 => '㮝',
+ 64211 => '䀘',
+ 64212 => '䀹',
+ 64213 => '𥉉',
+ 64214 => '𥳐',
+ 64215 => '𧻓',
+ 64216 => '齃',
+ 64217 => '龎',
+ 64256 => 'ff',
+ 64257 => 'fi',
+ 64258 => 'fl',
+ 64259 => 'ffi',
+ 64260 => 'ffl',
+ 64261 => 'st',
+ 64262 => 'st',
+ 64275 => 'մն',
+ 64276 => 'մե',
+ 64277 => 'մի',
+ 64278 => 'վն',
+ 64279 => 'մխ',
+ 64285 => 'יִ',
+ 64287 => 'ײַ',
+ 64288 => 'ע',
+ 64289 => 'א',
+ 64290 => 'ד',
+ 64291 => 'ה',
+ 64292 => 'כ',
+ 64293 => 'ל',
+ 64294 => 'ם',
+ 64295 => 'ר',
+ 64296 => 'ת',
+ 64298 => 'שׁ',
+ 64299 => 'שׂ',
+ 64300 => 'שּׁ',
+ 64301 => 'שּׂ',
+ 64302 => 'אַ',
+ 64303 => 'אָ',
+ 64304 => 'אּ',
+ 64305 => 'בּ',
+ 64306 => 'גּ',
+ 64307 => 'דּ',
+ 64308 => 'הּ',
+ 64309 => 'וּ',
+ 64310 => 'זּ',
+ 64312 => 'טּ',
+ 64313 => 'יּ',
+ 64314 => 'ךּ',
+ 64315 => 'כּ',
+ 64316 => 'לּ',
+ 64318 => 'מּ',
+ 64320 => 'נּ',
+ 64321 => 'סּ',
+ 64323 => 'ףּ',
+ 64324 => 'פּ',
+ 64326 => 'צּ',
+ 64327 => 'קּ',
+ 64328 => 'רּ',
+ 64329 => 'שּ',
+ 64330 => 'תּ',
+ 64331 => 'וֹ',
+ 64332 => 'בֿ',
+ 64333 => 'כֿ',
+ 64334 => 'פֿ',
+ 64335 => 'אל',
+ 64336 => 'ٱ',
+ 64337 => 'ٱ',
+ 64338 => 'ٻ',
+ 64339 => 'ٻ',
+ 64340 => 'ٻ',
+ 64341 => 'ٻ',
+ 64342 => 'پ',
+ 64343 => 'پ',
+ 64344 => 'پ',
+ 64345 => 'پ',
+ 64346 => 'ڀ',
+ 64347 => 'ڀ',
+ 64348 => 'ڀ',
+ 64349 => 'ڀ',
+ 64350 => 'ٺ',
+ 64351 => 'ٺ',
+ 64352 => 'ٺ',
+ 64353 => 'ٺ',
+ 64354 => 'ٿ',
+ 64355 => 'ٿ',
+ 64356 => 'ٿ',
+ 64357 => 'ٿ',
+ 64358 => 'ٹ',
+ 64359 => 'ٹ',
+ 64360 => 'ٹ',
+ 64361 => 'ٹ',
+ 64362 => 'ڤ',
+ 64363 => 'ڤ',
+ 64364 => 'ڤ',
+ 64365 => 'ڤ',
+ 64366 => 'ڦ',
+ 64367 => 'ڦ',
+ 64368 => 'ڦ',
+ 64369 => 'ڦ',
+ 64370 => 'ڄ',
+ 64371 => 'ڄ',
+ 64372 => 'ڄ',
+ 64373 => 'ڄ',
+ 64374 => 'ڃ',
+ 64375 => 'ڃ',
+ 64376 => 'ڃ',
+ 64377 => 'ڃ',
+ 64378 => 'چ',
+ 64379 => 'چ',
+ 64380 => 'چ',
+ 64381 => 'چ',
+ 64382 => 'ڇ',
+ 64383 => 'ڇ',
+ 64384 => 'ڇ',
+ 64385 => 'ڇ',
+ 64386 => 'ڍ',
+ 64387 => 'ڍ',
+ 64388 => 'ڌ',
+ 64389 => 'ڌ',
+ 64390 => 'ڎ',
+ 64391 => 'ڎ',
+ 64392 => 'ڈ',
+ 64393 => 'ڈ',
+ 64394 => 'ژ',
+ 64395 => 'ژ',
+ 64396 => 'ڑ',
+ 64397 => 'ڑ',
+ 64398 => 'ک',
+ 64399 => 'ک',
+ 64400 => 'ک',
+ 64401 => 'ک',
+ 64402 => 'گ',
+ 64403 => 'گ',
+ 64404 => 'گ',
+ 64405 => 'گ',
+ 64406 => 'ڳ',
+ 64407 => 'ڳ',
+ 64408 => 'ڳ',
+ 64409 => 'ڳ',
+ 64410 => 'ڱ',
+ 64411 => 'ڱ',
+ 64412 => 'ڱ',
+ 64413 => 'ڱ',
+ 64414 => 'ں',
+ 64415 => 'ں',
+ 64416 => 'ڻ',
+ 64417 => 'ڻ',
+ 64418 => 'ڻ',
+ 64419 => 'ڻ',
+ 64420 => 'ۀ',
+ 64421 => 'ۀ',
+ 64422 => 'ہ',
+ 64423 => 'ہ',
+ 64424 => 'ہ',
+ 64425 => 'ہ',
+ 64426 => 'ھ',
+ 64427 => 'ھ',
+ 64428 => 'ھ',
+ 64429 => 'ھ',
+ 64430 => 'ے',
+ 64431 => 'ے',
+ 64432 => 'ۓ',
+ 64433 => 'ۓ',
+ 64467 => 'ڭ',
+ 64468 => 'ڭ',
+ 64469 => 'ڭ',
+ 64470 => 'ڭ',
+ 64471 => 'ۇ',
+ 64472 => 'ۇ',
+ 64473 => 'ۆ',
+ 64474 => 'ۆ',
+ 64475 => 'ۈ',
+ 64476 => 'ۈ',
+ 64477 => 'ۇٴ',
+ 64478 => 'ۋ',
+ 64479 => 'ۋ',
+ 64480 => 'ۅ',
+ 64481 => 'ۅ',
+ 64482 => 'ۉ',
+ 64483 => 'ۉ',
+ 64484 => 'ې',
+ 64485 => 'ې',
+ 64486 => 'ې',
+ 64487 => 'ې',
+ 64488 => 'ى',
+ 64489 => 'ى',
+ 64490 => 'ئا',
+ 64491 => 'ئا',
+ 64492 => 'ئە',
+ 64493 => 'ئە',
+ 64494 => 'ئو',
+ 64495 => 'ئو',
+ 64496 => 'ئۇ',
+ 64497 => 'ئۇ',
+ 64498 => 'ئۆ',
+ 64499 => 'ئۆ',
+ 64500 => 'ئۈ',
+ 64501 => 'ئۈ',
+ 64502 => 'ئې',
+ 64503 => 'ئې',
+ 64504 => 'ئې',
+ 64505 => 'ئى',
+ 64506 => 'ئى',
+ 64507 => 'ئى',
+ 64508 => 'ی',
+ 64509 => 'ی',
+ 64510 => 'ی',
+ 64511 => 'ی',
+ 64512 => 'ئج',
+ 64513 => 'ئح',
+ 64514 => 'ئم',
+ 64515 => 'ئى',
+ 64516 => 'ئي',
+ 64517 => 'بج',
+ 64518 => 'بح',
+ 64519 => 'بخ',
+ 64520 => 'بم',
+ 64521 => 'بى',
+ 64522 => 'بي',
+ 64523 => 'تج',
+ 64524 => 'تح',
+ 64525 => 'تخ',
+ 64526 => 'تم',
+ 64527 => 'تى',
+ 64528 => 'تي',
+ 64529 => 'ثج',
+ 64530 => 'ثم',
+ 64531 => 'ثى',
+ 64532 => 'ثي',
+ 64533 => 'جح',
+ 64534 => 'جم',
+ 64535 => 'حج',
+ 64536 => 'حم',
+ 64537 => 'خج',
+ 64538 => 'خح',
+ 64539 => 'خم',
+ 64540 => 'سج',
+ 64541 => 'سح',
+ 64542 => 'سخ',
+ 64543 => 'سم',
+ 64544 => 'صح',
+ 64545 => 'صم',
+ 64546 => 'ضج',
+ 64547 => 'ضح',
+ 64548 => 'ضخ',
+ 64549 => 'ضم',
+ 64550 => 'طح',
+ 64551 => 'طم',
+ 64552 => 'ظم',
+ 64553 => 'عج',
+ 64554 => 'عم',
+ 64555 => 'غج',
+ 64556 => 'غم',
+ 64557 => 'فج',
+ 64558 => 'فح',
+ 64559 => 'فخ',
+ 64560 => 'فم',
+ 64561 => 'فى',
+ 64562 => 'في',
+ 64563 => 'قح',
+ 64564 => 'قم',
+ 64565 => 'قى',
+ 64566 => 'قي',
+ 64567 => 'كا',
+ 64568 => 'كج',
+ 64569 => 'كح',
+ 64570 => 'كخ',
+ 64571 => 'كل',
+ 64572 => 'كم',
+ 64573 => 'كى',
+ 64574 => 'كي',
+ 64575 => 'لج',
+ 64576 => 'لح',
+ 64577 => 'لخ',
+ 64578 => 'لم',
+ 64579 => 'لى',
+ 64580 => 'لي',
+ 64581 => 'مج',
+ 64582 => 'مح',
+ 64583 => 'مخ',
+ 64584 => 'مم',
+ 64585 => 'مى',
+ 64586 => 'مي',
+ 64587 => 'نج',
+ 64588 => 'نح',
+ 64589 => 'نخ',
+ 64590 => 'نم',
+ 64591 => 'نى',
+ 64592 => 'ني',
+ 64593 => 'هج',
+ 64594 => 'هم',
+ 64595 => 'هى',
+ 64596 => 'هي',
+ 64597 => 'يج',
+ 64598 => 'يح',
+ 64599 => 'يخ',
+ 64600 => 'يم',
+ 64601 => 'يى',
+ 64602 => 'يي',
+ 64603 => 'ذٰ',
+ 64604 => 'رٰ',
+ 64605 => 'ىٰ',
+ 64612 => 'ئر',
+ 64613 => 'ئز',
+ 64614 => 'ئم',
+ 64615 => 'ئن',
+ 64616 => 'ئى',
+ 64617 => 'ئي',
+ 64618 => 'بر',
+ 64619 => 'بز',
+ 64620 => 'بم',
+ 64621 => 'بن',
+ 64622 => 'بى',
+ 64623 => 'بي',
+ 64624 => 'تر',
+ 64625 => 'تز',
+ 64626 => 'تم',
+ 64627 => 'تن',
+ 64628 => 'تى',
+ 64629 => 'تي',
+ 64630 => 'ثر',
+ 64631 => 'ثز',
+ 64632 => 'ثم',
+ 64633 => 'ثن',
+ 64634 => 'ثى',
+ 64635 => 'ثي',
+ 64636 => 'فى',
+ 64637 => 'في',
+ 64638 => 'قى',
+ 64639 => 'قي',
+ 64640 => 'كا',
+ 64641 => 'كل',
+ 64642 => 'كم',
+ 64643 => 'كى',
+ 64644 => 'كي',
+ 64645 => 'لم',
+ 64646 => 'لى',
+ 64647 => 'لي',
+ 64648 => 'ما',
+ 64649 => 'مم',
+ 64650 => 'نر',
+ 64651 => 'نز',
+ 64652 => 'نم',
+ 64653 => 'نن',
+ 64654 => 'نى',
+ 64655 => 'ني',
+ 64656 => 'ىٰ',
+ 64657 => 'ير',
+ 64658 => 'يز',
+ 64659 => 'يم',
+ 64660 => 'ين',
+ 64661 => 'يى',
+ 64662 => 'يي',
+ 64663 => 'ئج',
+ 64664 => 'ئح',
+ 64665 => 'ئخ',
+ 64666 => 'ئم',
+ 64667 => 'ئه',
+ 64668 => 'بج',
+ 64669 => 'بح',
+ 64670 => 'بخ',
+ 64671 => 'بم',
+ 64672 => 'به',
+ 64673 => 'تج',
+ 64674 => 'تح',
+ 64675 => 'تخ',
+ 64676 => 'تم',
+ 64677 => 'ته',
+ 64678 => 'ثم',
+ 64679 => 'جح',
+ 64680 => 'جم',
+ 64681 => 'حج',
+ 64682 => 'حم',
+ 64683 => 'خج',
+ 64684 => 'خم',
+ 64685 => 'سج',
+ 64686 => 'سح',
+ 64687 => 'سخ',
+ 64688 => 'سم',
+ 64689 => 'صح',
+ 64690 => 'صخ',
+ 64691 => 'صم',
+ 64692 => 'ضج',
+ 64693 => 'ضح',
+ 64694 => 'ضخ',
+ 64695 => 'ضم',
+ 64696 => 'طح',
+ 64697 => 'ظم',
+ 64698 => 'عج',
+ 64699 => 'عم',
+ 64700 => 'غج',
+ 64701 => 'غم',
+ 64702 => 'فج',
+ 64703 => 'فح',
+ 64704 => 'فخ',
+ 64705 => 'فم',
+ 64706 => 'قح',
+ 64707 => 'قم',
+ 64708 => 'كج',
+ 64709 => 'كح',
+ 64710 => 'كخ',
+ 64711 => 'كل',
+ 64712 => 'كم',
+ 64713 => 'لج',
+ 64714 => 'لح',
+ 64715 => 'لخ',
+ 64716 => 'لم',
+ 64717 => 'له',
+ 64718 => 'مج',
+ 64719 => 'مح',
+ 64720 => 'مخ',
+ 64721 => 'مم',
+ 64722 => 'نج',
+ 64723 => 'نح',
+ 64724 => 'نخ',
+ 64725 => 'نم',
+ 64726 => 'نه',
+ 64727 => 'هج',
+ 64728 => 'هم',
+ 64729 => 'هٰ',
+ 64730 => 'يج',
+ 64731 => 'يح',
+ 64732 => 'يخ',
+ 64733 => 'يم',
+ 64734 => 'يه',
+ 64735 => 'ئم',
+ 64736 => 'ئه',
+ 64737 => 'بم',
+ 64738 => 'به',
+ 64739 => 'تم',
+ 64740 => 'ته',
+ 64741 => 'ثم',
+ 64742 => 'ثه',
+ 64743 => 'سم',
+ 64744 => 'سه',
+ 64745 => 'شم',
+ 64746 => 'شه',
+ 64747 => 'كل',
+ 64748 => 'كم',
+ 64749 => 'لم',
+ 64750 => 'نم',
+ 64751 => 'نه',
+ 64752 => 'يم',
+ 64753 => 'يه',
+ 64754 => 'ـَّ',
+ 64755 => 'ـُّ',
+ 64756 => 'ـِّ',
+ 64757 => 'طى',
+ 64758 => 'طي',
+ 64759 => 'عى',
+ 64760 => 'عي',
+ 64761 => 'غى',
+ 64762 => 'غي',
+ 64763 => 'سى',
+ 64764 => 'سي',
+ 64765 => 'شى',
+ 64766 => 'شي',
+ 64767 => 'حى',
+ 64768 => 'حي',
+ 64769 => 'جى',
+ 64770 => 'جي',
+ 64771 => 'خى',
+ 64772 => 'خي',
+ 64773 => 'صى',
+ 64774 => 'صي',
+ 64775 => 'ضى',
+ 64776 => 'ضي',
+ 64777 => 'شج',
+ 64778 => 'شح',
+ 64779 => 'شخ',
+ 64780 => 'شم',
+ 64781 => 'شر',
+ 64782 => 'سر',
+ 64783 => 'صر',
+ 64784 => 'ضر',
+ 64785 => 'طى',
+ 64786 => 'طي',
+ 64787 => 'عى',
+ 64788 => 'عي',
+ 64789 => 'غى',
+ 64790 => 'غي',
+ 64791 => 'سى',
+ 64792 => 'سي',
+ 64793 => 'شى',
+ 64794 => 'شي',
+ 64795 => 'حى',
+ 64796 => 'حي',
+ 64797 => 'جى',
+ 64798 => 'جي',
+ 64799 => 'خى',
+ 64800 => 'خي',
+ 64801 => 'صى',
+ 64802 => 'صي',
+ 64803 => 'ضى',
+ 64804 => 'ضي',
+ 64805 => 'شج',
+ 64806 => 'شح',
+ 64807 => 'شخ',
+ 64808 => 'شم',
+ 64809 => 'شر',
+ 64810 => 'سر',
+ 64811 => 'صر',
+ 64812 => 'ضر',
+ 64813 => 'شج',
+ 64814 => 'شح',
+ 64815 => 'شخ',
+ 64816 => 'شم',
+ 64817 => 'سه',
+ 64818 => 'شه',
+ 64819 => 'طم',
+ 64820 => 'سج',
+ 64821 => 'سح',
+ 64822 => 'سخ',
+ 64823 => 'شج',
+ 64824 => 'شح',
+ 64825 => 'شخ',
+ 64826 => 'طم',
+ 64827 => 'ظم',
+ 64828 => 'اً',
+ 64829 => 'اً',
+ 64848 => 'تجم',
+ 64849 => 'تحج',
+ 64850 => 'تحج',
+ 64851 => 'تحم',
+ 64852 => 'تخم',
+ 64853 => 'تمج',
+ 64854 => 'تمح',
+ 64855 => 'تمخ',
+ 64856 => 'جمح',
+ 64857 => 'جمح',
+ 64858 => 'حمي',
+ 64859 => 'حمى',
+ 64860 => 'سحج',
+ 64861 => 'سجح',
+ 64862 => 'سجى',
+ 64863 => 'سمح',
+ 64864 => 'سمح',
+ 64865 => 'سمج',
+ 64866 => 'سمم',
+ 64867 => 'سمم',
+ 64868 => 'صحح',
+ 64869 => 'صحح',
+ 64870 => 'صمم',
+ 64871 => 'شحم',
+ 64872 => 'شحم',
+ 64873 => 'شجي',
+ 64874 => 'شمخ',
+ 64875 => 'شمخ',
+ 64876 => 'شمم',
+ 64877 => 'شمم',
+ 64878 => 'ضحى',
+ 64879 => 'ضخم',
+ 64880 => 'ضخم',
+ 64881 => 'طمح',
+ 64882 => 'طمح',
+ 64883 => 'طمم',
+ 64884 => 'طمي',
+ 64885 => 'عجم',
+ 64886 => 'عمم',
+ 64887 => 'عمم',
+ 64888 => 'عمى',
+ 64889 => 'غمم',
+ 64890 => 'غمي',
+ 64891 => 'غمى',
+ 64892 => 'فخم',
+ 64893 => 'فخم',
+ 64894 => 'قمح',
+ 64895 => 'قمم',
+ 64896 => 'لحم',
+ 64897 => 'لحي',
+ 64898 => 'لحى',
+ 64899 => 'لجج',
+ 64900 => 'لجج',
+ 64901 => 'لخم',
+ 64902 => 'لخم',
+ 64903 => 'لمح',
+ 64904 => 'لمح',
+ 64905 => 'محج',
+ 64906 => 'محم',
+ 64907 => 'محي',
+ 64908 => 'مجح',
+ 64909 => 'مجم',
+ 64910 => 'مخج',
+ 64911 => 'مخم',
+ 64914 => 'مجخ',
+ 64915 => 'همج',
+ 64916 => 'همم',
+ 64917 => 'نحم',
+ 64918 => 'نحى',
+ 64919 => 'نجم',
+ 64920 => 'نجم',
+ 64921 => 'نجى',
+ 64922 => 'نمي',
+ 64923 => 'نمى',
+ 64924 => 'يمم',
+ 64925 => 'يمم',
+ 64926 => 'بخي',
+ 64927 => 'تجي',
+ 64928 => 'تجى',
+ 64929 => 'تخي',
+ 64930 => 'تخى',
+ 64931 => 'تمي',
+ 64932 => 'تمى',
+ 64933 => 'جمي',
+ 64934 => 'جحى',
+ 64935 => 'جمى',
+ 64936 => 'سخى',
+ 64937 => 'صحي',
+ 64938 => 'شحي',
+ 64939 => 'ضحي',
+ 64940 => 'لجي',
+ 64941 => 'لمي',
+ 64942 => 'يحي',
+ 64943 => 'يجي',
+ 64944 => 'يمي',
+ 64945 => 'ممي',
+ 64946 => 'قمي',
+ 64947 => 'نحي',
+ 64948 => 'قمح',
+ 64949 => 'لحم',
+ 64950 => 'عمي',
+ 64951 => 'كمي',
+ 64952 => 'نجح',
+ 64953 => 'مخي',
+ 64954 => 'لجم',
+ 64955 => 'كمم',
+ 64956 => 'لجم',
+ 64957 => 'نجح',
+ 64958 => 'جحي',
+ 64959 => 'حجي',
+ 64960 => 'مجي',
+ 64961 => 'فمي',
+ 64962 => 'بحي',
+ 64963 => 'كمم',
+ 64964 => 'عجم',
+ 64965 => 'صمم',
+ 64966 => 'سخي',
+ 64967 => 'نجي',
+ 65008 => 'صلے',
+ 65009 => 'قلے',
+ 65010 => 'الله',
+ 65011 => 'اكبر',
+ 65012 => 'محمد',
+ 65013 => 'صلعم',
+ 65014 => 'رسول',
+ 65015 => 'عليه',
+ 65016 => 'وسلم',
+ 65017 => 'صلى',
+ 65020 => 'ریال',
+ 65041 => '、',
+ 65047 => '〖',
+ 65048 => '〗',
+ 65073 => '—',
+ 65074 => '–',
+ 65081 => '〔',
+ 65082 => '〕',
+ 65083 => '【',
+ 65084 => '】',
+ 65085 => '《',
+ 65086 => '》',
+ 65087 => '〈',
+ 65088 => '〉',
+ 65089 => '「',
+ 65090 => '」',
+ 65091 => '『',
+ 65092 => '』',
+ 65105 => '、',
+ 65112 => '—',
+ 65117 => '〔',
+ 65118 => '〕',
+ 65123 => '-',
+ 65137 => 'ـً',
+ 65143 => 'ـَ',
+ 65145 => 'ـُ',
+ 65147 => 'ـِ',
+ 65149 => 'ـّ',
+ 65151 => 'ـْ',
+ 65152 => 'ء',
+ 65153 => 'آ',
+ 65154 => 'آ',
+ 65155 => 'أ',
+ 65156 => 'أ',
+ 65157 => 'ؤ',
+ 65158 => 'ؤ',
+ 65159 => 'إ',
+ 65160 => 'إ',
+ 65161 => 'ئ',
+ 65162 => 'ئ',
+ 65163 => 'ئ',
+ 65164 => 'ئ',
+ 65165 => 'ا',
+ 65166 => 'ا',
+ 65167 => 'ب',
+ 65168 => 'ب',
+ 65169 => 'ب',
+ 65170 => 'ب',
+ 65171 => 'ة',
+ 65172 => 'ة',
+ 65173 => 'ت',
+ 65174 => 'ت',
+ 65175 => 'ت',
+ 65176 => 'ت',
+ 65177 => 'ث',
+ 65178 => 'ث',
+ 65179 => 'ث',
+ 65180 => 'ث',
+ 65181 => 'ج',
+ 65182 => 'ج',
+ 65183 => 'ج',
+ 65184 => 'ج',
+ 65185 => 'ح',
+ 65186 => 'ح',
+ 65187 => 'ح',
+ 65188 => 'ح',
+ 65189 => 'خ',
+ 65190 => 'خ',
+ 65191 => 'خ',
+ 65192 => 'خ',
+ 65193 => 'د',
+ 65194 => 'د',
+ 65195 => 'ذ',
+ 65196 => 'ذ',
+ 65197 => 'ر',
+ 65198 => 'ر',
+ 65199 => 'ز',
+ 65200 => 'ز',
+ 65201 => 'س',
+ 65202 => 'س',
+ 65203 => 'س',
+ 65204 => 'س',
+ 65205 => 'ش',
+ 65206 => 'ش',
+ 65207 => 'ش',
+ 65208 => 'ش',
+ 65209 => 'ص',
+ 65210 => 'ص',
+ 65211 => 'ص',
+ 65212 => 'ص',
+ 65213 => 'ض',
+ 65214 => 'ض',
+ 65215 => 'ض',
+ 65216 => 'ض',
+ 65217 => 'ط',
+ 65218 => 'ط',
+ 65219 => 'ط',
+ 65220 => 'ط',
+ 65221 => 'ظ',
+ 65222 => 'ظ',
+ 65223 => 'ظ',
+ 65224 => 'ظ',
+ 65225 => 'ع',
+ 65226 => 'ع',
+ 65227 => 'ع',
+ 65228 => 'ع',
+ 65229 => 'غ',
+ 65230 => 'غ',
+ 65231 => 'غ',
+ 65232 => 'غ',
+ 65233 => 'ف',
+ 65234 => 'ف',
+ 65235 => 'ف',
+ 65236 => 'ف',
+ 65237 => 'ق',
+ 65238 => 'ق',
+ 65239 => 'ق',
+ 65240 => 'ق',
+ 65241 => 'ك',
+ 65242 => 'ك',
+ 65243 => 'ك',
+ 65244 => 'ك',
+ 65245 => 'ل',
+ 65246 => 'ل',
+ 65247 => 'ل',
+ 65248 => 'ل',
+ 65249 => 'م',
+ 65250 => 'م',
+ 65251 => 'م',
+ 65252 => 'م',
+ 65253 => 'ن',
+ 65254 => 'ن',
+ 65255 => 'ن',
+ 65256 => 'ن',
+ 65257 => 'ه',
+ 65258 => 'ه',
+ 65259 => 'ه',
+ 65260 => 'ه',
+ 65261 => 'و',
+ 65262 => 'و',
+ 65263 => 'ى',
+ 65264 => 'ى',
+ 65265 => 'ي',
+ 65266 => 'ي',
+ 65267 => 'ي',
+ 65268 => 'ي',
+ 65269 => 'لآ',
+ 65270 => 'لآ',
+ 65271 => 'لأ',
+ 65272 => 'لأ',
+ 65273 => 'لإ',
+ 65274 => 'لإ',
+ 65275 => 'لا',
+ 65276 => 'لا',
+ 65293 => '-',
+ 65294 => '.',
+ 65296 => '0',
+ 65297 => '1',
+ 65298 => '2',
+ 65299 => '3',
+ 65300 => '4',
+ 65301 => '5',
+ 65302 => '6',
+ 65303 => '7',
+ 65304 => '8',
+ 65305 => '9',
+ 65313 => 'a',
+ 65314 => 'b',
+ 65315 => 'c',
+ 65316 => 'd',
+ 65317 => 'e',
+ 65318 => 'f',
+ 65319 => 'g',
+ 65320 => 'h',
+ 65321 => 'i',
+ 65322 => 'j',
+ 65323 => 'k',
+ 65324 => 'l',
+ 65325 => 'm',
+ 65326 => 'n',
+ 65327 => 'o',
+ 65328 => 'p',
+ 65329 => 'q',
+ 65330 => 'r',
+ 65331 => 's',
+ 65332 => 't',
+ 65333 => 'u',
+ 65334 => 'v',
+ 65335 => 'w',
+ 65336 => 'x',
+ 65337 => 'y',
+ 65338 => 'z',
+ 65345 => 'a',
+ 65346 => 'b',
+ 65347 => 'c',
+ 65348 => 'd',
+ 65349 => 'e',
+ 65350 => 'f',
+ 65351 => 'g',
+ 65352 => 'h',
+ 65353 => 'i',
+ 65354 => 'j',
+ 65355 => 'k',
+ 65356 => 'l',
+ 65357 => 'm',
+ 65358 => 'n',
+ 65359 => 'o',
+ 65360 => 'p',
+ 65361 => 'q',
+ 65362 => 'r',
+ 65363 => 's',
+ 65364 => 't',
+ 65365 => 'u',
+ 65366 => 'v',
+ 65367 => 'w',
+ 65368 => 'x',
+ 65369 => 'y',
+ 65370 => 'z',
+ 65375 => '⦅',
+ 65376 => '⦆',
+ 65377 => '.',
+ 65378 => '「',
+ 65379 => '」',
+ 65380 => '、',
+ 65381 => '・',
+ 65382 => 'ヲ',
+ 65383 => 'ァ',
+ 65384 => 'ィ',
+ 65385 => 'ゥ',
+ 65386 => 'ェ',
+ 65387 => 'ォ',
+ 65388 => 'ャ',
+ 65389 => 'ュ',
+ 65390 => 'ョ',
+ 65391 => 'ッ',
+ 65392 => 'ー',
+ 65393 => 'ア',
+ 65394 => 'イ',
+ 65395 => 'ウ',
+ 65396 => 'エ',
+ 65397 => 'オ',
+ 65398 => 'カ',
+ 65399 => 'キ',
+ 65400 => 'ク',
+ 65401 => 'ケ',
+ 65402 => 'コ',
+ 65403 => 'サ',
+ 65404 => 'シ',
+ 65405 => 'ス',
+ 65406 => 'セ',
+ 65407 => 'ソ',
+ 65408 => 'タ',
+ 65409 => 'チ',
+ 65410 => 'ツ',
+ 65411 => 'テ',
+ 65412 => 'ト',
+ 65413 => 'ナ',
+ 65414 => 'ニ',
+ 65415 => 'ヌ',
+ 65416 => 'ネ',
+ 65417 => 'ノ',
+ 65418 => 'ハ',
+ 65419 => 'ヒ',
+ 65420 => 'フ',
+ 65421 => 'ヘ',
+ 65422 => 'ホ',
+ 65423 => 'マ',
+ 65424 => 'ミ',
+ 65425 => 'ム',
+ 65426 => 'メ',
+ 65427 => 'モ',
+ 65428 => 'ヤ',
+ 65429 => 'ユ',
+ 65430 => 'ヨ',
+ 65431 => 'ラ',
+ 65432 => 'リ',
+ 65433 => 'ル',
+ 65434 => 'レ',
+ 65435 => 'ロ',
+ 65436 => 'ワ',
+ 65437 => 'ン',
+ 65438 => '゙',
+ 65439 => '゚',
+ 65441 => 'ᄀ',
+ 65442 => 'ᄁ',
+ 65443 => 'ᆪ',
+ 65444 => 'ᄂ',
+ 65445 => 'ᆬ',
+ 65446 => 'ᆭ',
+ 65447 => 'ᄃ',
+ 65448 => 'ᄄ',
+ 65449 => 'ᄅ',
+ 65450 => 'ᆰ',
+ 65451 => 'ᆱ',
+ 65452 => 'ᆲ',
+ 65453 => 'ᆳ',
+ 65454 => 'ᆴ',
+ 65455 => 'ᆵ',
+ 65456 => 'ᄚ',
+ 65457 => 'ᄆ',
+ 65458 => 'ᄇ',
+ 65459 => 'ᄈ',
+ 65460 => 'ᄡ',
+ 65461 => 'ᄉ',
+ 65462 => 'ᄊ',
+ 65463 => 'ᄋ',
+ 65464 => 'ᄌ',
+ 65465 => 'ᄍ',
+ 65466 => 'ᄎ',
+ 65467 => 'ᄏ',
+ 65468 => 'ᄐ',
+ 65469 => 'ᄑ',
+ 65470 => 'ᄒ',
+ 65474 => 'ᅡ',
+ 65475 => 'ᅢ',
+ 65476 => 'ᅣ',
+ 65477 => 'ᅤ',
+ 65478 => 'ᅥ',
+ 65479 => 'ᅦ',
+ 65482 => 'ᅧ',
+ 65483 => 'ᅨ',
+ 65484 => 'ᅩ',
+ 65485 => 'ᅪ',
+ 65486 => 'ᅫ',
+ 65487 => 'ᅬ',
+ 65490 => 'ᅭ',
+ 65491 => 'ᅮ',
+ 65492 => 'ᅯ',
+ 65493 => 'ᅰ',
+ 65494 => 'ᅱ',
+ 65495 => 'ᅲ',
+ 65498 => 'ᅳ',
+ 65499 => 'ᅴ',
+ 65500 => 'ᅵ',
+ 65504 => '¢',
+ 65505 => '£',
+ 65506 => '¬',
+ 65508 => '¦',
+ 65509 => '¥',
+ 65510 => '₩',
+ 65512 => '│',
+ 65513 => '←',
+ 65514 => '↑',
+ 65515 => '→',
+ 65516 => '↓',
+ 65517 => '■',
+ 65518 => '○',
+ 66560 => '𐐨',
+ 66561 => '𐐩',
+ 66562 => '𐐪',
+ 66563 => '𐐫',
+ 66564 => '𐐬',
+ 66565 => '𐐭',
+ 66566 => '𐐮',
+ 66567 => '𐐯',
+ 66568 => '𐐰',
+ 66569 => '𐐱',
+ 66570 => '𐐲',
+ 66571 => '𐐳',
+ 66572 => '𐐴',
+ 66573 => '𐐵',
+ 66574 => '𐐶',
+ 66575 => '𐐷',
+ 66576 => '𐐸',
+ 66577 => '𐐹',
+ 66578 => '𐐺',
+ 66579 => '𐐻',
+ 66580 => '𐐼',
+ 66581 => '𐐽',
+ 66582 => '𐐾',
+ 66583 => '𐐿',
+ 66584 => '𐑀',
+ 66585 => '𐑁',
+ 66586 => '𐑂',
+ 66587 => '𐑃',
+ 66588 => '𐑄',
+ 66589 => '𐑅',
+ 66590 => '𐑆',
+ 66591 => '𐑇',
+ 66592 => '𐑈',
+ 66593 => '𐑉',
+ 66594 => '𐑊',
+ 66595 => '𐑋',
+ 66596 => '𐑌',
+ 66597 => '𐑍',
+ 66598 => '𐑎',
+ 66599 => '𐑏',
+ 66736 => '𐓘',
+ 66737 => '𐓙',
+ 66738 => '𐓚',
+ 66739 => '𐓛',
+ 66740 => '𐓜',
+ 66741 => '𐓝',
+ 66742 => '𐓞',
+ 66743 => '𐓟',
+ 66744 => '𐓠',
+ 66745 => '𐓡',
+ 66746 => '𐓢',
+ 66747 => '𐓣',
+ 66748 => '𐓤',
+ 66749 => '𐓥',
+ 66750 => '𐓦',
+ 66751 => '𐓧',
+ 66752 => '𐓨',
+ 66753 => '𐓩',
+ 66754 => '𐓪',
+ 66755 => '𐓫',
+ 66756 => '𐓬',
+ 66757 => '𐓭',
+ 66758 => '𐓮',
+ 66759 => '𐓯',
+ 66760 => '𐓰',
+ 66761 => '𐓱',
+ 66762 => '𐓲',
+ 66763 => '𐓳',
+ 66764 => '𐓴',
+ 66765 => '𐓵',
+ 66766 => '𐓶',
+ 66767 => '𐓷',
+ 66768 => '𐓸',
+ 66769 => '𐓹',
+ 66770 => '𐓺',
+ 66771 => '𐓻',
+ 68736 => '𐳀',
+ 68737 => '𐳁',
+ 68738 => '𐳂',
+ 68739 => '𐳃',
+ 68740 => '𐳄',
+ 68741 => '𐳅',
+ 68742 => '𐳆',
+ 68743 => '𐳇',
+ 68744 => '𐳈',
+ 68745 => '𐳉',
+ 68746 => '𐳊',
+ 68747 => '𐳋',
+ 68748 => '𐳌',
+ 68749 => '𐳍',
+ 68750 => '𐳎',
+ 68751 => '𐳏',
+ 68752 => '𐳐',
+ 68753 => '𐳑',
+ 68754 => '𐳒',
+ 68755 => '𐳓',
+ 68756 => '𐳔',
+ 68757 => '𐳕',
+ 68758 => '𐳖',
+ 68759 => '𐳗',
+ 68760 => '𐳘',
+ 68761 => '𐳙',
+ 68762 => '𐳚',
+ 68763 => '𐳛',
+ 68764 => '𐳜',
+ 68765 => '𐳝',
+ 68766 => '𐳞',
+ 68767 => '𐳟',
+ 68768 => '𐳠',
+ 68769 => '𐳡',
+ 68770 => '𐳢',
+ 68771 => '𐳣',
+ 68772 => '𐳤',
+ 68773 => '𐳥',
+ 68774 => '𐳦',
+ 68775 => '𐳧',
+ 68776 => '𐳨',
+ 68777 => '𐳩',
+ 68778 => '𐳪',
+ 68779 => '𐳫',
+ 68780 => '𐳬',
+ 68781 => '𐳭',
+ 68782 => '𐳮',
+ 68783 => '𐳯',
+ 68784 => '𐳰',
+ 68785 => '𐳱',
+ 68786 => '𐳲',
+ 71840 => '𑣀',
+ 71841 => '𑣁',
+ 71842 => '𑣂',
+ 71843 => '𑣃',
+ 71844 => '𑣄',
+ 71845 => '𑣅',
+ 71846 => '𑣆',
+ 71847 => '𑣇',
+ 71848 => '𑣈',
+ 71849 => '𑣉',
+ 71850 => '𑣊',
+ 71851 => '𑣋',
+ 71852 => '𑣌',
+ 71853 => '𑣍',
+ 71854 => '𑣎',
+ 71855 => '𑣏',
+ 71856 => '𑣐',
+ 71857 => '𑣑',
+ 71858 => '𑣒',
+ 71859 => '𑣓',
+ 71860 => '𑣔',
+ 71861 => '𑣕',
+ 71862 => '𑣖',
+ 71863 => '𑣗',
+ 71864 => '𑣘',
+ 71865 => '𑣙',
+ 71866 => '𑣚',
+ 71867 => '𑣛',
+ 71868 => '𑣜',
+ 71869 => '𑣝',
+ 71870 => '𑣞',
+ 71871 => '𑣟',
+ 93760 => '𖹠',
+ 93761 => '𖹡',
+ 93762 => '𖹢',
+ 93763 => '𖹣',
+ 93764 => '𖹤',
+ 93765 => '𖹥',
+ 93766 => '𖹦',
+ 93767 => '𖹧',
+ 93768 => '𖹨',
+ 93769 => '𖹩',
+ 93770 => '𖹪',
+ 93771 => '𖹫',
+ 93772 => '𖹬',
+ 93773 => '𖹭',
+ 93774 => '𖹮',
+ 93775 => '𖹯',
+ 93776 => '𖹰',
+ 93777 => '𖹱',
+ 93778 => '𖹲',
+ 93779 => '𖹳',
+ 93780 => '𖹴',
+ 93781 => '𖹵',
+ 93782 => '𖹶',
+ 93783 => '𖹷',
+ 93784 => '𖹸',
+ 93785 => '𖹹',
+ 93786 => '𖹺',
+ 93787 => '𖹻',
+ 93788 => '𖹼',
+ 93789 => '𖹽',
+ 93790 => '𖹾',
+ 93791 => '𖹿',
+ 119134 => '𝅗𝅥',
+ 119135 => '𝅘𝅥',
+ 119136 => '𝅘𝅥𝅮',
+ 119137 => '𝅘𝅥𝅯',
+ 119138 => '𝅘𝅥𝅰',
+ 119139 => '𝅘𝅥𝅱',
+ 119140 => '𝅘𝅥𝅲',
+ 119227 => '𝆹𝅥',
+ 119228 => '𝆺𝅥',
+ 119229 => '𝆹𝅥𝅮',
+ 119230 => '𝆺𝅥𝅮',
+ 119231 => '𝆹𝅥𝅯',
+ 119232 => '𝆺𝅥𝅯',
+ 119808 => 'a',
+ 119809 => 'b',
+ 119810 => 'c',
+ 119811 => 'd',
+ 119812 => 'e',
+ 119813 => 'f',
+ 119814 => 'g',
+ 119815 => 'h',
+ 119816 => 'i',
+ 119817 => 'j',
+ 119818 => 'k',
+ 119819 => 'l',
+ 119820 => 'm',
+ 119821 => 'n',
+ 119822 => 'o',
+ 119823 => 'p',
+ 119824 => 'q',
+ 119825 => 'r',
+ 119826 => 's',
+ 119827 => 't',
+ 119828 => 'u',
+ 119829 => 'v',
+ 119830 => 'w',
+ 119831 => 'x',
+ 119832 => 'y',
+ 119833 => 'z',
+ 119834 => 'a',
+ 119835 => 'b',
+ 119836 => 'c',
+ 119837 => 'd',
+ 119838 => 'e',
+ 119839 => 'f',
+ 119840 => 'g',
+ 119841 => 'h',
+ 119842 => 'i',
+ 119843 => 'j',
+ 119844 => 'k',
+ 119845 => 'l',
+ 119846 => 'm',
+ 119847 => 'n',
+ 119848 => 'o',
+ 119849 => 'p',
+ 119850 => 'q',
+ 119851 => 'r',
+ 119852 => 's',
+ 119853 => 't',
+ 119854 => 'u',
+ 119855 => 'v',
+ 119856 => 'w',
+ 119857 => 'x',
+ 119858 => 'y',
+ 119859 => 'z',
+ 119860 => 'a',
+ 119861 => 'b',
+ 119862 => 'c',
+ 119863 => 'd',
+ 119864 => 'e',
+ 119865 => 'f',
+ 119866 => 'g',
+ 119867 => 'h',
+ 119868 => 'i',
+ 119869 => 'j',
+ 119870 => 'k',
+ 119871 => 'l',
+ 119872 => 'm',
+ 119873 => 'n',
+ 119874 => 'o',
+ 119875 => 'p',
+ 119876 => 'q',
+ 119877 => 'r',
+ 119878 => 's',
+ 119879 => 't',
+ 119880 => 'u',
+ 119881 => 'v',
+ 119882 => 'w',
+ 119883 => 'x',
+ 119884 => 'y',
+ 119885 => 'z',
+ 119886 => 'a',
+ 119887 => 'b',
+ 119888 => 'c',
+ 119889 => 'd',
+ 119890 => 'e',
+ 119891 => 'f',
+ 119892 => 'g',
+ 119894 => 'i',
+ 119895 => 'j',
+ 119896 => 'k',
+ 119897 => 'l',
+ 119898 => 'm',
+ 119899 => 'n',
+ 119900 => 'o',
+ 119901 => 'p',
+ 119902 => 'q',
+ 119903 => 'r',
+ 119904 => 's',
+ 119905 => 't',
+ 119906 => 'u',
+ 119907 => 'v',
+ 119908 => 'w',
+ 119909 => 'x',
+ 119910 => 'y',
+ 119911 => 'z',
+ 119912 => 'a',
+ 119913 => 'b',
+ 119914 => 'c',
+ 119915 => 'd',
+ 119916 => 'e',
+ 119917 => 'f',
+ 119918 => 'g',
+ 119919 => 'h',
+ 119920 => 'i',
+ 119921 => 'j',
+ 119922 => 'k',
+ 119923 => 'l',
+ 119924 => 'm',
+ 119925 => 'n',
+ 119926 => 'o',
+ 119927 => 'p',
+ 119928 => 'q',
+ 119929 => 'r',
+ 119930 => 's',
+ 119931 => 't',
+ 119932 => 'u',
+ 119933 => 'v',
+ 119934 => 'w',
+ 119935 => 'x',
+ 119936 => 'y',
+ 119937 => 'z',
+ 119938 => 'a',
+ 119939 => 'b',
+ 119940 => 'c',
+ 119941 => 'd',
+ 119942 => 'e',
+ 119943 => 'f',
+ 119944 => 'g',
+ 119945 => 'h',
+ 119946 => 'i',
+ 119947 => 'j',
+ 119948 => 'k',
+ 119949 => 'l',
+ 119950 => 'm',
+ 119951 => 'n',
+ 119952 => 'o',
+ 119953 => 'p',
+ 119954 => 'q',
+ 119955 => 'r',
+ 119956 => 's',
+ 119957 => 't',
+ 119958 => 'u',
+ 119959 => 'v',
+ 119960 => 'w',
+ 119961 => 'x',
+ 119962 => 'y',
+ 119963 => 'z',
+ 119964 => 'a',
+ 119966 => 'c',
+ 119967 => 'd',
+ 119970 => 'g',
+ 119973 => 'j',
+ 119974 => 'k',
+ 119977 => 'n',
+ 119978 => 'o',
+ 119979 => 'p',
+ 119980 => 'q',
+ 119982 => 's',
+ 119983 => 't',
+ 119984 => 'u',
+ 119985 => 'v',
+ 119986 => 'w',
+ 119987 => 'x',
+ 119988 => 'y',
+ 119989 => 'z',
+ 119990 => 'a',
+ 119991 => 'b',
+ 119992 => 'c',
+ 119993 => 'd',
+ 119995 => 'f',
+ 119997 => 'h',
+ 119998 => 'i',
+ 119999 => 'j',
+ 120000 => 'k',
+ 120001 => 'l',
+ 120002 => 'm',
+ 120003 => 'n',
+ 120005 => 'p',
+ 120006 => 'q',
+ 120007 => 'r',
+ 120008 => 's',
+ 120009 => 't',
+ 120010 => 'u',
+ 120011 => 'v',
+ 120012 => 'w',
+ 120013 => 'x',
+ 120014 => 'y',
+ 120015 => 'z',
+ 120016 => 'a',
+ 120017 => 'b',
+ 120018 => 'c',
+ 120019 => 'd',
+ 120020 => 'e',
+ 120021 => 'f',
+ 120022 => 'g',
+ 120023 => 'h',
+ 120024 => 'i',
+ 120025 => 'j',
+ 120026 => 'k',
+ 120027 => 'l',
+ 120028 => 'm',
+ 120029 => 'n',
+ 120030 => 'o',
+ 120031 => 'p',
+ 120032 => 'q',
+ 120033 => 'r',
+ 120034 => 's',
+ 120035 => 't',
+ 120036 => 'u',
+ 120037 => 'v',
+ 120038 => 'w',
+ 120039 => 'x',
+ 120040 => 'y',
+ 120041 => 'z',
+ 120042 => 'a',
+ 120043 => 'b',
+ 120044 => 'c',
+ 120045 => 'd',
+ 120046 => 'e',
+ 120047 => 'f',
+ 120048 => 'g',
+ 120049 => 'h',
+ 120050 => 'i',
+ 120051 => 'j',
+ 120052 => 'k',
+ 120053 => 'l',
+ 120054 => 'm',
+ 120055 => 'n',
+ 120056 => 'o',
+ 120057 => 'p',
+ 120058 => 'q',
+ 120059 => 'r',
+ 120060 => 's',
+ 120061 => 't',
+ 120062 => 'u',
+ 120063 => 'v',
+ 120064 => 'w',
+ 120065 => 'x',
+ 120066 => 'y',
+ 120067 => 'z',
+ 120068 => 'a',
+ 120069 => 'b',
+ 120071 => 'd',
+ 120072 => 'e',
+ 120073 => 'f',
+ 120074 => 'g',
+ 120077 => 'j',
+ 120078 => 'k',
+ 120079 => 'l',
+ 120080 => 'm',
+ 120081 => 'n',
+ 120082 => 'o',
+ 120083 => 'p',
+ 120084 => 'q',
+ 120086 => 's',
+ 120087 => 't',
+ 120088 => 'u',
+ 120089 => 'v',
+ 120090 => 'w',
+ 120091 => 'x',
+ 120092 => 'y',
+ 120094 => 'a',
+ 120095 => 'b',
+ 120096 => 'c',
+ 120097 => 'd',
+ 120098 => 'e',
+ 120099 => 'f',
+ 120100 => 'g',
+ 120101 => 'h',
+ 120102 => 'i',
+ 120103 => 'j',
+ 120104 => 'k',
+ 120105 => 'l',
+ 120106 => 'm',
+ 120107 => 'n',
+ 120108 => 'o',
+ 120109 => 'p',
+ 120110 => 'q',
+ 120111 => 'r',
+ 120112 => 's',
+ 120113 => 't',
+ 120114 => 'u',
+ 120115 => 'v',
+ 120116 => 'w',
+ 120117 => 'x',
+ 120118 => 'y',
+ 120119 => 'z',
+ 120120 => 'a',
+ 120121 => 'b',
+ 120123 => 'd',
+ 120124 => 'e',
+ 120125 => 'f',
+ 120126 => 'g',
+ 120128 => 'i',
+ 120129 => 'j',
+ 120130 => 'k',
+ 120131 => 'l',
+ 120132 => 'm',
+ 120134 => 'o',
+ 120138 => 's',
+ 120139 => 't',
+ 120140 => 'u',
+ 120141 => 'v',
+ 120142 => 'w',
+ 120143 => 'x',
+ 120144 => 'y',
+ 120146 => 'a',
+ 120147 => 'b',
+ 120148 => 'c',
+ 120149 => 'd',
+ 120150 => 'e',
+ 120151 => 'f',
+ 120152 => 'g',
+ 120153 => 'h',
+ 120154 => 'i',
+ 120155 => 'j',
+ 120156 => 'k',
+ 120157 => 'l',
+ 120158 => 'm',
+ 120159 => 'n',
+ 120160 => 'o',
+ 120161 => 'p',
+ 120162 => 'q',
+ 120163 => 'r',
+ 120164 => 's',
+ 120165 => 't',
+ 120166 => 'u',
+ 120167 => 'v',
+ 120168 => 'w',
+ 120169 => 'x',
+ 120170 => 'y',
+ 120171 => 'z',
+ 120172 => 'a',
+ 120173 => 'b',
+ 120174 => 'c',
+ 120175 => 'd',
+ 120176 => 'e',
+ 120177 => 'f',
+ 120178 => 'g',
+ 120179 => 'h',
+ 120180 => 'i',
+ 120181 => 'j',
+ 120182 => 'k',
+ 120183 => 'l',
+ 120184 => 'm',
+ 120185 => 'n',
+ 120186 => 'o',
+ 120187 => 'p',
+ 120188 => 'q',
+ 120189 => 'r',
+ 120190 => 's',
+ 120191 => 't',
+ 120192 => 'u',
+ 120193 => 'v',
+ 120194 => 'w',
+ 120195 => 'x',
+ 120196 => 'y',
+ 120197 => 'z',
+ 120198 => 'a',
+ 120199 => 'b',
+ 120200 => 'c',
+ 120201 => 'd',
+ 120202 => 'e',
+ 120203 => 'f',
+ 120204 => 'g',
+ 120205 => 'h',
+ 120206 => 'i',
+ 120207 => 'j',
+ 120208 => 'k',
+ 120209 => 'l',
+ 120210 => 'm',
+ 120211 => 'n',
+ 120212 => 'o',
+ 120213 => 'p',
+ 120214 => 'q',
+ 120215 => 'r',
+ 120216 => 's',
+ 120217 => 't',
+ 120218 => 'u',
+ 120219 => 'v',
+ 120220 => 'w',
+ 120221 => 'x',
+ 120222 => 'y',
+ 120223 => 'z',
+ 120224 => 'a',
+ 120225 => 'b',
+ 120226 => 'c',
+ 120227 => 'd',
+ 120228 => 'e',
+ 120229 => 'f',
+ 120230 => 'g',
+ 120231 => 'h',
+ 120232 => 'i',
+ 120233 => 'j',
+ 120234 => 'k',
+ 120235 => 'l',
+ 120236 => 'm',
+ 120237 => 'n',
+ 120238 => 'o',
+ 120239 => 'p',
+ 120240 => 'q',
+ 120241 => 'r',
+ 120242 => 's',
+ 120243 => 't',
+ 120244 => 'u',
+ 120245 => 'v',
+ 120246 => 'w',
+ 120247 => 'x',
+ 120248 => 'y',
+ 120249 => 'z',
+ 120250 => 'a',
+ 120251 => 'b',
+ 120252 => 'c',
+ 120253 => 'd',
+ 120254 => 'e',
+ 120255 => 'f',
+ 120256 => 'g',
+ 120257 => 'h',
+ 120258 => 'i',
+ 120259 => 'j',
+ 120260 => 'k',
+ 120261 => 'l',
+ 120262 => 'm',
+ 120263 => 'n',
+ 120264 => 'o',
+ 120265 => 'p',
+ 120266 => 'q',
+ 120267 => 'r',
+ 120268 => 's',
+ 120269 => 't',
+ 120270 => 'u',
+ 120271 => 'v',
+ 120272 => 'w',
+ 120273 => 'x',
+ 120274 => 'y',
+ 120275 => 'z',
+ 120276 => 'a',
+ 120277 => 'b',
+ 120278 => 'c',
+ 120279 => 'd',
+ 120280 => 'e',
+ 120281 => 'f',
+ 120282 => 'g',
+ 120283 => 'h',
+ 120284 => 'i',
+ 120285 => 'j',
+ 120286 => 'k',
+ 120287 => 'l',
+ 120288 => 'm',
+ 120289 => 'n',
+ 120290 => 'o',
+ 120291 => 'p',
+ 120292 => 'q',
+ 120293 => 'r',
+ 120294 => 's',
+ 120295 => 't',
+ 120296 => 'u',
+ 120297 => 'v',
+ 120298 => 'w',
+ 120299 => 'x',
+ 120300 => 'y',
+ 120301 => 'z',
+ 120302 => 'a',
+ 120303 => 'b',
+ 120304 => 'c',
+ 120305 => 'd',
+ 120306 => 'e',
+ 120307 => 'f',
+ 120308 => 'g',
+ 120309 => 'h',
+ 120310 => 'i',
+ 120311 => 'j',
+ 120312 => 'k',
+ 120313 => 'l',
+ 120314 => 'm',
+ 120315 => 'n',
+ 120316 => 'o',
+ 120317 => 'p',
+ 120318 => 'q',
+ 120319 => 'r',
+ 120320 => 's',
+ 120321 => 't',
+ 120322 => 'u',
+ 120323 => 'v',
+ 120324 => 'w',
+ 120325 => 'x',
+ 120326 => 'y',
+ 120327 => 'z',
+ 120328 => 'a',
+ 120329 => 'b',
+ 120330 => 'c',
+ 120331 => 'd',
+ 120332 => 'e',
+ 120333 => 'f',
+ 120334 => 'g',
+ 120335 => 'h',
+ 120336 => 'i',
+ 120337 => 'j',
+ 120338 => 'k',
+ 120339 => 'l',
+ 120340 => 'm',
+ 120341 => 'n',
+ 120342 => 'o',
+ 120343 => 'p',
+ 120344 => 'q',
+ 120345 => 'r',
+ 120346 => 's',
+ 120347 => 't',
+ 120348 => 'u',
+ 120349 => 'v',
+ 120350 => 'w',
+ 120351 => 'x',
+ 120352 => 'y',
+ 120353 => 'z',
+ 120354 => 'a',
+ 120355 => 'b',
+ 120356 => 'c',
+ 120357 => 'd',
+ 120358 => 'e',
+ 120359 => 'f',
+ 120360 => 'g',
+ 120361 => 'h',
+ 120362 => 'i',
+ 120363 => 'j',
+ 120364 => 'k',
+ 120365 => 'l',
+ 120366 => 'm',
+ 120367 => 'n',
+ 120368 => 'o',
+ 120369 => 'p',
+ 120370 => 'q',
+ 120371 => 'r',
+ 120372 => 's',
+ 120373 => 't',
+ 120374 => 'u',
+ 120375 => 'v',
+ 120376 => 'w',
+ 120377 => 'x',
+ 120378 => 'y',
+ 120379 => 'z',
+ 120380 => 'a',
+ 120381 => 'b',
+ 120382 => 'c',
+ 120383 => 'd',
+ 120384 => 'e',
+ 120385 => 'f',
+ 120386 => 'g',
+ 120387 => 'h',
+ 120388 => 'i',
+ 120389 => 'j',
+ 120390 => 'k',
+ 120391 => 'l',
+ 120392 => 'm',
+ 120393 => 'n',
+ 120394 => 'o',
+ 120395 => 'p',
+ 120396 => 'q',
+ 120397 => 'r',
+ 120398 => 's',
+ 120399 => 't',
+ 120400 => 'u',
+ 120401 => 'v',
+ 120402 => 'w',
+ 120403 => 'x',
+ 120404 => 'y',
+ 120405 => 'z',
+ 120406 => 'a',
+ 120407 => 'b',
+ 120408 => 'c',
+ 120409 => 'd',
+ 120410 => 'e',
+ 120411 => 'f',
+ 120412 => 'g',
+ 120413 => 'h',
+ 120414 => 'i',
+ 120415 => 'j',
+ 120416 => 'k',
+ 120417 => 'l',
+ 120418 => 'm',
+ 120419 => 'n',
+ 120420 => 'o',
+ 120421 => 'p',
+ 120422 => 'q',
+ 120423 => 'r',
+ 120424 => 's',
+ 120425 => 't',
+ 120426 => 'u',
+ 120427 => 'v',
+ 120428 => 'w',
+ 120429 => 'x',
+ 120430 => 'y',
+ 120431 => 'z',
+ 120432 => 'a',
+ 120433 => 'b',
+ 120434 => 'c',
+ 120435 => 'd',
+ 120436 => 'e',
+ 120437 => 'f',
+ 120438 => 'g',
+ 120439 => 'h',
+ 120440 => 'i',
+ 120441 => 'j',
+ 120442 => 'k',
+ 120443 => 'l',
+ 120444 => 'm',
+ 120445 => 'n',
+ 120446 => 'o',
+ 120447 => 'p',
+ 120448 => 'q',
+ 120449 => 'r',
+ 120450 => 's',
+ 120451 => 't',
+ 120452 => 'u',
+ 120453 => 'v',
+ 120454 => 'w',
+ 120455 => 'x',
+ 120456 => 'y',
+ 120457 => 'z',
+ 120458 => 'a',
+ 120459 => 'b',
+ 120460 => 'c',
+ 120461 => 'd',
+ 120462 => 'e',
+ 120463 => 'f',
+ 120464 => 'g',
+ 120465 => 'h',
+ 120466 => 'i',
+ 120467 => 'j',
+ 120468 => 'k',
+ 120469 => 'l',
+ 120470 => 'm',
+ 120471 => 'n',
+ 120472 => 'o',
+ 120473 => 'p',
+ 120474 => 'q',
+ 120475 => 'r',
+ 120476 => 's',
+ 120477 => 't',
+ 120478 => 'u',
+ 120479 => 'v',
+ 120480 => 'w',
+ 120481 => 'x',
+ 120482 => 'y',
+ 120483 => 'z',
+ 120484 => 'ı',
+ 120485 => 'ȷ',
+ 120488 => 'α',
+ 120489 => 'β',
+ 120490 => 'γ',
+ 120491 => 'δ',
+ 120492 => 'ε',
+ 120493 => 'ζ',
+ 120494 => 'η',
+ 120495 => 'θ',
+ 120496 => 'ι',
+ 120497 => 'κ',
+ 120498 => 'λ',
+ 120499 => 'μ',
+ 120500 => 'ν',
+ 120501 => 'ξ',
+ 120502 => 'ο',
+ 120503 => 'π',
+ 120504 => 'ρ',
+ 120505 => 'θ',
+ 120506 => 'σ',
+ 120507 => 'τ',
+ 120508 => 'υ',
+ 120509 => 'φ',
+ 120510 => 'χ',
+ 120511 => 'ψ',
+ 120512 => 'ω',
+ 120513 => '∇',
+ 120514 => 'α',
+ 120515 => 'β',
+ 120516 => 'γ',
+ 120517 => 'δ',
+ 120518 => 'ε',
+ 120519 => 'ζ',
+ 120520 => 'η',
+ 120521 => 'θ',
+ 120522 => 'ι',
+ 120523 => 'κ',
+ 120524 => 'λ',
+ 120525 => 'μ',
+ 120526 => 'ν',
+ 120527 => 'ξ',
+ 120528 => 'ο',
+ 120529 => 'π',
+ 120530 => 'ρ',
+ 120531 => 'σ',
+ 120532 => 'σ',
+ 120533 => 'τ',
+ 120534 => 'υ',
+ 120535 => 'φ',
+ 120536 => 'χ',
+ 120537 => 'ψ',
+ 120538 => 'ω',
+ 120539 => '∂',
+ 120540 => 'ε',
+ 120541 => 'θ',
+ 120542 => 'κ',
+ 120543 => 'φ',
+ 120544 => 'ρ',
+ 120545 => 'π',
+ 120546 => 'α',
+ 120547 => 'β',
+ 120548 => 'γ',
+ 120549 => 'δ',
+ 120550 => 'ε',
+ 120551 => 'ζ',
+ 120552 => 'η',
+ 120553 => 'θ',
+ 120554 => 'ι',
+ 120555 => 'κ',
+ 120556 => 'λ',
+ 120557 => 'μ',
+ 120558 => 'ν',
+ 120559 => 'ξ',
+ 120560 => 'ο',
+ 120561 => 'π',
+ 120562 => 'ρ',
+ 120563 => 'θ',
+ 120564 => 'σ',
+ 120565 => 'τ',
+ 120566 => 'υ',
+ 120567 => 'φ',
+ 120568 => 'χ',
+ 120569 => 'ψ',
+ 120570 => 'ω',
+ 120571 => '∇',
+ 120572 => 'α',
+ 120573 => 'β',
+ 120574 => 'γ',
+ 120575 => 'δ',
+ 120576 => 'ε',
+ 120577 => 'ζ',
+ 120578 => 'η',
+ 120579 => 'θ',
+ 120580 => 'ι',
+ 120581 => 'κ',
+ 120582 => 'λ',
+ 120583 => 'μ',
+ 120584 => 'ν',
+ 120585 => 'ξ',
+ 120586 => 'ο',
+ 120587 => 'π',
+ 120588 => 'ρ',
+ 120589 => 'σ',
+ 120590 => 'σ',
+ 120591 => 'τ',
+ 120592 => 'υ',
+ 120593 => 'φ',
+ 120594 => 'χ',
+ 120595 => 'ψ',
+ 120596 => 'ω',
+ 120597 => '∂',
+ 120598 => 'ε',
+ 120599 => 'θ',
+ 120600 => 'κ',
+ 120601 => 'φ',
+ 120602 => 'ρ',
+ 120603 => 'π',
+ 120604 => 'α',
+ 120605 => 'β',
+ 120606 => 'γ',
+ 120607 => 'δ',
+ 120608 => 'ε',
+ 120609 => 'ζ',
+ 120610 => 'η',
+ 120611 => 'θ',
+ 120612 => 'ι',
+ 120613 => 'κ',
+ 120614 => 'λ',
+ 120615 => 'μ',
+ 120616 => 'ν',
+ 120617 => 'ξ',
+ 120618 => 'ο',
+ 120619 => 'π',
+ 120620 => 'ρ',
+ 120621 => 'θ',
+ 120622 => 'σ',
+ 120623 => 'τ',
+ 120624 => 'υ',
+ 120625 => 'φ',
+ 120626 => 'χ',
+ 120627 => 'ψ',
+ 120628 => 'ω',
+ 120629 => '∇',
+ 120630 => 'α',
+ 120631 => 'β',
+ 120632 => 'γ',
+ 120633 => 'δ',
+ 120634 => 'ε',
+ 120635 => 'ζ',
+ 120636 => 'η',
+ 120637 => 'θ',
+ 120638 => 'ι',
+ 120639 => 'κ',
+ 120640 => 'λ',
+ 120641 => 'μ',
+ 120642 => 'ν',
+ 120643 => 'ξ',
+ 120644 => 'ο',
+ 120645 => 'π',
+ 120646 => 'ρ',
+ 120647 => 'σ',
+ 120648 => 'σ',
+ 120649 => 'τ',
+ 120650 => 'υ',
+ 120651 => 'φ',
+ 120652 => 'χ',
+ 120653 => 'ψ',
+ 120654 => 'ω',
+ 120655 => '∂',
+ 120656 => 'ε',
+ 120657 => 'θ',
+ 120658 => 'κ',
+ 120659 => 'φ',
+ 120660 => 'ρ',
+ 120661 => 'π',
+ 120662 => 'α',
+ 120663 => 'β',
+ 120664 => 'γ',
+ 120665 => 'δ',
+ 120666 => 'ε',
+ 120667 => 'ζ',
+ 120668 => 'η',
+ 120669 => 'θ',
+ 120670 => 'ι',
+ 120671 => 'κ',
+ 120672 => 'λ',
+ 120673 => 'μ',
+ 120674 => 'ν',
+ 120675 => 'ξ',
+ 120676 => 'ο',
+ 120677 => 'π',
+ 120678 => 'ρ',
+ 120679 => 'θ',
+ 120680 => 'σ',
+ 120681 => 'τ',
+ 120682 => 'υ',
+ 120683 => 'φ',
+ 120684 => 'χ',
+ 120685 => 'ψ',
+ 120686 => 'ω',
+ 120687 => '∇',
+ 120688 => 'α',
+ 120689 => 'β',
+ 120690 => 'γ',
+ 120691 => 'δ',
+ 120692 => 'ε',
+ 120693 => 'ζ',
+ 120694 => 'η',
+ 120695 => 'θ',
+ 120696 => 'ι',
+ 120697 => 'κ',
+ 120698 => 'λ',
+ 120699 => 'μ',
+ 120700 => 'ν',
+ 120701 => 'ξ',
+ 120702 => 'ο',
+ 120703 => 'π',
+ 120704 => 'ρ',
+ 120705 => 'σ',
+ 120706 => 'σ',
+ 120707 => 'τ',
+ 120708 => 'υ',
+ 120709 => 'φ',
+ 120710 => 'χ',
+ 120711 => 'ψ',
+ 120712 => 'ω',
+ 120713 => '∂',
+ 120714 => 'ε',
+ 120715 => 'θ',
+ 120716 => 'κ',
+ 120717 => 'φ',
+ 120718 => 'ρ',
+ 120719 => 'π',
+ 120720 => 'α',
+ 120721 => 'β',
+ 120722 => 'γ',
+ 120723 => 'δ',
+ 120724 => 'ε',
+ 120725 => 'ζ',
+ 120726 => 'η',
+ 120727 => 'θ',
+ 120728 => 'ι',
+ 120729 => 'κ',
+ 120730 => 'λ',
+ 120731 => 'μ',
+ 120732 => 'ν',
+ 120733 => 'ξ',
+ 120734 => 'ο',
+ 120735 => 'π',
+ 120736 => 'ρ',
+ 120737 => 'θ',
+ 120738 => 'σ',
+ 120739 => 'τ',
+ 120740 => 'υ',
+ 120741 => 'φ',
+ 120742 => 'χ',
+ 120743 => 'ψ',
+ 120744 => 'ω',
+ 120745 => '∇',
+ 120746 => 'α',
+ 120747 => 'β',
+ 120748 => 'γ',
+ 120749 => 'δ',
+ 120750 => 'ε',
+ 120751 => 'ζ',
+ 120752 => 'η',
+ 120753 => 'θ',
+ 120754 => 'ι',
+ 120755 => 'κ',
+ 120756 => 'λ',
+ 120757 => 'μ',
+ 120758 => 'ν',
+ 120759 => 'ξ',
+ 120760 => 'ο',
+ 120761 => 'π',
+ 120762 => 'ρ',
+ 120763 => 'σ',
+ 120764 => 'σ',
+ 120765 => 'τ',
+ 120766 => 'υ',
+ 120767 => 'φ',
+ 120768 => 'χ',
+ 120769 => 'ψ',
+ 120770 => 'ω',
+ 120771 => '∂',
+ 120772 => 'ε',
+ 120773 => 'θ',
+ 120774 => 'κ',
+ 120775 => 'φ',
+ 120776 => 'ρ',
+ 120777 => 'π',
+ 120778 => 'ϝ',
+ 120779 => 'ϝ',
+ 120782 => '0',
+ 120783 => '1',
+ 120784 => '2',
+ 120785 => '3',
+ 120786 => '4',
+ 120787 => '5',
+ 120788 => '6',
+ 120789 => '7',
+ 120790 => '8',
+ 120791 => '9',
+ 120792 => '0',
+ 120793 => '1',
+ 120794 => '2',
+ 120795 => '3',
+ 120796 => '4',
+ 120797 => '5',
+ 120798 => '6',
+ 120799 => '7',
+ 120800 => '8',
+ 120801 => '9',
+ 120802 => '0',
+ 120803 => '1',
+ 120804 => '2',
+ 120805 => '3',
+ 120806 => '4',
+ 120807 => '5',
+ 120808 => '6',
+ 120809 => '7',
+ 120810 => '8',
+ 120811 => '9',
+ 120812 => '0',
+ 120813 => '1',
+ 120814 => '2',
+ 120815 => '3',
+ 120816 => '4',
+ 120817 => '5',
+ 120818 => '6',
+ 120819 => '7',
+ 120820 => '8',
+ 120821 => '9',
+ 120822 => '0',
+ 120823 => '1',
+ 120824 => '2',
+ 120825 => '3',
+ 120826 => '4',
+ 120827 => '5',
+ 120828 => '6',
+ 120829 => '7',
+ 120830 => '8',
+ 120831 => '9',
+ 125184 => '𞤢',
+ 125185 => '𞤣',
+ 125186 => '𞤤',
+ 125187 => '𞤥',
+ 125188 => '𞤦',
+ 125189 => '𞤧',
+ 125190 => '𞤨',
+ 125191 => '𞤩',
+ 125192 => '𞤪',
+ 125193 => '𞤫',
+ 125194 => '𞤬',
+ 125195 => '𞤭',
+ 125196 => '𞤮',
+ 125197 => '𞤯',
+ 125198 => '𞤰',
+ 125199 => '𞤱',
+ 125200 => '𞤲',
+ 125201 => '𞤳',
+ 125202 => '𞤴',
+ 125203 => '𞤵',
+ 125204 => '𞤶',
+ 125205 => '𞤷',
+ 125206 => '𞤸',
+ 125207 => '𞤹',
+ 125208 => '𞤺',
+ 125209 => '𞤻',
+ 125210 => '𞤼',
+ 125211 => '𞤽',
+ 125212 => '𞤾',
+ 125213 => '𞤿',
+ 125214 => '𞥀',
+ 125215 => '𞥁',
+ 125216 => '𞥂',
+ 125217 => '𞥃',
+ 126464 => 'ا',
+ 126465 => 'ب',
+ 126466 => 'ج',
+ 126467 => 'د',
+ 126469 => 'و',
+ 126470 => 'ز',
+ 126471 => 'ح',
+ 126472 => 'ط',
+ 126473 => 'ي',
+ 126474 => 'ك',
+ 126475 => 'ل',
+ 126476 => 'م',
+ 126477 => 'ن',
+ 126478 => 'س',
+ 126479 => 'ع',
+ 126480 => 'ف',
+ 126481 => 'ص',
+ 126482 => 'ق',
+ 126483 => 'ر',
+ 126484 => 'ش',
+ 126485 => 'ت',
+ 126486 => 'ث',
+ 126487 => 'خ',
+ 126488 => 'ذ',
+ 126489 => 'ض',
+ 126490 => 'ظ',
+ 126491 => 'غ',
+ 126492 => 'ٮ',
+ 126493 => 'ں',
+ 126494 => 'ڡ',
+ 126495 => 'ٯ',
+ 126497 => 'ب',
+ 126498 => 'ج',
+ 126500 => 'ه',
+ 126503 => 'ح',
+ 126505 => 'ي',
+ 126506 => 'ك',
+ 126507 => 'ل',
+ 126508 => 'م',
+ 126509 => 'ن',
+ 126510 => 'س',
+ 126511 => 'ع',
+ 126512 => 'ف',
+ 126513 => 'ص',
+ 126514 => 'ق',
+ 126516 => 'ش',
+ 126517 => 'ت',
+ 126518 => 'ث',
+ 126519 => 'خ',
+ 126521 => 'ض',
+ 126523 => 'غ',
+ 126530 => 'ج',
+ 126535 => 'ح',
+ 126537 => 'ي',
+ 126539 => 'ل',
+ 126541 => 'ن',
+ 126542 => 'س',
+ 126543 => 'ع',
+ 126545 => 'ص',
+ 126546 => 'ق',
+ 126548 => 'ش',
+ 126551 => 'خ',
+ 126553 => 'ض',
+ 126555 => 'غ',
+ 126557 => 'ں',
+ 126559 => 'ٯ',
+ 126561 => 'ب',
+ 126562 => 'ج',
+ 126564 => 'ه',
+ 126567 => 'ح',
+ 126568 => 'ط',
+ 126569 => 'ي',
+ 126570 => 'ك',
+ 126572 => 'م',
+ 126573 => 'ن',
+ 126574 => 'س',
+ 126575 => 'ع',
+ 126576 => 'ف',
+ 126577 => 'ص',
+ 126578 => 'ق',
+ 126580 => 'ش',
+ 126581 => 'ت',
+ 126582 => 'ث',
+ 126583 => 'خ',
+ 126585 => 'ض',
+ 126586 => 'ظ',
+ 126587 => 'غ',
+ 126588 => 'ٮ',
+ 126590 => 'ڡ',
+ 126592 => 'ا',
+ 126593 => 'ب',
+ 126594 => 'ج',
+ 126595 => 'د',
+ 126596 => 'ه',
+ 126597 => 'و',
+ 126598 => 'ز',
+ 126599 => 'ح',
+ 126600 => 'ط',
+ 126601 => 'ي',
+ 126603 => 'ل',
+ 126604 => 'م',
+ 126605 => 'ن',
+ 126606 => 'س',
+ 126607 => 'ع',
+ 126608 => 'ف',
+ 126609 => 'ص',
+ 126610 => 'ق',
+ 126611 => 'ر',
+ 126612 => 'ش',
+ 126613 => 'ت',
+ 126614 => 'ث',
+ 126615 => 'خ',
+ 126616 => 'ذ',
+ 126617 => 'ض',
+ 126618 => 'ظ',
+ 126619 => 'غ',
+ 126625 => 'ب',
+ 126626 => 'ج',
+ 126627 => 'د',
+ 126629 => 'و',
+ 126630 => 'ز',
+ 126631 => 'ح',
+ 126632 => 'ط',
+ 126633 => 'ي',
+ 126635 => 'ل',
+ 126636 => 'م',
+ 126637 => 'ن',
+ 126638 => 'س',
+ 126639 => 'ع',
+ 126640 => 'ف',
+ 126641 => 'ص',
+ 126642 => 'ق',
+ 126643 => 'ر',
+ 126644 => 'ش',
+ 126645 => 'ت',
+ 126646 => 'ث',
+ 126647 => 'خ',
+ 126648 => 'ذ',
+ 126649 => 'ض',
+ 126650 => 'ظ',
+ 126651 => 'غ',
+ 127274 => '〔s〕',
+ 127275 => 'c',
+ 127276 => 'r',
+ 127277 => 'cd',
+ 127278 => 'wz',
+ 127280 => 'a',
+ 127281 => 'b',
+ 127282 => 'c',
+ 127283 => 'd',
+ 127284 => 'e',
+ 127285 => 'f',
+ 127286 => 'g',
+ 127287 => 'h',
+ 127288 => 'i',
+ 127289 => 'j',
+ 127290 => 'k',
+ 127291 => 'l',
+ 127292 => 'm',
+ 127293 => 'n',
+ 127294 => 'o',
+ 127295 => 'p',
+ 127296 => 'q',
+ 127297 => 'r',
+ 127298 => 's',
+ 127299 => 't',
+ 127300 => 'u',
+ 127301 => 'v',
+ 127302 => 'w',
+ 127303 => 'x',
+ 127304 => 'y',
+ 127305 => 'z',
+ 127306 => 'hv',
+ 127307 => 'mv',
+ 127308 => 'sd',
+ 127309 => 'ss',
+ 127310 => 'ppv',
+ 127311 => 'wc',
+ 127338 => 'mc',
+ 127339 => 'md',
+ 127340 => 'mr',
+ 127376 => 'dj',
+ 127488 => 'ほか',
+ 127489 => 'ココ',
+ 127490 => 'サ',
+ 127504 => '手',
+ 127505 => '字',
+ 127506 => '双',
+ 127507 => 'デ',
+ 127508 => '二',
+ 127509 => '多',
+ 127510 => '解',
+ 127511 => '天',
+ 127512 => '交',
+ 127513 => '映',
+ 127514 => '無',
+ 127515 => '料',
+ 127516 => '前',
+ 127517 => '後',
+ 127518 => '再',
+ 127519 => '新',
+ 127520 => '初',
+ 127521 => '終',
+ 127522 => '生',
+ 127523 => '販',
+ 127524 => '声',
+ 127525 => '吹',
+ 127526 => '演',
+ 127527 => '投',
+ 127528 => '捕',
+ 127529 => '一',
+ 127530 => '三',
+ 127531 => '遊',
+ 127532 => '左',
+ 127533 => '中',
+ 127534 => '右',
+ 127535 => '指',
+ 127536 => '走',
+ 127537 => '打',
+ 127538 => '禁',
+ 127539 => '空',
+ 127540 => '合',
+ 127541 => '満',
+ 127542 => '有',
+ 127543 => '月',
+ 127544 => '申',
+ 127545 => '割',
+ 127546 => '営',
+ 127547 => '配',
+ 127552 => '〔本〕',
+ 127553 => '〔三〕',
+ 127554 => '〔二〕',
+ 127555 => '〔安〕',
+ 127556 => '〔点〕',
+ 127557 => '〔打〕',
+ 127558 => '〔盗〕',
+ 127559 => '〔勝〕',
+ 127560 => '〔敗〕',
+ 127568 => '得',
+ 127569 => '可',
+ 130032 => '0',
+ 130033 => '1',
+ 130034 => '2',
+ 130035 => '3',
+ 130036 => '4',
+ 130037 => '5',
+ 130038 => '6',
+ 130039 => '7',
+ 130040 => '8',
+ 130041 => '9',
+ 194560 => '丽',
+ 194561 => '丸',
+ 194562 => '乁',
+ 194563 => '𠄢',
+ 194564 => '你',
+ 194565 => '侮',
+ 194566 => '侻',
+ 194567 => '倂',
+ 194568 => '偺',
+ 194569 => '備',
+ 194570 => '僧',
+ 194571 => '像',
+ 194572 => '㒞',
+ 194573 => '𠘺',
+ 194574 => '免',
+ 194575 => '兔',
+ 194576 => '兤',
+ 194577 => '具',
+ 194578 => '𠔜',
+ 194579 => '㒹',
+ 194580 => '內',
+ 194581 => '再',
+ 194582 => '𠕋',
+ 194583 => '冗',
+ 194584 => '冤',
+ 194585 => '仌',
+ 194586 => '冬',
+ 194587 => '况',
+ 194588 => '𩇟',
+ 194589 => '凵',
+ 194590 => '刃',
+ 194591 => '㓟',
+ 194592 => '刻',
+ 194593 => '剆',
+ 194594 => '割',
+ 194595 => '剷',
+ 194596 => '㔕',
+ 194597 => '勇',
+ 194598 => '勉',
+ 194599 => '勤',
+ 194600 => '勺',
+ 194601 => '包',
+ 194602 => '匆',
+ 194603 => '北',
+ 194604 => '卉',
+ 194605 => '卑',
+ 194606 => '博',
+ 194607 => '即',
+ 194608 => '卽',
+ 194609 => '卿',
+ 194610 => '卿',
+ 194611 => '卿',
+ 194612 => '𠨬',
+ 194613 => '灰',
+ 194614 => '及',
+ 194615 => '叟',
+ 194616 => '𠭣',
+ 194617 => '叫',
+ 194618 => '叱',
+ 194619 => '吆',
+ 194620 => '咞',
+ 194621 => '吸',
+ 194622 => '呈',
+ 194623 => '周',
+ 194624 => '咢',
+ 194625 => '哶',
+ 194626 => '唐',
+ 194627 => '啓',
+ 194628 => '啣',
+ 194629 => '善',
+ 194630 => '善',
+ 194631 => '喙',
+ 194632 => '喫',
+ 194633 => '喳',
+ 194634 => '嗂',
+ 194635 => '圖',
+ 194636 => '嘆',
+ 194637 => '圗',
+ 194638 => '噑',
+ 194639 => '噴',
+ 194640 => '切',
+ 194641 => '壮',
+ 194642 => '城',
+ 194643 => '埴',
+ 194644 => '堍',
+ 194645 => '型',
+ 194646 => '堲',
+ 194647 => '報',
+ 194648 => '墬',
+ 194649 => '𡓤',
+ 194650 => '売',
+ 194651 => '壷',
+ 194652 => '夆',
+ 194653 => '多',
+ 194654 => '夢',
+ 194655 => '奢',
+ 194656 => '𡚨',
+ 194657 => '𡛪',
+ 194658 => '姬',
+ 194659 => '娛',
+ 194660 => '娧',
+ 194661 => '姘',
+ 194662 => '婦',
+ 194663 => '㛮',
+ 194665 => '嬈',
+ 194666 => '嬾',
+ 194667 => '嬾',
+ 194668 => '𡧈',
+ 194669 => '寃',
+ 194670 => '寘',
+ 194671 => '寧',
+ 194672 => '寳',
+ 194673 => '𡬘',
+ 194674 => '寿',
+ 194675 => '将',
+ 194677 => '尢',
+ 194678 => '㞁',
+ 194679 => '屠',
+ 194680 => '屮',
+ 194681 => '峀',
+ 194682 => '岍',
+ 194683 => '𡷤',
+ 194684 => '嵃',
+ 194685 => '𡷦',
+ 194686 => '嵮',
+ 194687 => '嵫',
+ 194688 => '嵼',
+ 194689 => '巡',
+ 194690 => '巢',
+ 194691 => '㠯',
+ 194692 => '巽',
+ 194693 => '帨',
+ 194694 => '帽',
+ 194695 => '幩',
+ 194696 => '㡢',
+ 194697 => '𢆃',
+ 194698 => '㡼',
+ 194699 => '庰',
+ 194700 => '庳',
+ 194701 => '庶',
+ 194702 => '廊',
+ 194703 => '𪎒',
+ 194704 => '廾',
+ 194705 => '𢌱',
+ 194706 => '𢌱',
+ 194707 => '舁',
+ 194708 => '弢',
+ 194709 => '弢',
+ 194710 => '㣇',
+ 194711 => '𣊸',
+ 194712 => '𦇚',
+ 194713 => '形',
+ 194714 => '彫',
+ 194715 => '㣣',
+ 194716 => '徚',
+ 194717 => '忍',
+ 194718 => '志',
+ 194719 => '忹',
+ 194720 => '悁',
+ 194721 => '㤺',
+ 194722 => '㤜',
+ 194723 => '悔',
+ 194724 => '𢛔',
+ 194725 => '惇',
+ 194726 => '慈',
+ 194727 => '慌',
+ 194728 => '慎',
+ 194729 => '慌',
+ 194730 => '慺',
+ 194731 => '憎',
+ 194732 => '憲',
+ 194733 => '憤',
+ 194734 => '憯',
+ 194735 => '懞',
+ 194736 => '懲',
+ 194737 => '懶',
+ 194738 => '成',
+ 194739 => '戛',
+ 194740 => '扝',
+ 194741 => '抱',
+ 194742 => '拔',
+ 194743 => '捐',
+ 194744 => '𢬌',
+ 194745 => '挽',
+ 194746 => '拼',
+ 194747 => '捨',
+ 194748 => '掃',
+ 194749 => '揤',
+ 194750 => '𢯱',
+ 194751 => '搢',
+ 194752 => '揅',
+ 194753 => '掩',
+ 194754 => '㨮',
+ 194755 => '摩',
+ 194756 => '摾',
+ 194757 => '撝',
+ 194758 => '摷',
+ 194759 => '㩬',
+ 194760 => '敏',
+ 194761 => '敬',
+ 194762 => '𣀊',
+ 194763 => '旣',
+ 194764 => '書',
+ 194765 => '晉',
+ 194766 => '㬙',
+ 194767 => '暑',
+ 194768 => '㬈',
+ 194769 => '㫤',
+ 194770 => '冒',
+ 194771 => '冕',
+ 194772 => '最',
+ 194773 => '暜',
+ 194774 => '肭',
+ 194775 => '䏙',
+ 194776 => '朗',
+ 194777 => '望',
+ 194778 => '朡',
+ 194779 => '杞',
+ 194780 => '杓',
+ 194781 => '𣏃',
+ 194782 => '㭉',
+ 194783 => '柺',
+ 194784 => '枅',
+ 194785 => '桒',
+ 194786 => '梅',
+ 194787 => '𣑭',
+ 194788 => '梎',
+ 194789 => '栟',
+ 194790 => '椔',
+ 194791 => '㮝',
+ 194792 => '楂',
+ 194793 => '榣',
+ 194794 => '槪',
+ 194795 => '檨',
+ 194796 => '𣚣',
+ 194797 => '櫛',
+ 194798 => '㰘',
+ 194799 => '次',
+ 194800 => '𣢧',
+ 194801 => '歔',
+ 194802 => '㱎',
+ 194803 => '歲',
+ 194804 => '殟',
+ 194805 => '殺',
+ 194806 => '殻',
+ 194807 => '𣪍',
+ 194808 => '𡴋',
+ 194809 => '𣫺',
+ 194810 => '汎',
+ 194811 => '𣲼',
+ 194812 => '沿',
+ 194813 => '泍',
+ 194814 => '汧',
+ 194815 => '洖',
+ 194816 => '派',
+ 194817 => '海',
+ 194818 => '流',
+ 194819 => '浩',
+ 194820 => '浸',
+ 194821 => '涅',
+ 194822 => '𣴞',
+ 194823 => '洴',
+ 194824 => '港',
+ 194825 => '湮',
+ 194826 => '㴳',
+ 194827 => '滋',
+ 194828 => '滇',
+ 194829 => '𣻑',
+ 194830 => '淹',
+ 194831 => '潮',
+ 194832 => '𣽞',
+ 194833 => '𣾎',
+ 194834 => '濆',
+ 194835 => '瀹',
+ 194836 => '瀞',
+ 194837 => '瀛',
+ 194838 => '㶖',
+ 194839 => '灊',
+ 194840 => '災',
+ 194841 => '灷',
+ 194842 => '炭',
+ 194843 => '𠔥',
+ 194844 => '煅',
+ 194845 => '𤉣',
+ 194846 => '熜',
+ 194848 => '爨',
+ 194849 => '爵',
+ 194850 => '牐',
+ 194851 => '𤘈',
+ 194852 => '犀',
+ 194853 => '犕',
+ 194854 => '𤜵',
+ 194855 => '𤠔',
+ 194856 => '獺',
+ 194857 => '王',
+ 194858 => '㺬',
+ 194859 => '玥',
+ 194860 => '㺸',
+ 194861 => '㺸',
+ 194862 => '瑇',
+ 194863 => '瑜',
+ 194864 => '瑱',
+ 194865 => '璅',
+ 194866 => '瓊',
+ 194867 => '㼛',
+ 194868 => '甤',
+ 194869 => '𤰶',
+ 194870 => '甾',
+ 194871 => '𤲒',
+ 194872 => '異',
+ 194873 => '𢆟',
+ 194874 => '瘐',
+ 194875 => '𤾡',
+ 194876 => '𤾸',
+ 194877 => '𥁄',
+ 194878 => '㿼',
+ 194879 => '䀈',
+ 194880 => '直',
+ 194881 => '𥃳',
+ 194882 => '𥃲',
+ 194883 => '𥄙',
+ 194884 => '𥄳',
+ 194885 => '眞',
+ 194886 => '真',
+ 194887 => '真',
+ 194888 => '睊',
+ 194889 => '䀹',
+ 194890 => '瞋',
+ 194891 => '䁆',
+ 194892 => '䂖',
+ 194893 => '𥐝',
+ 194894 => '硎',
+ 194895 => '碌',
+ 194896 => '磌',
+ 194897 => '䃣',
+ 194898 => '𥘦',
+ 194899 => '祖',
+ 194900 => '𥚚',
+ 194901 => '𥛅',
+ 194902 => '福',
+ 194903 => '秫',
+ 194904 => '䄯',
+ 194905 => '穀',
+ 194906 => '穊',
+ 194907 => '穏',
+ 194908 => '𥥼',
+ 194909 => '𥪧',
+ 194910 => '𥪧',
+ 194912 => '䈂',
+ 194913 => '𥮫',
+ 194914 => '篆',
+ 194915 => '築',
+ 194916 => '䈧',
+ 194917 => '𥲀',
+ 194918 => '糒',
+ 194919 => '䊠',
+ 194920 => '糨',
+ 194921 => '糣',
+ 194922 => '紀',
+ 194923 => '𥾆',
+ 194924 => '絣',
+ 194925 => '䌁',
+ 194926 => '緇',
+ 194927 => '縂',
+ 194928 => '繅',
+ 194929 => '䌴',
+ 194930 => '𦈨',
+ 194931 => '𦉇',
+ 194932 => '䍙',
+ 194933 => '𦋙',
+ 194934 => '罺',
+ 194935 => '𦌾',
+ 194936 => '羕',
+ 194937 => '翺',
+ 194938 => '者',
+ 194939 => '𦓚',
+ 194940 => '𦔣',
+ 194941 => '聠',
+ 194942 => '𦖨',
+ 194943 => '聰',
+ 194944 => '𣍟',
+ 194945 => '䏕',
+ 194946 => '育',
+ 194947 => '脃',
+ 194948 => '䐋',
+ 194949 => '脾',
+ 194950 => '媵',
+ 194951 => '𦞧',
+ 194952 => '𦞵',
+ 194953 => '𣎓',
+ 194954 => '𣎜',
+ 194955 => '舁',
+ 194956 => '舄',
+ 194957 => '辞',
+ 194958 => '䑫',
+ 194959 => '芑',
+ 194960 => '芋',
+ 194961 => '芝',
+ 194962 => '劳',
+ 194963 => '花',
+ 194964 => '芳',
+ 194965 => '芽',
+ 194966 => '苦',
+ 194967 => '𦬼',
+ 194968 => '若',
+ 194969 => '茝',
+ 194970 => '荣',
+ 194971 => '莭',
+ 194972 => '茣',
+ 194973 => '莽',
+ 194974 => '菧',
+ 194975 => '著',
+ 194976 => '荓',
+ 194977 => '菊',
+ 194978 => '菌',
+ 194979 => '菜',
+ 194980 => '𦰶',
+ 194981 => '𦵫',
+ 194982 => '𦳕',
+ 194983 => '䔫',
+ 194984 => '蓱',
+ 194985 => '蓳',
+ 194986 => '蔖',
+ 194987 => '𧏊',
+ 194988 => '蕤',
+ 194989 => '𦼬',
+ 194990 => '䕝',
+ 194991 => '䕡',
+ 194992 => '𦾱',
+ 194993 => '𧃒',
+ 194994 => '䕫',
+ 194995 => '虐',
+ 194996 => '虜',
+ 194997 => '虧',
+ 194998 => '虩',
+ 194999 => '蚩',
+ 195000 => '蚈',
+ 195001 => '蜎',
+ 195002 => '蛢',
+ 195003 => '蝹',
+ 195004 => '蜨',
+ 195005 => '蝫',
+ 195006 => '螆',
+ 195008 => '蟡',
+ 195009 => '蠁',
+ 195010 => '䗹',
+ 195011 => '衠',
+ 195012 => '衣',
+ 195013 => '𧙧',
+ 195014 => '裗',
+ 195015 => '裞',
+ 195016 => '䘵',
+ 195017 => '裺',
+ 195018 => '㒻',
+ 195019 => '𧢮',
+ 195020 => '𧥦',
+ 195021 => '䚾',
+ 195022 => '䛇',
+ 195023 => '誠',
+ 195024 => '諭',
+ 195025 => '變',
+ 195026 => '豕',
+ 195027 => '𧲨',
+ 195028 => '貫',
+ 195029 => '賁',
+ 195030 => '贛',
+ 195031 => '起',
+ 195032 => '𧼯',
+ 195033 => '𠠄',
+ 195034 => '跋',
+ 195035 => '趼',
+ 195036 => '跰',
+ 195037 => '𠣞',
+ 195038 => '軔',
+ 195039 => '輸',
+ 195040 => '𨗒',
+ 195041 => '𨗭',
+ 195042 => '邔',
+ 195043 => '郱',
+ 195044 => '鄑',
+ 195045 => '𨜮',
+ 195046 => '鄛',
+ 195047 => '鈸',
+ 195048 => '鋗',
+ 195049 => '鋘',
+ 195050 => '鉼',
+ 195051 => '鏹',
+ 195052 => '鐕',
+ 195053 => '𨯺',
+ 195054 => '開',
+ 195055 => '䦕',
+ 195056 => '閷',
+ 195057 => '𨵷',
+ 195058 => '䧦',
+ 195059 => '雃',
+ 195060 => '嶲',
+ 195061 => '霣',
+ 195062 => '𩅅',
+ 195063 => '𩈚',
+ 195064 => '䩮',
+ 195065 => '䩶',
+ 195066 => '韠',
+ 195067 => '𩐊',
+ 195068 => '䪲',
+ 195069 => '𩒖',
+ 195070 => '頋',
+ 195071 => '頋',
+ 195072 => '頩',
+ 195073 => '𩖶',
+ 195074 => '飢',
+ 195075 => '䬳',
+ 195076 => '餩',
+ 195077 => '馧',
+ 195078 => '駂',
+ 195079 => '駾',
+ 195080 => '䯎',
+ 195081 => '𩬰',
+ 195082 => '鬒',
+ 195083 => '鱀',
+ 195084 => '鳽',
+ 195085 => '䳎',
+ 195086 => '䳭',
+ 195087 => '鵧',
+ 195088 => '𪃎',
+ 195089 => '䳸',
+ 195090 => '𪄅',
+ 195091 => '𪈎',
+ 195092 => '𪊑',
+ 195093 => '麻',
+ 195094 => '䵖',
+ 195095 => '黹',
+ 195096 => '黾',
+ 195097 => '鼅',
+ 195098 => '鼏',
+ 195099 => '鼖',
+ 195100 => '鼻',
+ 195101 => '𪘀',
+);
diff --git a/vendor/symfony/polyfill-intl-idn/Resources/unidata/virama.php b/vendor/symfony/polyfill-intl-idn/Resources/unidata/virama.php
new file mode 100644
index 0000000..1958e37
--- /dev/null
+++ b/vendor/symfony/polyfill-intl-idn/Resources/unidata/virama.php
@@ -0,0 +1,65 @@
+ 9,
+ 2509 => 9,
+ 2637 => 9,
+ 2765 => 9,
+ 2893 => 9,
+ 3021 => 9,
+ 3149 => 9,
+ 3277 => 9,
+ 3387 => 9,
+ 3388 => 9,
+ 3405 => 9,
+ 3530 => 9,
+ 3642 => 9,
+ 3770 => 9,
+ 3972 => 9,
+ 4153 => 9,
+ 4154 => 9,
+ 5908 => 9,
+ 5940 => 9,
+ 6098 => 9,
+ 6752 => 9,
+ 6980 => 9,
+ 7082 => 9,
+ 7083 => 9,
+ 7154 => 9,
+ 7155 => 9,
+ 11647 => 9,
+ 43014 => 9,
+ 43052 => 9,
+ 43204 => 9,
+ 43347 => 9,
+ 43456 => 9,
+ 43766 => 9,
+ 44013 => 9,
+ 68159 => 9,
+ 69702 => 9,
+ 69759 => 9,
+ 69817 => 9,
+ 69939 => 9,
+ 69940 => 9,
+ 70080 => 9,
+ 70197 => 9,
+ 70378 => 9,
+ 70477 => 9,
+ 70722 => 9,
+ 70850 => 9,
+ 71103 => 9,
+ 71231 => 9,
+ 71350 => 9,
+ 71467 => 9,
+ 71737 => 9,
+ 71997 => 9,
+ 71998 => 9,
+ 72160 => 9,
+ 72244 => 9,
+ 72263 => 9,
+ 72345 => 9,
+ 72767 => 9,
+ 73028 => 9,
+ 73029 => 9,
+ 73111 => 9,
+);
diff --git a/vendor/symfony/polyfill-intl-idn/bootstrap.php b/vendor/symfony/polyfill-intl-idn/bootstrap.php
new file mode 100644
index 0000000..57c7835
--- /dev/null
+++ b/vendor/symfony/polyfill-intl-idn/bootstrap.php
@@ -0,0 +1,145 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Polyfill\Intl\Idn as p;
+
+if (extension_loaded('intl')) {
+ return;
+}
+
+if (\PHP_VERSION_ID >= 80000) {
+ return require __DIR__.'/bootstrap80.php';
+}
+
+if (!defined('U_IDNA_PROHIBITED_ERROR')) {
+ define('U_IDNA_PROHIBITED_ERROR', 66560);
+}
+if (!defined('U_IDNA_ERROR_START')) {
+ define('U_IDNA_ERROR_START', 66560);
+}
+if (!defined('U_IDNA_UNASSIGNED_ERROR')) {
+ define('U_IDNA_UNASSIGNED_ERROR', 66561);
+}
+if (!defined('U_IDNA_CHECK_BIDI_ERROR')) {
+ define('U_IDNA_CHECK_BIDI_ERROR', 66562);
+}
+if (!defined('U_IDNA_STD3_ASCII_RULES_ERROR')) {
+ define('U_IDNA_STD3_ASCII_RULES_ERROR', 66563);
+}
+if (!defined('U_IDNA_ACE_PREFIX_ERROR')) {
+ define('U_IDNA_ACE_PREFIX_ERROR', 66564);
+}
+if (!defined('U_IDNA_VERIFICATION_ERROR')) {
+ define('U_IDNA_VERIFICATION_ERROR', 66565);
+}
+if (!defined('U_IDNA_LABEL_TOO_LONG_ERROR')) {
+ define('U_IDNA_LABEL_TOO_LONG_ERROR', 66566);
+}
+if (!defined('U_IDNA_ZERO_LENGTH_LABEL_ERROR')) {
+ define('U_IDNA_ZERO_LENGTH_LABEL_ERROR', 66567);
+}
+if (!defined('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR')) {
+ define('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR', 66568);
+}
+if (!defined('U_IDNA_ERROR_LIMIT')) {
+ define('U_IDNA_ERROR_LIMIT', 66569);
+}
+if (!defined('U_STRINGPREP_PROHIBITED_ERROR')) {
+ define('U_STRINGPREP_PROHIBITED_ERROR', 66560);
+}
+if (!defined('U_STRINGPREP_UNASSIGNED_ERROR')) {
+ define('U_STRINGPREP_UNASSIGNED_ERROR', 66561);
+}
+if (!defined('U_STRINGPREP_CHECK_BIDI_ERROR')) {
+ define('U_STRINGPREP_CHECK_BIDI_ERROR', 66562);
+}
+if (!defined('IDNA_DEFAULT')) {
+ define('IDNA_DEFAULT', 0);
+}
+if (!defined('IDNA_ALLOW_UNASSIGNED')) {
+ define('IDNA_ALLOW_UNASSIGNED', 1);
+}
+if (!defined('IDNA_USE_STD3_RULES')) {
+ define('IDNA_USE_STD3_RULES', 2);
+}
+if (!defined('IDNA_CHECK_BIDI')) {
+ define('IDNA_CHECK_BIDI', 4);
+}
+if (!defined('IDNA_CHECK_CONTEXTJ')) {
+ define('IDNA_CHECK_CONTEXTJ', 8);
+}
+if (!defined('IDNA_NONTRANSITIONAL_TO_ASCII')) {
+ define('IDNA_NONTRANSITIONAL_TO_ASCII', 16);
+}
+if (!defined('IDNA_NONTRANSITIONAL_TO_UNICODE')) {
+ define('IDNA_NONTRANSITIONAL_TO_UNICODE', 32);
+}
+if (!defined('INTL_IDNA_VARIANT_2003')) {
+ define('INTL_IDNA_VARIANT_2003', 0);
+}
+if (!defined('INTL_IDNA_VARIANT_UTS46')) {
+ define('INTL_IDNA_VARIANT_UTS46', 1);
+}
+if (!defined('IDNA_ERROR_EMPTY_LABEL')) {
+ define('IDNA_ERROR_EMPTY_LABEL', 1);
+}
+if (!defined('IDNA_ERROR_LABEL_TOO_LONG')) {
+ define('IDNA_ERROR_LABEL_TOO_LONG', 2);
+}
+if (!defined('IDNA_ERROR_DOMAIN_NAME_TOO_LONG')) {
+ define('IDNA_ERROR_DOMAIN_NAME_TOO_LONG', 4);
+}
+if (!defined('IDNA_ERROR_LEADING_HYPHEN')) {
+ define('IDNA_ERROR_LEADING_HYPHEN', 8);
+}
+if (!defined('IDNA_ERROR_TRAILING_HYPHEN')) {
+ define('IDNA_ERROR_TRAILING_HYPHEN', 16);
+}
+if (!defined('IDNA_ERROR_HYPHEN_3_4')) {
+ define('IDNA_ERROR_HYPHEN_3_4', 32);
+}
+if (!defined('IDNA_ERROR_LEADING_COMBINING_MARK')) {
+ define('IDNA_ERROR_LEADING_COMBINING_MARK', 64);
+}
+if (!defined('IDNA_ERROR_DISALLOWED')) {
+ define('IDNA_ERROR_DISALLOWED', 128);
+}
+if (!defined('IDNA_ERROR_PUNYCODE')) {
+ define('IDNA_ERROR_PUNYCODE', 256);
+}
+if (!defined('IDNA_ERROR_LABEL_HAS_DOT')) {
+ define('IDNA_ERROR_LABEL_HAS_DOT', 512);
+}
+if (!defined('IDNA_ERROR_INVALID_ACE_LABEL')) {
+ define('IDNA_ERROR_INVALID_ACE_LABEL', 1024);
+}
+if (!defined('IDNA_ERROR_BIDI')) {
+ define('IDNA_ERROR_BIDI', 2048);
+}
+if (!defined('IDNA_ERROR_CONTEXTJ')) {
+ define('IDNA_ERROR_CONTEXTJ', 4096);
+}
+
+if (\PHP_VERSION_ID < 70400) {
+ if (!function_exists('idn_to_ascii')) {
+ function idn_to_ascii($domain, $flags = 0, $variant = \INTL_IDNA_VARIANT_2003, &$idna_info = null) { return p\Idn::idn_to_ascii($domain, $flags, $variant, $idna_info); }
+ }
+ if (!function_exists('idn_to_utf8')) {
+ function idn_to_utf8($domain, $flags = 0, $variant = \INTL_IDNA_VARIANT_2003, &$idna_info = null) { return p\Idn::idn_to_utf8($domain, $flags, $variant, $idna_info); }
+ }
+} else {
+ if (!function_exists('idn_to_ascii')) {
+ function idn_to_ascii($domain, $flags = 0, $variant = \INTL_IDNA_VARIANT_UTS46, &$idna_info = null) { return p\Idn::idn_to_ascii($domain, $flags, $variant, $idna_info); }
+ }
+ if (!function_exists('idn_to_utf8')) {
+ function idn_to_utf8($domain, $flags = 0, $variant = \INTL_IDNA_VARIANT_UTS46, &$idna_info = null) { return p\Idn::idn_to_utf8($domain, $flags, $variant, $idna_info); }
+ }
+}
diff --git a/vendor/symfony/polyfill-intl-idn/bootstrap80.php b/vendor/symfony/polyfill-intl-idn/bootstrap80.php
new file mode 100644
index 0000000..a62c2d6
--- /dev/null
+++ b/vendor/symfony/polyfill-intl-idn/bootstrap80.php
@@ -0,0 +1,125 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Polyfill\Intl\Idn as p;
+
+if (!defined('U_IDNA_PROHIBITED_ERROR')) {
+ define('U_IDNA_PROHIBITED_ERROR', 66560);
+}
+if (!defined('U_IDNA_ERROR_START')) {
+ define('U_IDNA_ERROR_START', 66560);
+}
+if (!defined('U_IDNA_UNASSIGNED_ERROR')) {
+ define('U_IDNA_UNASSIGNED_ERROR', 66561);
+}
+if (!defined('U_IDNA_CHECK_BIDI_ERROR')) {
+ define('U_IDNA_CHECK_BIDI_ERROR', 66562);
+}
+if (!defined('U_IDNA_STD3_ASCII_RULES_ERROR')) {
+ define('U_IDNA_STD3_ASCII_RULES_ERROR', 66563);
+}
+if (!defined('U_IDNA_ACE_PREFIX_ERROR')) {
+ define('U_IDNA_ACE_PREFIX_ERROR', 66564);
+}
+if (!defined('U_IDNA_VERIFICATION_ERROR')) {
+ define('U_IDNA_VERIFICATION_ERROR', 66565);
+}
+if (!defined('U_IDNA_LABEL_TOO_LONG_ERROR')) {
+ define('U_IDNA_LABEL_TOO_LONG_ERROR', 66566);
+}
+if (!defined('U_IDNA_ZERO_LENGTH_LABEL_ERROR')) {
+ define('U_IDNA_ZERO_LENGTH_LABEL_ERROR', 66567);
+}
+if (!defined('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR')) {
+ define('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR', 66568);
+}
+if (!defined('U_IDNA_ERROR_LIMIT')) {
+ define('U_IDNA_ERROR_LIMIT', 66569);
+}
+if (!defined('U_STRINGPREP_PROHIBITED_ERROR')) {
+ define('U_STRINGPREP_PROHIBITED_ERROR', 66560);
+}
+if (!defined('U_STRINGPREP_UNASSIGNED_ERROR')) {
+ define('U_STRINGPREP_UNASSIGNED_ERROR', 66561);
+}
+if (!defined('U_STRINGPREP_CHECK_BIDI_ERROR')) {
+ define('U_STRINGPREP_CHECK_BIDI_ERROR', 66562);
+}
+if (!defined('IDNA_DEFAULT')) {
+ define('IDNA_DEFAULT', 0);
+}
+if (!defined('IDNA_ALLOW_UNASSIGNED')) {
+ define('IDNA_ALLOW_UNASSIGNED', 1);
+}
+if (!defined('IDNA_USE_STD3_RULES')) {
+ define('IDNA_USE_STD3_RULES', 2);
+}
+if (!defined('IDNA_CHECK_BIDI')) {
+ define('IDNA_CHECK_BIDI', 4);
+}
+if (!defined('IDNA_CHECK_CONTEXTJ')) {
+ define('IDNA_CHECK_CONTEXTJ', 8);
+}
+if (!defined('IDNA_NONTRANSITIONAL_TO_ASCII')) {
+ define('IDNA_NONTRANSITIONAL_TO_ASCII', 16);
+}
+if (!defined('IDNA_NONTRANSITIONAL_TO_UNICODE')) {
+ define('IDNA_NONTRANSITIONAL_TO_UNICODE', 32);
+}
+if (!defined('INTL_IDNA_VARIANT_UTS46')) {
+ define('INTL_IDNA_VARIANT_UTS46', 1);
+}
+if (!defined('IDNA_ERROR_EMPTY_LABEL')) {
+ define('IDNA_ERROR_EMPTY_LABEL', 1);
+}
+if (!defined('IDNA_ERROR_LABEL_TOO_LONG')) {
+ define('IDNA_ERROR_LABEL_TOO_LONG', 2);
+}
+if (!defined('IDNA_ERROR_DOMAIN_NAME_TOO_LONG')) {
+ define('IDNA_ERROR_DOMAIN_NAME_TOO_LONG', 4);
+}
+if (!defined('IDNA_ERROR_LEADING_HYPHEN')) {
+ define('IDNA_ERROR_LEADING_HYPHEN', 8);
+}
+if (!defined('IDNA_ERROR_TRAILING_HYPHEN')) {
+ define('IDNA_ERROR_TRAILING_HYPHEN', 16);
+}
+if (!defined('IDNA_ERROR_HYPHEN_3_4')) {
+ define('IDNA_ERROR_HYPHEN_3_4', 32);
+}
+if (!defined('IDNA_ERROR_LEADING_COMBINING_MARK')) {
+ define('IDNA_ERROR_LEADING_COMBINING_MARK', 64);
+}
+if (!defined('IDNA_ERROR_DISALLOWED')) {
+ define('IDNA_ERROR_DISALLOWED', 128);
+}
+if (!defined('IDNA_ERROR_PUNYCODE')) {
+ define('IDNA_ERROR_PUNYCODE', 256);
+}
+if (!defined('IDNA_ERROR_LABEL_HAS_DOT')) {
+ define('IDNA_ERROR_LABEL_HAS_DOT', 512);
+}
+if (!defined('IDNA_ERROR_INVALID_ACE_LABEL')) {
+ define('IDNA_ERROR_INVALID_ACE_LABEL', 1024);
+}
+if (!defined('IDNA_ERROR_BIDI')) {
+ define('IDNA_ERROR_BIDI', 2048);
+}
+if (!defined('IDNA_ERROR_CONTEXTJ')) {
+ define('IDNA_ERROR_CONTEXTJ', 4096);
+}
+
+if (!function_exists('idn_to_ascii')) {
+ function idn_to_ascii(?string $domain, ?int $flags = IDNA_DEFAULT, ?int $variant = INTL_IDNA_VARIANT_UTS46, &$idna_info = null): string|false { return p\Idn::idn_to_ascii((string) $domain, (int) $flags, (int) $variant, $idna_info); }
+}
+if (!function_exists('idn_to_utf8')) {
+ function idn_to_utf8(?string $domain, ?int $flags = IDNA_DEFAULT, ?int $variant = INTL_IDNA_VARIANT_UTS46, &$idna_info = null): string|false { return p\Idn::idn_to_utf8((string) $domain, (int) $flags, (int) $variant, $idna_info); }
+}
diff --git a/vendor/symfony/polyfill-intl-idn/composer.json b/vendor/symfony/polyfill-intl-idn/composer.json
new file mode 100644
index 0000000..71030a2
--- /dev/null
+++ b/vendor/symfony/polyfill-intl-idn/composer.json
@@ -0,0 +1,44 @@
+{
+ "name": "symfony/polyfill-intl-idn",
+ "type": "library",
+ "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
+ "keywords": ["polyfill", "shim", "compatibility", "portable", "intl", "idn"],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Laurent Bassin",
+ "email": "laurent@bassin.info"
+ },
+ {
+ "name": "Trevor Rowbotham",
+ "email": "trevor.rowbotham@pm.me"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=7.1",
+ "symfony/polyfill-intl-normalizer": "^1.10",
+ "symfony/polyfill-php72": "^1.10"
+ },
+ "autoload": {
+ "psr-4": { "Symfony\\Polyfill\\Intl\\Idn\\": "" },
+ "files": [ "bootstrap.php" ]
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.26-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ }
+}
diff --git a/vendor/symfony/process/ExecutableFinder.php b/vendor/symfony/process/ExecutableFinder.php
index cb4345e..e2dd064 100644
--- a/vendor/symfony/process/ExecutableFinder.php
+++ b/vendor/symfony/process/ExecutableFinder.php
@@ -50,8 +50,8 @@ class ExecutableFinder
*/
public function find($name, $default = null, array $extraDirs = [])
{
- if (ini_get('open_basedir')) {
- $searchPath = array_merge(explode(PATH_SEPARATOR, ini_get('open_basedir')), $extraDirs);
+ if (\ini_get('open_basedir')) {
+ $searchPath = array_merge(explode(\PATH_SEPARATOR, \ini_get('open_basedir')), $extraDirs);
$dirs = [];
foreach ($searchPath as $path) {
// Silencing against https://bugs.php.net/69240
@@ -65,7 +65,7 @@ class ExecutableFinder
}
} else {
$dirs = array_merge(
- explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
+ explode(\PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
$extraDirs
);
}
@@ -73,7 +73,7 @@ class ExecutableFinder
$suffixes = [''];
if ('\\' === \DIRECTORY_SEPARATOR) {
$pathExt = getenv('PATHEXT');
- $suffixes = array_merge($pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes);
+ $suffixes = array_merge($pathExt ? explode(\PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes);
}
foreach ($suffixes as $suffix) {
foreach ($dirs as $dir) {
diff --git a/vendor/symfony/process/InputStream.php b/vendor/symfony/process/InputStream.php
index c952daf..4f8f713 100644
--- a/vendor/symfony/process/InputStream.php
+++ b/vendor/symfony/process/InputStream.php
@@ -45,7 +45,7 @@ class InputStream implements \IteratorAggregate
return;
}
if ($this->isClosed()) {
- throw new RuntimeException(sprintf('%s is closed', static::class));
+ throw new RuntimeException(sprintf('"%s" is closed.', static::class));
}
$this->input[] = ProcessUtils::validateInput(__METHOD__, $input);
}
@@ -69,6 +69,7 @@ class InputStream implements \IteratorAggregate
/**
* @return \Traversable
*/
+ #[\ReturnTypeWillChange]
public function getIterator()
{
$this->open = true;
diff --git a/vendor/symfony/process/LICENSE b/vendor/symfony/process/LICENSE
index 9e936ec..88bf75b 100644
--- a/vendor/symfony/process/LICENSE
+++ b/vendor/symfony/process/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2020 Fabien Potencier
+Copyright (c) 2004-2022 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/symfony/process/PhpExecutableFinder.php b/vendor/symfony/process/PhpExecutableFinder.php
index 5b8f1fc..92e0262 100644
--- a/vendor/symfony/process/PhpExecutableFinder.php
+++ b/vendor/symfony/process/PhpExecutableFinder.php
@@ -38,7 +38,7 @@ class PhpExecutableFinder
if ($php = getenv('PHP_BINARY')) {
if (!is_executable($php)) {
$command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v';
- if ($php = strtok(exec($command.' '.escapeshellarg($php)), PHP_EOL)) {
+ if ($php = strtok(exec($command.' '.escapeshellarg($php)), \PHP_EOL)) {
if (!is_executable($php)) {
return false;
}
@@ -47,6 +47,10 @@ class PhpExecutableFinder
}
}
+ if (@is_dir($php)) {
+ return false;
+ }
+
return $php;
}
@@ -54,12 +58,12 @@ class PhpExecutableFinder
$args = $includeArgs && $args ? ' '.implode(' ', $args) : '';
// PHP_BINARY return the current sapi executable
- if (PHP_BINARY && \in_array(\PHP_SAPI, ['cgi-fcgi', 'cli', 'cli-server', 'phpdbg'], true)) {
- return PHP_BINARY.$args;
+ if (\PHP_BINARY && \in_array(\PHP_SAPI, ['cgi-fcgi', 'cli', 'cli-server', 'phpdbg'], true)) {
+ return \PHP_BINARY.$args;
}
if ($php = getenv('PHP_PATH')) {
- if (!@is_executable($php)) {
+ if (!@is_executable($php) || @is_dir($php)) {
return false;
}
@@ -67,16 +71,16 @@ class PhpExecutableFinder
}
if ($php = getenv('PHP_PEAR_PHP_BIN')) {
- if (@is_executable($php)) {
+ if (@is_executable($php) && !@is_dir($php)) {
return $php;
}
}
- if (@is_executable($php = PHP_BINDIR.('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) {
+ if (@is_executable($php = \PHP_BINDIR.('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php')) && !@is_dir($php)) {
return $php;
}
- $dirs = [PHP_BINDIR];
+ $dirs = [\PHP_BINDIR];
if ('\\' === \DIRECTORY_SEPARATOR) {
$dirs[] = 'C:\xampp\php\\';
}
diff --git a/vendor/symfony/process/PhpProcess.php b/vendor/symfony/process/PhpProcess.php
index 22fc1b3..dc064e0 100644
--- a/vendor/symfony/process/PhpProcess.php
+++ b/vendor/symfony/process/PhpProcess.php
@@ -65,7 +65,7 @@ class PhpProcess extends Process
*/
public function setPhpBinary($php)
{
- @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the $php argument of the constructor instead.', __METHOD__), E_USER_DEPRECATED);
+ @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the $php argument of the constructor instead.', __METHOD__), \E_USER_DEPRECATED);
$this->setCommandLine($php);
}
diff --git a/vendor/symfony/process/Process.php b/vendor/symfony/process/Process.php
index 3b8c4cb..09cd960 100644
--- a/vendor/symfony/process/Process.php
+++ b/vendor/symfony/process/Process.php
@@ -30,30 +30,30 @@ use Symfony\Component\Process\Pipes\WindowsPipes;
*/
class Process implements \IteratorAggregate
{
- const ERR = 'err';
- const OUT = 'out';
+ public const ERR = 'err';
+ public const OUT = 'out';
- const STATUS_READY = 'ready';
- const STATUS_STARTED = 'started';
- const STATUS_TERMINATED = 'terminated';
+ public const STATUS_READY = 'ready';
+ public const STATUS_STARTED = 'started';
+ public const STATUS_TERMINATED = 'terminated';
- const STDIN = 0;
- const STDOUT = 1;
- const STDERR = 2;
+ public const STDIN = 0;
+ public const STDOUT = 1;
+ public const STDERR = 2;
// Timeout Precision in seconds.
- const TIMEOUT_PRECISION = 0.2;
+ public const TIMEOUT_PRECISION = 0.2;
- const ITER_NON_BLOCKING = 1; // By default, iterating over outputs is a blocking call, use this flag to make it non-blocking
- const ITER_KEEP_OUTPUT = 2; // By default, outputs are cleared while iterating, use this flag to keep them in memory
- const ITER_SKIP_OUT = 4; // Use this flag to skip STDOUT while iterating
- const ITER_SKIP_ERR = 8; // Use this flag to skip STDERR while iterating
+ public const ITER_NON_BLOCKING = 1; // By default, iterating over outputs is a blocking call, use this flag to make it non-blocking
+ public const ITER_KEEP_OUTPUT = 2; // By default, outputs are cleared while iterating, use this flag to keep them in memory
+ public const ITER_SKIP_OUT = 4; // Use this flag to skip STDOUT while iterating
+ public const ITER_SKIP_ERR = 8; // Use this flag to skip STDERR while iterating
private $callback;
private $hasCallback = false;
private $commandline;
private $cwd;
- private $env;
+ private $env = [];
private $input;
private $starttime;
private $lastOutputTime;
@@ -132,7 +132,7 @@ class Process implements \IteratorAggregate
* @param array $command The command to run and its arguments listed as separate entries
* @param string|null $cwd The working directory or null to use the working dir of the current PHP process
* @param array|null $env The environment variables or null to use the same environment as the current PHP process
- * @param mixed|null $input The input as stream resource, scalar or \Traversable, or null for no input
+ * @param mixed $input The input as stream resource, scalar or \Traversable, or null for no input
* @param int|float|null $timeout The timeout in seconds or null to disable
*
* @throws LogicException When proc_open is not installed
@@ -144,7 +144,7 @@ class Process implements \IteratorAggregate
}
if (!\is_array($command)) {
- @trigger_error(sprintf('Passing a command as string when creating a "%s" instance is deprecated since Symfony 4.2, pass it as an array of its arguments instead, or use the "Process::fromShellCommandline()" constructor if you need features provided by the shell.', __CLASS__), E_USER_DEPRECATED);
+ @trigger_error(sprintf('Passing a command as string when creating a "%s" instance is deprecated since Symfony 4.2, pass it as an array of its arguments instead, or use the "Process::fromShellCommandline()" constructor if you need features provided by the shell.', __CLASS__), \E_USER_DEPRECATED);
}
$this->commandline = $command;
@@ -177,13 +177,13 @@ class Process implements \IteratorAggregate
* In order to inject dynamic values into command-lines, we strongly recommend using placeholders.
* This will save escaping values, which is not portable nor secure anyway:
*
- * $process = Process::fromShellCommandline('my_command "$MY_VAR"');
+ * $process = Process::fromShellCommandline('my_command "${:MY_VAR}"');
* $process->run(null, ['MY_VAR' => $theValue]);
*
* @param string $command The command line to pass to the shell of the OS
* @param string|null $cwd The working directory or null to use the working dir of the current PHP process
* @param array|null $env The environment variables or null to use the same environment as the current PHP process
- * @param mixed|null $input The input as stream resource, scalar or \Traversable, or null for no input
+ * @param mixed $input The input as stream resource, scalar or \Traversable, or null for no input
* @param int|float|null $timeout The timeout in seconds or null to disable
*
* @return static
@@ -198,6 +198,19 @@ class Process implements \IteratorAggregate
return $process;
}
+ /**
+ * @return array
+ */
+ public function __sleep()
+ {
+ throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
+ }
+
+ public function __wakeup()
+ {
+ throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
+ }
+
public function __destruct()
{
$this->stop(0);
@@ -281,7 +294,7 @@ class Process implements \IteratorAggregate
public function start(callable $callback = null, array $env = [])
{
if ($this->isRunning()) {
- throw new RuntimeException('Process is already running');
+ throw new RuntimeException('Process is already running.');
}
$this->resetProcessData();
@@ -291,10 +304,10 @@ class Process implements \IteratorAggregate
$descriptors = $this->getDescriptors();
if ($this->env) {
- $env += $this->env;
+ $env += '\\' === \DIRECTORY_SEPARATOR ? array_diff_ukey($this->env, $env, 'strcasecmp') : $this->env;
}
- $env += $this->getDefaultEnv();
+ $env += '\\' === \DIRECTORY_SEPARATOR ? array_diff_ukey($this->getDefaultEnv(), $env, 'strcasecmp') : $this->getDefaultEnv();
if (\is_array($commandline = $this->commandline)) {
$commandline = implode(' ', array_map([$this, 'escapeArgument'], $commandline));
@@ -327,7 +340,7 @@ class Process implements \IteratorAggregate
$envPairs = [];
foreach ($env as $k => $v) {
- if (false !== $v) {
+ if (false !== $v && false === \in_array($k, ['argc', 'argv', 'ARGC', 'ARGV'], true)) {
$envPairs[] = $k.'='.$v;
}
}
@@ -336,7 +349,7 @@ class Process implements \IteratorAggregate
throw new RuntimeException(sprintf('The provided cwd "%s" does not exist.', $this->cwd));
}
- $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $options);
+ $this->process = @proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $options);
if (!\is_resource($this->process)) {
throw new RuntimeException('Unable to launch a new process.');
@@ -375,7 +388,7 @@ class Process implements \IteratorAggregate
public function restart(callable $callback = null, array $env = []): self
{
if ($this->isRunning()) {
- throw new RuntimeException('Process is already running');
+ throw new RuntimeException('Process is already running.');
}
$process = clone $this;
@@ -408,7 +421,7 @@ class Process implements \IteratorAggregate
if (null !== $callback) {
if (!$this->processPipes->haveReadSupport()) {
$this->stop(0);
- throw new LogicException('Pass the callback to the "Process::start" method or call enableOutput to use a callback with "Process::wait"');
+ throw new LogicException('Pass the callback to the "Process::start" method or call enableOutput to use a callback with "Process::wait".');
}
$this->callback = $this->buildCallback($callback);
}
@@ -609,6 +622,7 @@ class Process implements \IteratorAggregate
*
* @return \Generator
*/
+ #[\ReturnTypeWillChange]
public function getIterator($flags = 0)
{
$this->readPipesForOutput(__FUNCTION__, false);
@@ -758,7 +772,7 @@ class Process implements \IteratorAggregate
return null;
}
- return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error';
+ return self::$exitCodes[$exitcode] ?? 'Unknown error';
}
/**
@@ -938,7 +952,7 @@ class Process implements \IteratorAggregate
{
$this->lastOutputTime = microtime(true);
- fseek($this->stdout, 0, SEEK_END);
+ fseek($this->stdout, 0, \SEEK_END);
fwrite($this->stdout, $line);
fseek($this->stdout, $this->incrementalOutputOffset);
}
@@ -952,15 +966,13 @@ class Process implements \IteratorAggregate
{
$this->lastOutputTime = microtime(true);
- fseek($this->stderr, 0, SEEK_END);
+ fseek($this->stderr, 0, \SEEK_END);
fwrite($this->stderr, $line);
fseek($this->stderr, $this->incrementalErrorOutputOffset);
}
/**
* Gets the last output time in seconds.
- *
- * @return float|null The last output time in seconds or null if it isn't started
*/
public function getLastOutputTime(): ?float
{
@@ -988,7 +1000,7 @@ class Process implements \IteratorAggregate
*/
public function setCommandLine($commandline)
{
- @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED);
+ @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2.', __METHOD__), \E_USER_DEPRECATED);
$this->commandline = $commandline;
@@ -1157,25 +1169,12 @@ class Process implements \IteratorAggregate
/**
* Sets the environment variables.
*
- * Each environment variable value should be a string.
- * If it is an array, the variable is ignored.
- * If it is false or null, it will be removed when
- * env vars are otherwise inherited.
- *
- * That happens in PHP when 'argv' is registered into
- * the $_ENV array for instance.
- *
- * @param array $env The new environment variables
+ * @param array $env The new environment variables
*
* @return $this
*/
public function setEnv(array $env)
{
- // Process can not handle env values that are arrays
- $env = array_filter($env, function ($value) {
- return !\is_array($value);
- });
-
$this->env = $env;
return $this;
@@ -1224,7 +1223,7 @@ class Process implements \IteratorAggregate
*/
public function inheritEnvironmentVariables($inheritEnv = true)
{
- @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.4, env variables are always inherited.', __METHOD__), E_USER_DEPRECATED);
+ @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.4, env variables are always inherited.', __METHOD__), \E_USER_DEPRECATED);
if (!$inheritEnv) {
throw new InvalidArgumentException('Not inheriting environment variables is not supported.');
@@ -1383,9 +1382,9 @@ class Process implements \IteratorAggregate
}
ob_start();
- phpinfo(INFO_GENERAL);
+ phpinfo(\INFO_GENERAL);
- return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
+ return self::$sigchild = str_contains(ob_get_clean(), '--enable-sigchild');
}
/**
@@ -1487,8 +1486,8 @@ class Process implements \IteratorAggregate
$this->exitcode = null;
$this->fallbackStatus = [];
$this->processInformation = null;
- $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+b');
- $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+b');
+ $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+');
+ $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+');
$this->process = null;
$this->latestSignal = null;
$this->status = self::STATUS_READY;
@@ -1502,8 +1501,6 @@ class Process implements \IteratorAggregate
* @param int $signal A valid POSIX signal (see https://php.net/pcntl.constants)
* @param bool $throwException Whether to throw exception in case signal failed
*
- * @return bool True if the signal was sent successfully, false otherwise
- *
* @throws LogicException In case the process is not running
* @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed
* @throws RuntimeException In case of failure
@@ -1572,7 +1569,7 @@ class Process implements \IteratorAggregate
if (isset($varCache[$m[0]])) {
return $varCache[$m[0]];
}
- if (false !== strpos($value = $m[1], "\0")) {
+ if (str_contains($value = $m[1], "\0")) {
$value = str_replace("\0", '?', $value);
}
if (false === strpbrk($value, "\"%!\n")) {
@@ -1606,7 +1603,7 @@ class Process implements \IteratorAggregate
private function requireProcessIsStarted(string $functionName)
{
if (!$this->isStarted()) {
- throw new LogicException(sprintf('Process must be started before calling %s.', $functionName));
+ throw new LogicException(sprintf('Process must be started before calling "%s()".', $functionName));
}
}
@@ -1618,7 +1615,7 @@ class Process implements \IteratorAggregate
private function requireProcessIsTerminated(string $functionName)
{
if (!$this->isTerminated()) {
- throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName));
+ throw new LogicException(sprintf('Process must be terminated before calling "%s()".', $functionName));
}
}
@@ -1633,7 +1630,7 @@ class Process implements \IteratorAggregate
if ('\\' !== \DIRECTORY_SEPARATOR) {
return "'".str_replace("'", "'\\''", $argument)."'";
}
- if (false !== strpos($argument, "\0")) {
+ if (str_contains($argument, "\0")) {
$argument = str_replace("\0", '?', $argument);
}
if (!preg_match('/[\/()%!^"<>&|\s]/', $argument)) {
@@ -1648,7 +1645,7 @@ class Process implements \IteratorAggregate
{
return preg_replace_callback('/"\$\{:([_a-zA-Z]++[_a-zA-Z0-9]*+)\}"/', function ($matches) use ($commandline, $env) {
if (!isset($env[$matches[1]]) || false === $env[$matches[1]]) {
- throw new InvalidArgumentException(sprintf('Command line is missing a value for parameter "%s": %s.', $matches[1], $commandline));
+ throw new InvalidArgumentException(sprintf('Command line is missing a value for parameter "%s": ', $matches[1]).$commandline);
}
return $this->escapeArgument($env[$matches[1]]);
@@ -1657,20 +1654,9 @@ class Process implements \IteratorAggregate
private function getDefaultEnv(): array
{
- $env = [];
+ $env = getenv();
+ $env = ('\\' === \DIRECTORY_SEPARATOR ? array_intersect_ukey($env, $_SERVER, 'strcasecmp') : array_intersect_key($env, $_SERVER)) ?: $env;
- foreach ($_SERVER as $k => $v) {
- if (\is_string($v) && false !== $v = getenv($k)) {
- $env[$k] = $v;
- }
- }
-
- foreach ($_ENV as $k => $v) {
- if (\is_string($v)) {
- $env[$k] = $v;
- }
- }
-
- return $env;
+ return $_ENV + ('\\' === \DIRECTORY_SEPARATOR ? array_diff_ukey($env, $_ENV, 'strcasecmp') : $env);
}
}
diff --git a/vendor/symfony/process/ProcessUtils.php b/vendor/symfony/process/ProcessUtils.php
index 2f9c4be..121693b 100644
--- a/vendor/symfony/process/ProcessUtils.php
+++ b/vendor/symfony/process/ProcessUtils.php
@@ -48,7 +48,7 @@ class ProcessUtils
if (\is_string($input)) {
return $input;
}
- if (is_scalar($input)) {
+ if (\is_scalar($input)) {
return (string) $input;
}
if ($input instanceof Process) {
@@ -61,7 +61,7 @@ class ProcessUtils
return new \IteratorIterator($input);
}
- throw new InvalidArgumentException(sprintf('%s only accepts strings, Traversable objects or stream resources.', $caller));
+ throw new InvalidArgumentException(sprintf('"%s" only accepts strings, Traversable objects or stream resources.', $caller));
}
return $input;
diff --git a/vendor/symfony/process/README.md b/vendor/symfony/process/README.md
index b7ca5b4..afce5e4 100644
--- a/vendor/symfony/process/README.md
+++ b/vendor/symfony/process/README.md
@@ -6,8 +6,8 @@ The Process component executes commands in sub-processes.
Resources
---------
- * [Documentation](https://symfony.com/doc/current/components/process.html)
- * [Contributing](https://symfony.com/doc/current/contributing/index.html)
- * [Report issues](https://github.com/symfony/symfony/issues) and
- [send Pull Requests](https://github.com/symfony/symfony/pulls)
- in the [main Symfony repository](https://github.com/symfony/symfony)
+ * [Documentation](https://symfony.com/doc/current/components/process.html)
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/symfony/issues) and
+ [send Pull Requests](https://github.com/symfony/symfony/pulls)
+ in the [main Symfony repository](https://github.com/symfony/symfony)
diff --git a/vendor/symfony/process/composer.json b/vendor/symfony/process/composer.json
index e0174de..c0f7599 100644
--- a/vendor/symfony/process/composer.json
+++ b/vendor/symfony/process/composer.json
@@ -1,7 +1,7 @@
{
"name": "symfony/process",
"type": "library",
- "description": "Symfony Process Component",
+ "description": "Executes commands in sub-processes",
"keywords": [],
"homepage": "https://symfony.com",
"license": "MIT",
@@ -16,7 +16,8 @@
}
],
"require": {
- "php": "^7.1.3"
+ "php": ">=7.1.3",
+ "symfony/polyfill-php80": "^1.16"
},
"autoload": {
"psr-4": { "Symfony\\Component\\Process\\": "" },
@@ -24,10 +25,5 @@
"/Tests/"
]
},
- "minimum-stability": "dev",
- "extra": {
- "branch-alias": {
- "dev-master": "4.4-dev"
- }
- }
+ "minimum-stability": "dev"
}
diff --git a/vendor/symfony/property-info/DependencyInjection/PropertyInfoConstructorPass.php b/vendor/symfony/property-info/DependencyInjection/PropertyInfoConstructorPass.php
new file mode 100644
index 0000000..2fb4f94
--- /dev/null
+++ b/vendor/symfony/property-info/DependencyInjection/PropertyInfoConstructorPass.php
@@ -0,0 +1,50 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\PropertyInfo\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+ * Adds extractors to the property_info.constructor_extractor service.
+ *
+ * @author Dmitrii Poddubnyi
+ */
+final class PropertyInfoConstructorPass implements CompilerPassInterface
+{
+ use PriorityTaggedServiceTrait;
+
+ private $service;
+ private $tag;
+
+ public function __construct(string $service = 'property_info.constructor_extractor', string $tag = 'property_info.constructor_extractor')
+ {
+ $this->service = $service;
+ $this->tag = $tag;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition($this->service)) {
+ return;
+ }
+ $definition = $container->getDefinition($this->service);
+
+ $listExtractors = $this->findAndSortTaggedServices($this->tag, $container);
+ $definition->replaceArgument(0, new IteratorArgument($listExtractors));
+ }
+}
diff --git a/vendor/symfony/property-info/Extractor/ConstructorArgumentTypeExtractorInterface.php b/vendor/symfony/property-info/Extractor/ConstructorArgumentTypeExtractorInterface.php
new file mode 100644
index 0000000..cbde902
--- /dev/null
+++ b/vendor/symfony/property-info/Extractor/ConstructorArgumentTypeExtractorInterface.php
@@ -0,0 +1,33 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\PropertyInfo\Extractor;
+
+use Symfony\Component\PropertyInfo\Type;
+
+/**
+ * Infers the constructor argument type.
+ *
+ * @author Dmitrii Poddubnyi
+ *
+ * @internal
+ */
+interface ConstructorArgumentTypeExtractorInterface
+{
+ /**
+ * Gets types of an argument from constructor.
+ *
+ * @return Type[]|null
+ *
+ * @internal
+ */
+ public function getTypesFromConstructor(string $class, string $property): ?array;
+}
diff --git a/vendor/symfony/property-info/Extractor/ConstructorExtractor.php b/vendor/symfony/property-info/Extractor/ConstructorExtractor.php
new file mode 100644
index 0000000..702251c
--- /dev/null
+++ b/vendor/symfony/property-info/Extractor/ConstructorExtractor.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\PropertyInfo\Extractor;
+
+use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
+
+/**
+ * Extracts the constructor argument type using ConstructorArgumentTypeExtractorInterface implementations.
+ *
+ * @author Dmitrii Poddubnyi
+ */
+final class ConstructorExtractor implements PropertyTypeExtractorInterface
+{
+ /** @var iterable|ConstructorArgumentTypeExtractorInterface[] */
+ private $extractors;
+
+ /**
+ * @param iterable|ConstructorArgumentTypeExtractorInterface[] $extractors
+ */
+ public function __construct(iterable $extractors = [])
+ {
+ $this->extractors = $extractors;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getTypes($class, $property, array $context = [])
+ {
+ foreach ($this->extractors as $extractor) {
+ $value = $extractor->getTypesFromConstructor($class, $property);
+ if (null !== $value) {
+ return $value;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/vendor/symfony/psr-http-message-bridge/.github/workflows/ci.yml b/vendor/symfony/psr-http-message-bridge/.github/workflows/ci.yml
new file mode 100644
index 0000000..4c0e8ae
--- /dev/null
+++ b/vendor/symfony/psr-http-message-bridge/.github/workflows/ci.yml
@@ -0,0 +1,49 @@
+name: CI
+
+on:
+ pull_request:
+ push:
+
+jobs:
+ test:
+ name: 'Test ${{ matrix.deps }} on PHP ${{ matrix.php }}'
+ runs-on: ubuntu-latest
+
+ strategy:
+ fail-fast: false
+ matrix:
+ php: ['7.1.3', '7.2', '7.3', '7.4', '8.0', '8.1']
+ include:
+ - php: '7.4'
+ deps: lowest
+ deprecations: max[self]=0
+ - php: '8.0'
+ deps: highest
+ deprecations: max[indirect]=5
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '${{ matrix.php }}'
+ coverage: none
+
+ - name: Configure composer
+ if: "${{ matrix.deps == 'highest' }}"
+ run: composer config minimum-stability dev
+
+ - name: Composer install
+ uses: ramsey/composer-install@v1
+ with:
+ dependency-versions: '${{ matrix.deps }}'
+
+ - name: Install PHPUnit
+ run: vendor/bin/simple-phpunit install
+
+ - name: Run tests
+ run: vendor/bin/simple-phpunit
+ env:
+ SYMFONY_DEPRECATIONS_HELPER: '${{ matrix.deprecations }}'
diff --git a/vendor/symfony/psr-http-message-bridge/ArgumentValueResolver/PsrServerRequestResolver.php b/vendor/symfony/psr-http-message-bridge/ArgumentValueResolver/PsrServerRequestResolver.php
new file mode 100644
index 0000000..29dc7dc
--- /dev/null
+++ b/vendor/symfony/psr-http-message-bridge/ArgumentValueResolver/PsrServerRequestResolver.php
@@ -0,0 +1,58 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bridge\PsrHttpMessage\ArgumentValueResolver;
+
+use Psr\Http\Message\MessageInterface;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
+use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
+
+/**
+ * Injects the RequestInterface, MessageInterface or ServerRequestInterface when requested.
+ *
+ * @author Iltar van der Berg
+ * @author Alexander M. Turek
+ */
+final class PsrServerRequestResolver implements ArgumentValueResolverInterface
+{
+ private const SUPPORTED_TYPES = [
+ ServerRequestInterface::class => true,
+ RequestInterface::class => true,
+ MessageInterface::class => true,
+ ];
+
+ private $httpMessageFactory;
+
+ public function __construct(HttpMessageFactoryInterface $httpMessageFactory)
+ {
+ $this->httpMessageFactory = $httpMessageFactory;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function supports(Request $request, ArgumentMetadata $argument): bool
+ {
+ return self::SUPPORTED_TYPES[$argument->getType()] ?? false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function resolve(Request $request, ArgumentMetadata $argument): \Traversable
+ {
+ yield $this->httpMessageFactory->createRequest($request);
+ }
+}
diff --git a/vendor/symfony/psr-http-message-bridge/EventListener/PsrResponseListener.php b/vendor/symfony/psr-http-message-bridge/EventListener/PsrResponseListener.php
new file mode 100644
index 0000000..ee0e047
--- /dev/null
+++ b/vendor/symfony/psr-http-message-bridge/EventListener/PsrResponseListener.php
@@ -0,0 +1,50 @@
+
+ * @author Alexander M. Turek
+ */
+final class PsrResponseListener implements EventSubscriberInterface
+{
+ private $httpFoundationFactory;
+
+ public function __construct(HttpFoundationFactoryInterface $httpFoundationFactory = null)
+ {
+ $this->httpFoundationFactory = $httpFoundationFactory ?? new HttpFoundationFactory();
+ }
+
+ /**
+ * Do the conversion if applicable and update the response of the event.
+ */
+ public function onKernelView(ViewEvent $event): void
+ {
+ $controllerResult = $event->getControllerResult();
+
+ if (!$controllerResult instanceof ResponseInterface) {
+ return;
+ }
+
+ $event->setResponse($this->httpFoundationFactory->createResponse($controllerResult));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getSubscribedEvents(): array
+ {
+ return [
+ KernelEvents::VIEW => 'onKernelView',
+ ];
+ }
+}
diff --git a/vendor/symfony/psr-http-message-bridge/Factory/UploadedFile.php b/vendor/symfony/psr-http-message-bridge/Factory/UploadedFile.php
new file mode 100644
index 0000000..53aa37a
--- /dev/null
+++ b/vendor/symfony/psr-http-message-bridge/Factory/UploadedFile.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\Bridge\PsrHttpMessage\Factory;
+
+use Psr\Http\Message\UploadedFileInterface;
+use Symfony\Component\HttpFoundation\File\Exception\FileException;
+use Symfony\Component\HttpFoundation\File\File;
+use Symfony\Component\HttpFoundation\File\UploadedFile as BaseUploadedFile;
+
+/**
+ * @author Nicolas Grekas
+ */
+class UploadedFile extends BaseUploadedFile
+{
+ private $psrUploadedFile;
+ private $test = false;
+
+ public function __construct(UploadedFileInterface $psrUploadedFile, callable $getTemporaryPath)
+ {
+ $error = $psrUploadedFile->getError();
+ $path = '';
+
+ if (\UPLOAD_ERR_NO_FILE !== $error) {
+ $path = $psrUploadedFile->getStream()->getMetadata('uri') ?? '';
+
+ if ($this->test = !\is_string($path) || !is_uploaded_file($path)) {
+ $path = $getTemporaryPath();
+ $psrUploadedFile->moveTo($path);
+ }
+ }
+
+ parent::__construct(
+ $path,
+ (string) $psrUploadedFile->getClientFilename(),
+ $psrUploadedFile->getClientMediaType(),
+ $psrUploadedFile->getError(),
+ $this->test
+ );
+
+ $this->psrUploadedFile = $psrUploadedFile;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function move($directory, $name = null): File
+ {
+ if (!$this->isValid() || $this->test) {
+ return parent::move($directory, $name);
+ }
+
+ $target = $this->getTargetFile($directory, $name);
+
+ try {
+ $this->psrUploadedFile->moveTo($target);
+ } catch (\RuntimeException $e) {
+ throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, $e->getMessage()), 0, $e);
+ }
+
+ @chmod($target, 0666 & ~umask());
+
+ return $target;
+ }
+}
diff --git a/vendor/symfony/psr-http-message-bridge/Tests/ArgumentValueResolver/PsrServerRequestResolverTest.php b/vendor/symfony/psr-http-message-bridge/Tests/ArgumentValueResolver/PsrServerRequestResolverTest.php
new file mode 100644
index 0000000..662b186
--- /dev/null
+++ b/vendor/symfony/psr-http-message-bridge/Tests/ArgumentValueResolver/PsrServerRequestResolverTest.php
@@ -0,0 +1,68 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bridge\PsrHttpMessage\Tests\ArgumentValueResolver;
+
+use PHPUnit\Framework\TestCase;
+use Psr\Http\Message\MessageInterface;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Symfony\Bridge\PsrHttpMessage\ArgumentValueResolver\PsrServerRequestResolver;
+use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
+
+/**
+ * @author Alexander M. Turek
+ */
+final class PsrServerRequestResolverTest extends TestCase
+{
+ public function testServerRequest()
+ {
+ $symfonyRequest = $this->createMock(Request::class);
+ $psrRequest = $this->createMock(ServerRequestInterface::class);
+
+ $resolver = $this->bootstrapResolver($symfonyRequest, $psrRequest);
+
+ self::assertSame([$psrRequest], $resolver->getArguments($symfonyRequest, static function (ServerRequestInterface $serverRequest): void {}));
+ }
+
+ public function testRequest()
+ {
+ $symfonyRequest = $this->createMock(Request::class);
+ $psrRequest = $this->createMock(ServerRequestInterface::class);
+
+ $resolver = $this->bootstrapResolver($symfonyRequest, $psrRequest);
+
+ self::assertSame([$psrRequest], $resolver->getArguments($symfonyRequest, static function (RequestInterface $request): void {}));
+ }
+
+ public function testMessage()
+ {
+ $symfonyRequest = $this->createMock(Request::class);
+ $psrRequest = $this->createMock(ServerRequestInterface::class);
+
+ $resolver = $this->bootstrapResolver($symfonyRequest, $psrRequest);
+
+ self::assertSame([$psrRequest], $resolver->getArguments($symfonyRequest, static function (MessageInterface $request): void {}));
+ }
+
+ private function bootstrapResolver(Request $symfonyRequest, ServerRequestInterface $psrRequest): ArgumentResolver
+ {
+ $messageFactory = $this->createMock(HttpMessageFactoryInterface::class);
+ $messageFactory->expects(self::once())
+ ->method('createRequest')
+ ->with(self::identicalTo($symfonyRequest))
+ ->willReturn($psrRequest);
+
+ return new ArgumentResolver(null, [new PsrServerRequestResolver($messageFactory)]);
+ }
+}
diff --git a/vendor/symfony/psr-http-message-bridge/Tests/EventListener/PsrResponseListenerTest.php b/vendor/symfony/psr-http-message-bridge/Tests/EventListener/PsrResponseListenerTest.php
new file mode 100644
index 0000000..9a94b20
--- /dev/null
+++ b/vendor/symfony/psr-http-message-bridge/Tests/EventListener/PsrResponseListenerTest.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\Bridge\PsrHttpMessage\Tests\EventListener;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Bridge\PsrHttpMessage\EventListener\PsrResponseListener;
+use Symfony\Bridge\PsrHttpMessage\Tests\Fixtures\Response;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Event\ViewEvent;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+
+/**
+ * @author Kévin Dunglas
+ */
+class PsrResponseListenerTest extends TestCase
+{
+ public function testConvertsControllerResult()
+ {
+ $listener = new PsrResponseListener();
+ $event = $this->createEventMock(new Response());
+ $listener->onKernelView($event);
+
+ self::assertTrue($event->hasResponse());
+ }
+
+ public function testDoesNotConvertControllerResult()
+ {
+ $listener = new PsrResponseListener();
+ $event = $this->createEventMock([]);
+
+ $listener->onKernelView($event);
+ self::assertFalse($event->hasResponse());
+
+ $event = $this->createEventMock(null);
+
+ $listener->onKernelView($event);
+ self::assertFalse($event->hasResponse());
+ }
+
+ private function createEventMock($controllerResult): ViewEvent
+ {
+ return new ViewEvent($this->createMock(HttpKernelInterface::class), new Request(), HttpKernelInterface::MASTER_REQUEST, $controllerResult);
+ }
+}
diff --git a/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/App/Controller/PsrRequestController.php b/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/App/Controller/PsrRequestController.php
new file mode 100644
index 0000000..18b7741
--- /dev/null
+++ b/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/App/Controller/PsrRequestController.php
@@ -0,0 +1,45 @@
+responseFactory = $responseFactory;
+ $this->streamFactory = $streamFactory;
+ }
+
+ public function serverRequestAction(ServerRequestInterface $request): ResponseInterface
+ {
+ return $this->responseFactory
+ ->createResponse()
+ ->withBody($this->streamFactory->createStream(sprintf('%s', $request->getMethod())));
+ }
+
+ public function requestAction(RequestInterface $request): ResponseInterface
+ {
+ return $this->responseFactory
+ ->createResponse()
+ ->withStatus(403)
+ ->withBody($this->streamFactory->createStream(sprintf('%s %s', $request->getMethod(), $request->getBody()->getContents())));
+ }
+
+ public function messageAction(MessageInterface $request): ResponseInterface
+ {
+ return $this->responseFactory
+ ->createResponse()
+ ->withStatus(422)
+ ->withBody($this->streamFactory->createStream(sprintf('%s', $request->getHeader('X-My-Header')[0])));
+ }
+}
diff --git a/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/App/Kernel.php b/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/App/Kernel.php
new file mode 100644
index 0000000..aef8193
--- /dev/null
+++ b/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/App/Kernel.php
@@ -0,0 +1,76 @@
+add('server_request', '/server-request')->controller([PsrRequestController::class, 'serverRequestAction'])->methods(['GET'])
+ ->add('request', '/request')->controller([PsrRequestController::class, 'requestAction'])->methods(['POST'])
+ ->add('message', '/message')->controller([PsrRequestController::class, 'messageAction'])->methods(['PUT'])
+ ;
+ }
+
+ protected function configureContainer(ContainerConfigurator $container): void
+ {
+ $container->extension('framework', [
+ 'router' => ['utf8' => true],
+ 'secret' => 'for your eyes only',
+ 'test' => true,
+ ]);
+
+ $container->services()
+ ->set('nyholm.psr_factory', Psr17Factory::class)
+ ->alias(ResponseFactoryInterface::class, 'nyholm.psr_factory')
+ ->alias(ServerRequestFactoryInterface::class, 'nyholm.psr_factory')
+ ->alias(StreamFactoryInterface::class, 'nyholm.psr_factory')
+ ->alias(UploadedFileFactoryInterface::class, 'nyholm.psr_factory')
+ ;
+
+ $container->services()
+ ->defaults()->autowire()->autoconfigure()
+ ->set(HttpFoundationFactoryInterface::class, HttpFoundationFactory::class)
+ ->set(HttpMessageFactoryInterface::class, PsrHttpFactory::class)
+ ->set(PsrResponseListener::class)
+ ->set(PsrServerRequestResolver::class)
+ ;
+
+ $container->services()
+ ->set('logger', NullLogger::class)
+ ->set(PsrRequestController::class)->public()->autowire()
+ ;
+ }
+}
diff --git a/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/App/Kernel44.php b/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/App/Kernel44.php
new file mode 100644
index 0000000..e976ae2
--- /dev/null
+++ b/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/App/Kernel44.php
@@ -0,0 +1,67 @@
+add('/server-request', PsrRequestController::class.'::serverRequestAction')->setMethods(['GET']);
+ $routes->add('/request', PsrRequestController::class.'::requestAction')->setMethods(['POST']);
+ $routes->add('/message', PsrRequestController::class.'::messageAction')->setMethods(['PUT']);
+ }
+
+ protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void
+ {
+ $container->loadFromExtension('framework', [
+ 'secret' => 'for your eyes only',
+ 'test' => true,
+ ]);
+
+ $container->register('nyholm.psr_factory', Psr17Factory::class);
+ $container->setAlias(ResponseFactoryInterface::class, 'nyholm.psr_factory');
+ $container->setAlias(ServerRequestFactoryInterface::class, 'nyholm.psr_factory');
+ $container->setAlias(StreamFactoryInterface::class, 'nyholm.psr_factory');
+ $container->setAlias(UploadedFileFactoryInterface::class, 'nyholm.psr_factory');
+
+ $container->register(HttpFoundationFactoryInterface::class, HttpFoundationFactory::class)->setAutowired(true)->setAutoconfigured(true);
+ $container->register(HttpMessageFactoryInterface::class, PsrHttpFactory::class)->setAutowired(true)->setAutoconfigured(true);
+ $container->register(PsrResponseListener::class)->setAutowired(true)->setAutoconfigured(true);
+ $container->register(PsrServerRequestResolver::class)->setAutowired(true)->setAutoconfigured(true);
+
+ $container->register('logger', NullLogger::class);
+ $container->register(PsrRequestController::class)->setPublic(true)->setAutowired(true);
+ }
+}
diff --git a/vendor/symfony/psr-http-message-bridge/Tests/Functional/ControllerTest.php b/vendor/symfony/psr-http-message-bridge/Tests/Functional/ControllerTest.php
new file mode 100644
index 0000000..0b88405
--- /dev/null
+++ b/vendor/symfony/psr-http-message-bridge/Tests/Functional/ControllerTest.php
@@ -0,0 +1,55 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bridge\PsrHttpMessage\Tests\Functional;
+
+use Symfony\Bridge\PsrHttpMessage\Tests\Fixtures\App\Kernel;
+use Symfony\Bridge\PsrHttpMessage\Tests\Fixtures\App\Kernel44;
+use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
+use Symfony\Component\HttpKernel\Kernel as SymfonyKernel;
+
+/**
+ * @author Alexander M. Turek
+ */
+final class ControllerTest extends WebTestCase
+{
+ public function testServerRequestAction()
+ {
+ $client = self::createClient();
+ $crawler = $client->request('GET', '/server-request');
+
+ self::assertResponseStatusCodeSame(200);
+ self::assertSame('GET', $crawler->text());
+ }
+
+ public function testRequestAction()
+ {
+ $client = self::createClient();
+ $crawler = $client->request('POST', '/request', [], [], [], 'some content');
+
+ self::assertResponseStatusCodeSame(403);
+ self::assertSame('POST some content', $crawler->text());
+ }
+
+ public function testMessageAction()
+ {
+ $client = self::createClient();
+ $crawler = $client->request('PUT', '/message', [], [], ['HTTP_X_MY_HEADER' => 'some content']);
+
+ self::assertResponseStatusCodeSame(422);
+ self::assertSame('some content', $crawler->text());
+ }
+
+ protected static function getKernelClass(): string
+ {
+ return SymfonyKernel::VERSION_ID >= 50200 ? Kernel::class : Kernel44::class;
+ }
+}
diff --git a/vendor/symfony/service-contracts/Attribute/Required.php b/vendor/symfony/service-contracts/Attribute/Required.php
index 8ba6183..9df8511 100644
--- a/vendor/symfony/service-contracts/Attribute/Required.php
+++ b/vendor/symfony/service-contracts/Attribute/Required.php
@@ -11,8 +11,6 @@
namespace Symfony\Contracts\Service\Attribute;
-use Attribute;
-
/**
* A required dependency.
*
@@ -21,7 +19,7 @@ use Attribute;
*
* @author Alexander M. Turek
*/
-#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_PROPERTY)]
+#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)]
final class Required
{
}
diff --git a/vendor/symfony/service-contracts/Attribute/SubscribedService.php b/vendor/symfony/service-contracts/Attribute/SubscribedService.php
new file mode 100644
index 0000000..10d1bc3
--- /dev/null
+++ b/vendor/symfony/service-contracts/Attribute/SubscribedService.php
@@ -0,0 +1,33 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Contracts\Service\Attribute;
+
+use Symfony\Contracts\Service\ServiceSubscriberTrait;
+
+/**
+ * Use with {@see ServiceSubscriberTrait} to mark a method's return type
+ * as a subscribed service.
+ *
+ * @author Kevin Bond
+ */
+#[\Attribute(\Attribute::TARGET_METHOD)]
+final class SubscribedService
+{
+ /**
+ * @param string|null $key The key to use for the service
+ * If null, use "ClassName::methodName"
+ */
+ public function __construct(
+ public ?string $key = null
+ ) {
+ }
+}
diff --git a/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php b/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php
index 5ed9149..2a1b565 100644
--- a/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php
+++ b/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php
@@ -17,6 +17,9 @@ use Symfony\Contracts\Service\ServiceLocatorTrait;
abstract class ServiceLocatorTest extends TestCase
{
+ /**
+ * @return ContainerInterface
+ */
protected function getServiceLocator(array $factories)
{
return new class($factories) implements ContainerInterface {
@@ -67,7 +70,7 @@ abstract class ServiceLocatorTest extends TestCase
public function testThrowsOnUndefinedInternalService()
{
if (!$this->getExpectedException()) {
- $this->expectException('Psr\Container\NotFoundExceptionInterface');
+ $this->expectException(\Psr\Container\NotFoundExceptionInterface::class);
$this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.');
}
$locator = $this->getServiceLocator([
@@ -79,7 +82,7 @@ abstract class ServiceLocatorTest extends TestCase
public function testThrowsOnCircularReference()
{
- $this->expectException('Psr\Container\ContainerExceptionInterface');
+ $this->expectException(\Psr\Container\ContainerExceptionInterface::class);
$this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".');
$locator = $this->getServiceLocator([
'foo' => function () use (&$locator) { return $locator->get('bar'); },
diff --git a/vendor/symfony/string/Inflector/FrenchInflector.php b/vendor/symfony/string/Inflector/FrenchInflector.php
new file mode 100644
index 0000000..42f6125
--- /dev/null
+++ b/vendor/symfony/string/Inflector/FrenchInflector.php
@@ -0,0 +1,157 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\String\Inflector;
+
+/**
+ * French inflector.
+ *
+ * This class does only inflect nouns; not adjectives nor composed words like "soixante-dix".
+ */
+final class FrenchInflector implements InflectorInterface
+{
+ /**
+ * A list of all rules for pluralise.
+ *
+ * @see https://la-conjugaison.nouvelobs.com/regles/grammaire/le-pluriel-des-noms-121.php
+ */
+ private const PLURALIZE_REGEXP = [
+ // First entry: regexp
+ // Second entry: replacement
+
+ // Words finishing with "s", "x" or "z" are invariables
+ // Les mots finissant par "s", "x" ou "z" sont invariables
+ ['/(s|x|z)$/i', '\1'],
+
+ // Words finishing with "eau" are pluralized with a "x"
+ // Les mots finissant par "eau" prennent tous un "x" au pluriel
+ ['/(eau)$/i', '\1x'],
+
+ // Words finishing with "au" are pluralized with a "x" excepted "landau"
+ // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau"
+ ['/^(landau)$/i', '\1s'],
+ ['/(au)$/i', '\1x'],
+
+ // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu"
+ // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu"
+ ['/^(pneu|bleu|émeu)$/i', '\1s'],
+ ['/(eu)$/i', '\1x'],
+
+ // Words finishing with "al" are pluralized with a "aux" excepted
+ // Les mots finissant en "al" se terminent en "aux" sauf
+ ['/^(bal|carnaval|caracal|chacal|choral|corral|étal|festival|récital|val)$/i', '\1s'],
+ ['/al$/i', '\1aux'],
+
+ // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux
+ ['/^(aspir|b|cor|ém|ferm|soupir|trav|vant|vitr)ail$/i', '\1aux'],
+
+ // Bijou, caillou, chou, genou, hibou, joujou et pou qui prennent un x au pluriel
+ ['/^(bij|caill|ch|gen|hib|jouj|p)ou$/i', '\1oux'],
+
+ // Invariable words
+ ['/^(cinquante|soixante|mille)$/i', '\1'],
+
+ // French titles
+ ['/^(mon|ma)(sieur|dame|demoiselle|seigneur)$/', 'mes\2s'],
+ ['/^(Mon|Ma)(sieur|dame|demoiselle|seigneur)$/', 'Mes\2s'],
+ ];
+
+ /**
+ * A list of all rules for singularize.
+ */
+ private const SINGULARIZE_REGEXP = [
+ // First entry: regexp
+ // Second entry: replacement
+
+ // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux
+ ['/((aspir|b|cor|ém|ferm|soupir|trav|vant|vitr))aux$/i', '\1ail'],
+
+ // Words finishing with "eau" are pluralized with a "x"
+ // Les mots finissant par "eau" prennent tous un "x" au pluriel
+ ['/(eau)x$/i', '\1'],
+
+ // Words finishing with "al" are pluralized with a "aux" expected
+ // Les mots finissant en "al" se terminent en "aux" sauf
+ ['/(amir|anim|arsen|boc|can|capit|capor|chev|crist|génér|hopit|hôpit|idé|journ|littor|loc|m|mét|minér|princip|radic|termin)aux$/i', '\1al'],
+
+ // Words finishing with "au" are pluralized with a "x" excepted "landau"
+ // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau"
+ ['/(au)x$/i', '\1'],
+
+ // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu"
+ // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu"
+ ['/(eu)x$/i', '\1'],
+
+ // Words finishing with "ou" are pluralized with a "s" excepted bijou, caillou, chou, genou, hibou, joujou, pou
+ // Les mots finissant par "ou" prennent un "s" sauf bijou, caillou, chou, genou, hibou, joujou, pou
+ ['/(bij|caill|ch|gen|hib|jouj|p)oux$/i', '\1ou'],
+
+ // French titles
+ ['/^mes(dame|demoiselle)s$/', 'ma\1'],
+ ['/^Mes(dame|demoiselle)s$/', 'Ma\1'],
+ ['/^mes(sieur|seigneur)s$/', 'mon\1'],
+ ['/^Mes(sieur|seigneur)s$/', 'Mon\1'],
+
+ //Default rule
+ ['/s$/i', ''],
+ ];
+
+ /**
+ * A list of words which should not be inflected.
+ * This list is only used by singularize.
+ */
+ private const UNINFLECTED = '/^(abcès|accès|abus|albatros|anchois|anglais|autobus|bois|brebis|carquois|cas|chas|colis|concours|corps|cours|cyprès|décès|devis|discours|dos|embarras|engrais|entrelacs|excès|fils|fois|gâchis|gars|glas|héros|intrus|jars|jus|kermès|lacis|legs|lilas|marais|mars|matelas|mépris|mets|mois|mors|obus|os|palais|paradis|parcours|pardessus|pays|plusieurs|poids|pois|pouls|printemps|processus|progrès|puits|pus|rabais|radis|recors|recours|refus|relais|remords|remous|rictus|rhinocéros|repas|rubis|sas|secours|sens|souris|succès|talus|tapis|tas|taudis|temps|tiers|univers|velours|verglas|vernis|virus)$/i';
+
+ /**
+ * {@inheritdoc}
+ */
+ public function singularize(string $plural): array
+ {
+ if ($this->isInflectedWord($plural)) {
+ return [$plural];
+ }
+
+ foreach (self::SINGULARIZE_REGEXP as $rule) {
+ [$regexp, $replace] = $rule;
+
+ if (1 === preg_match($regexp, $plural)) {
+ return [preg_replace($regexp, $replace, $plural)];
+ }
+ }
+
+ return [$plural];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function pluralize(string $singular): array
+ {
+ if ($this->isInflectedWord($singular)) {
+ return [$singular];
+ }
+
+ foreach (self::PLURALIZE_REGEXP as $rule) {
+ [$regexp, $replace] = $rule;
+
+ if (1 === preg_match($regexp, $singular)) {
+ return [preg_replace($regexp, $replace, $singular)];
+ }
+ }
+
+ return [$singular.'s'];
+ }
+
+ private function isInflectedWord(string $word): bool
+ {
+ return 1 === preg_match(self::UNINFLECTED, $word);
+ }
+}
diff --git a/vendor/symfony/translation-contracts/Test/TranslatorTest.php b/vendor/symfony/translation-contracts/Test/TranslatorTest.php
index 5bfb0f8..a3e9b20 100644
--- a/vendor/symfony/translation-contracts/Test/TranslatorTest.php
+++ b/vendor/symfony/translation-contracts/Test/TranslatorTest.php
@@ -30,6 +30,22 @@ use Symfony\Contracts\Translation\TranslatorTrait;
*/
class TranslatorTest extends TestCase
{
+ private $defaultLocale;
+
+ protected function setUp(): void
+ {
+ $this->defaultLocale = \Locale::getDefault();
+ \Locale::setDefault('en');
+ }
+
+ protected function tearDown(): void
+ {
+ \Locale::setDefault($this->defaultLocale);
+ }
+
+ /**
+ * @return TranslatorInterface
+ */
public function getTranslator()
{
return new class() implements TranslatorInterface {
@@ -53,7 +69,18 @@ class TranslatorTest extends TestCase
public function testTransChoiceWithExplicitLocale($expected, $id, $number)
{
$translator = $this->getTranslator();
- $translator->setLocale('en');
+
+ $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number]));
+ }
+
+ /**
+ * @requires extension intl
+ *
+ * @dataProvider getTransChoiceTests
+ */
+ public function testTransChoiceWithDefaultLocale($expected, $id, $number)
+ {
+ $translator = $this->getTranslator();
$this->assertEquals($expected, $translator->trans($id, ['%count%' => $number]));
}
@@ -61,11 +88,10 @@ class TranslatorTest extends TestCase
/**
* @dataProvider getTransChoiceTests
*/
- public function testTransChoiceWithDefaultLocale($expected, $id, $number)
+ public function testTransChoiceWithEnUsPosix($expected, $id, $number)
{
- \Locale::setDefault('en');
-
$translator = $this->getTranslator();
+ $translator->setLocale('en_US_POSIX');
$this->assertEquals($expected, $translator->trans($id, ['%count%' => $number]));
}
@@ -73,7 +99,6 @@ class TranslatorTest extends TestCase
public function testGetSetLocale()
{
$translator = $this->getTranslator();
- $translator->setLocale('en');
$this->assertEquals('en', $translator->getLocale());
}
@@ -142,11 +167,11 @@ class TranslatorTest extends TestCase
/**
* @dataProvider getChooseTests
*/
- public function testChoose($expected, $id, $number)
+ public function testChoose($expected, $id, $number, $locale = null)
{
$translator = $this->getTranslator();
- $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number]));
+ $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number], null, $locale));
}
public function testReturnMessageIfExactlyOneStandardRuleIsGiven()
@@ -161,7 +186,7 @@ class TranslatorTest extends TestCase
*/
public function testThrowExceptionIfMatchingMessageCannotBeFound($id, $number)
{
- $this->expectException('InvalidArgumentException');
+ $this->expectException(\InvalidArgumentException::class);
$translator = $this->getTranslator();
$translator->trans($id, ['%count%' => $number]);
@@ -255,6 +280,18 @@ class TranslatorTest extends TestCase
['', '|', 1],
// Empty plural set (3 plural forms) from a .PO file
['', '||', 1],
+
+ // Floating values
+ ['1.5 liters', '%count% liter|%count% liters', 1.5],
+ ['1.5 litre', '%count% litre|%count% litres', 1.5, 'fr'],
+
+ // Negative values
+ ['-1 degree', '%count% degree|%count% degrees', -1],
+ ['-1 degré', '%count% degré|%count% degrés', -1],
+ ['-1.5 degrees', '%count% degree|%count% degrees', -1.5],
+ ['-1.5 degré', '%count% degré|%count% degrés', -1.5, 'fr'],
+ ['-2 degrees', '%count% degree|%count% degrees', -2],
+ ['-2 degrés', '%count% degré|%count% degrés', -2],
];
}
@@ -287,7 +324,7 @@ class TranslatorTest extends TestCase
{
return [
['1', ['ay', 'bo', 'cgg', 'dz', 'id', 'ja', 'jbo', 'ka', 'kk', 'km', 'ko', 'ky']],
- ['2', ['nl', 'fr', 'en', 'de', 'de_GE', 'hy', 'hy_AM']],
+ ['2', ['nl', 'fr', 'en', 'de', 'de_GE', 'hy', 'hy_AM', 'en_US_POSIX']],
['3', ['be', 'bs', 'cs', 'hr']],
['4', ['cy', 'mt', 'sl']],
['6', ['ar']],
@@ -325,7 +362,7 @@ class TranslatorTest extends TestCase
foreach ($matrix as $langCode => $data) {
$indexes = array_flip($data);
if ($expectSuccess) {
- $this->assertEquals($nplural, \count($indexes), "Langcode '$langCode' has '$nplural' plural forms.");
+ $this->assertCount($nplural, $indexes, "Langcode '$langCode' has '$nplural' plural forms.");
} else {
$this->assertNotEquals((int) $nplural, \count($indexes), "Langcode '$langCode' has '$nplural' plural forms.");
}
diff --git a/vendor/symfony/translation/Command/TranslationPullCommand.php b/vendor/symfony/translation/Command/TranslationPullCommand.php
new file mode 100644
index 0000000..e2e7c00
--- /dev/null
+++ b/vendor/symfony/translation/Command/TranslationPullCommand.php
@@ -0,0 +1,188 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Command;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Completion\CompletionInput;
+use Symfony\Component\Console\Completion\CompletionSuggestions;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\Translation\Catalogue\TargetOperation;
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Provider\TranslationProviderCollection;
+use Symfony\Component\Translation\Reader\TranslationReaderInterface;
+use Symfony\Component\Translation\Writer\TranslationWriterInterface;
+
+/**
+ * @author Mathieu Santostefano
+ */
+final class TranslationPullCommand extends Command
+{
+ use TranslationTrait;
+
+ protected static $defaultName = 'translation:pull';
+ protected static $defaultDescription = 'Pull translations from a given provider.';
+
+ private $providerCollection;
+ private $writer;
+ private $reader;
+ private $defaultLocale;
+ private $transPaths;
+ private $enabledLocales;
+
+ public function __construct(TranslationProviderCollection $providerCollection, TranslationWriterInterface $writer, TranslationReaderInterface $reader, string $defaultLocale, array $transPaths = [], array $enabledLocales = [])
+ {
+ $this->providerCollection = $providerCollection;
+ $this->writer = $writer;
+ $this->reader = $reader;
+ $this->defaultLocale = $defaultLocale;
+ $this->transPaths = $transPaths;
+ $this->enabledLocales = $enabledLocales;
+
+ parent::__construct();
+ }
+
+ public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
+ {
+ if ($input->mustSuggestArgumentValuesFor('provider')) {
+ $suggestions->suggestValues($this->providerCollection->keys());
+
+ return;
+ }
+
+ if ($input->mustSuggestOptionValuesFor('domains')) {
+ $provider = $this->providerCollection->get($input->getArgument('provider'));
+
+ if ($provider && method_exists($provider, 'getDomains')) {
+ $domains = $provider->getDomains();
+ $suggestions->suggestValues($domains);
+ }
+
+ return;
+ }
+
+ if ($input->mustSuggestOptionValuesFor('locales')) {
+ $suggestions->suggestValues($this->enabledLocales);
+
+ return;
+ }
+
+ if ($input->mustSuggestOptionValuesFor('format')) {
+ $suggestions->suggestValues(['php', 'xlf', 'xlf12', 'xlf20', 'po', 'mo', 'yml', 'yaml', 'ts', 'csv', 'json', 'ini', 'res']);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $keys = $this->providerCollection->keys();
+ $defaultProvider = 1 === \count($keys) ? $keys[0] : null;
+
+ $this
+ ->setDefinition([
+ new InputArgument('provider', null !== $defaultProvider ? InputArgument::OPTIONAL : InputArgument::REQUIRED, 'The provider to pull translations from.', $defaultProvider),
+ new InputOption('force', null, InputOption::VALUE_NONE, 'Override existing translations with provider ones (it will delete not synchronized messages).'),
+ new InputOption('intl-icu', null, InputOption::VALUE_NONE, 'Associated to --force option, it will write messages in "%domain%+intl-icu.%locale%.xlf" files.'),
+ new InputOption('domains', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the domains to pull.'),
+ new InputOption('locales', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the locales to pull.'),
+ new InputOption('format', null, InputOption::VALUE_OPTIONAL, 'Override the default output format.', 'xlf12'),
+ ])
+ ->setHelp(<<<'EOF'
+The %command.name%> command pulls translations from the given provider. Only
+new translations are pulled, existing ones are not overwritten.
+
+You can overwrite existing translations (and remove the missing ones on local side) by using the --force> flag:
+
+ php %command.full_name% --force provider>
+
+Full example:
+
+ php %command.full_name% provider --force --domains=messages --domains=validators --locales=en>
+
+This command pulls all translations associated with the messages> and validators> domains for the