summaryrefslogtreecommitdiffstats
path: root/vendor/ramsey/collection
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 11:30:08 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 11:30:08 +0000
commit4ce65d59ca91871cfd126497158200a818720bce (patch)
treee277def01fc7eba7dbc21c4a4ae5576e8aa2cf1f /vendor/ramsey/collection
parentInitial commit. (diff)
downloadicinga-php-library-4ce65d59ca91871cfd126497158200a818720bce.tar.xz
icinga-php-library-4ce65d59ca91871cfd126497158200a818720bce.zip
Adding upstream version 0.13.1.upstream/0.13.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--vendor/ramsey/collection/LICENSE19
-rw-r--r--vendor/ramsey/collection/composer.json105
-rw-r--r--vendor/ramsey/collection/src/AbstractArray.php190
-rw-r--r--vendor/ramsey/collection/src/AbstractCollection.php316
-rw-r--r--vendor/ramsey/collection/src/AbstractSet.php50
-rw-r--r--vendor/ramsey/collection/src/ArrayInterface.php49
-rw-r--r--vendor/ramsey/collection/src/Collection.php106
-rw-r--r--vendor/ramsey/collection/src/CollectionInterface.php205
-rw-r--r--vendor/ramsey/collection/src/DoubleEndedQueue.php187
-rw-r--r--vendor/ramsey/collection/src/DoubleEndedQueueInterface.php316
-rw-r--r--vendor/ramsey/collection/src/Exception/CollectionMismatchException.php22
-rw-r--r--vendor/ramsey/collection/src/Exception/InvalidArgumentException.php22
-rw-r--r--vendor/ramsey/collection/src/Exception/InvalidSortOrderException.php22
-rw-r--r--vendor/ramsey/collection/src/Exception/NoSuchElementException.php22
-rw-r--r--vendor/ramsey/collection/src/Exception/OutOfBoundsException.php22
-rw-r--r--vendor/ramsey/collection/src/Exception/UnsupportedOperationException.php22
-rw-r--r--vendor/ramsey/collection/src/Exception/ValueExtractionException.php22
-rw-r--r--vendor/ramsey/collection/src/GenericArray.php24
-rw-r--r--vendor/ramsey/collection/src/Map/AbstractMap.php162
-rw-r--r--vendor/ramsey/collection/src/Map/AbstractTypedMap.php69
-rw-r--r--vendor/ramsey/collection/src/Map/AssociativeArrayMap.php25
-rw-r--r--vendor/ramsey/collection/src/Map/MapInterface.php149
-rw-r--r--vendor/ramsey/collection/src/Map/NamedParameterMap.php120
-rw-r--r--vendor/ramsey/collection/src/Map/TypedMap.php137
-rw-r--r--vendor/ramsey/collection/src/Map/TypedMapInterface.php35
-rw-r--r--vendor/ramsey/collection/src/Queue.php169
-rw-r--r--vendor/ramsey/collection/src/QueueInterface.php203
-rw-r--r--vendor/ramsey/collection/src/Set.php69
-rw-r--r--vendor/ramsey/collection/src/Tool/TypeTrait.php73
-rw-r--r--vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php58
-rw-r--r--vendor/ramsey/collection/src/Tool/ValueToStringTrait.php94
31 files changed, 3084 insertions, 0 deletions
diff --git a/vendor/ramsey/collection/LICENSE b/vendor/ramsey/collection/LICENSE
new file mode 100644
index 0000000..ae15f59
--- /dev/null
+++ b/vendor/ramsey/collection/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2015-2021 Ben Ramsey <ben@benramsey.com>
+
+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/ramsey/collection/composer.json b/vendor/ramsey/collection/composer.json
new file mode 100644
index 0000000..0c5d095
--- /dev/null
+++ b/vendor/ramsey/collection/composer.json
@@ -0,0 +1,105 @@
+{
+ "name": "ramsey/collection",
+ "type": "library",
+ "description": "A PHP 7.2+ library for representing and manipulating collections.",
+ "keywords": [
+ "array",
+ "collection",
+ "hash",
+ "map",
+ "queue",
+ "set"
+ ],
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Ben Ramsey",
+ "email": "ben@benramsey.com",
+ "homepage": "https://benramsey.com"
+ }
+ ],
+ "require": {
+ "php": "^7.2 || ^8"
+ },
+ "require-dev": {
+ "captainhook/captainhook": "^5.3",
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
+ "ergebnis/composer-normalize": "^2.6",
+ "fakerphp/faker": "^1.5",
+ "hamcrest/hamcrest-php": "^2",
+ "jangregor/phpstan-prophecy": "^0.8",
+ "mockery/mockery": "^1.3",
+ "phpstan/extension-installer": "^1",
+ "phpstan/phpstan": "^0.12.32",
+ "phpstan/phpstan-mockery": "^0.12.5",
+ "phpstan/phpstan-phpunit": "^0.12.11",
+ "phpunit/phpunit": "^8.5 || ^9",
+ "psy/psysh": "^0.10.4",
+ "slevomat/coding-standard": "^6.3",
+ "squizlabs/php_codesniffer": "^3.5",
+ "vimeo/psalm": "^4.4"
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "autoload": {
+ "psr-4": {
+ "Ramsey\\Collection\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Ramsey\\Console\\": "resources/console/",
+ "Ramsey\\Collection\\Test\\": "tests/"
+ },
+ "files": [
+ "vendor/hamcrest/hamcrest-php/hamcrest/Hamcrest.php"
+ ]
+ },
+ "scripts": {
+ "post-autoload-dump": "captainhook install --ansi -f -s",
+ "br:analyze": [
+ "@br:analyze:phpstan",
+ "@br:analyze:psalm"
+ ],
+ "br:analyze:phpstan": "phpstan --memory-limit=1G analyse",
+ "br:analyze:psalm": "psalm --diff --config=psalm.xml",
+ "br:build:clean": "git clean -fX build/.",
+ "br:build:clear-cache": "git clean -fX build/cache/.",
+ "br:lint": "phpcs --cache=build/cache/phpcs.cache",
+ "br:lint:fix": "./bin/lint-fix.sh",
+ "br:repl": [
+ "echo ; echo 'Type ./bin/repl to start the REPL.'"
+ ],
+ "br:test": "phpunit",
+ "br:test:all": [
+ "@br:lint",
+ "@br:analyze",
+ "@br:test"
+ ],
+ "br:test:coverage:ci": "phpunit --coverage-clover build/logs/clover.xml",
+ "br:test:coverage:html": "phpunit --coverage-html build/coverage",
+ "pre-commit": [
+ "@br:lint:fix",
+ "@br:lint",
+ "@br:analyze"
+ ],
+ "test": "@br:test:all"
+ },
+ "scripts-descriptions": {
+ "br:analyze": "Performs static analysis on the code base.",
+ "br:analyze:phpstan": "Runs the PHPStan static analyzer.",
+ "br:analyze:psalm": "Runs the Psalm static analyzer.",
+ "br:build:clean": "Removes everything not under version control from the build directory.",
+ "br:build:clear-cache": "Removes everything not under version control from build/cache/.",
+ "br:lint": "Checks all source code for coding standards issues.",
+ "br:lint:fix": "Checks source code for coding standards issues and fixes them, if possible.",
+ "br:repl": "Note: Use ./bin/repl to run the REPL.",
+ "br:test": "Runs the full unit test suite.",
+ "br:test:all": "Runs linting, static analysis, and unit tests.",
+ "br:test:coverage:ci": "Runs the unit test suite and generates a Clover coverage report.",
+ "br:test:coverage:html": "Runs the unit tests suite and generates an HTML coverage report.",
+ "pre-commit": "These commands are run as part of a Git pre-commit hook installed using captainhook/captainhook. Each command should be prepared to accept a list of space-separated staged files.",
+ "test": "Shortcut to run the full test suite."
+ }
+}
diff --git a/vendor/ramsey/collection/src/AbstractArray.php b/vendor/ramsey/collection/src/AbstractArray.php
new file mode 100644
index 0000000..a8a164c
--- /dev/null
+++ b/vendor/ramsey/collection/src/AbstractArray.php
@@ -0,0 +1,190 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection;
+
+use ArrayIterator;
+use Traversable;
+
+use function serialize;
+use function unserialize;
+
+/**
+ * This class provides a basic implementation of `ArrayInterface`, to minimize
+ * the effort required to implement this interface.
+ *
+ * @template T
+ * @template-implements ArrayInterface<T>
+ */
+abstract class AbstractArray implements ArrayInterface
+{
+ /**
+ * The items of this array.
+ *
+ * @var array<array-key, T>
+ */
+ protected $data = [];
+
+ /**
+ * Constructs a new array object.
+ *
+ * @param array<array-key, T> $data The initial items to add to this array.
+ */
+ public function __construct(array $data = [])
+ {
+ // Invoke offsetSet() for each value added; in this way, sub-classes
+ // may provide additional logic about values added to the array object.
+ foreach ($data as $key => $value) {
+ $this[$key] = $value;
+ }
+ }
+
+ /**
+ * Returns an iterator for this array.
+ *
+ * @link http://php.net/manual/en/iteratoraggregate.getiterator.php IteratorAggregate::getIterator()
+ *
+ * @return Traversable<T>
+ */
+ public function getIterator(): Traversable
+ {
+ return new ArrayIterator($this->data);
+ }
+
+ /**
+ * Returns `true` if the given offset exists in this array.
+ *
+ * @link http://php.net/manual/en/arrayaccess.offsetexists.php ArrayAccess::offsetExists()
+ *
+ * @param array-key $offset The offset to check.
+ */
+ public function offsetExists($offset): bool
+ {
+ return isset($this->data[$offset]);
+ }
+
+ /**
+ * Returns the value at the specified offset.
+ *
+ * @link http://php.net/manual/en/arrayaccess.offsetget.php ArrayAccess::offsetGet()
+ *
+ * @param array-key $offset The offset for which a value should be returned.
+ *
+ * @return T|null the value stored at the offset, or null if the offset
+ * does not exist.
+ */
+ #[\ReturnTypeWillChange]
+ public function offsetGet($offset)
+ {
+ return $this->data[$offset] ?? null;
+ }
+
+ /**
+ * Sets the given value to the given offset in the array.
+ *
+ * @link http://php.net/manual/en/arrayaccess.offsetset.php ArrayAccess::offsetSet()
+ *
+ * @param array-key|null $offset The offset to set. If `null`, the value may be
+ * set at a numerically-indexed offset.
+ * @param T $value The value to set at the given offset.
+ */
+ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ public function offsetSet($offset, $value): void
+ {
+ if ($offset === null) {
+ $this->data[] = $value;
+ } else {
+ $this->data[$offset] = $value;
+ }
+ }
+
+ /**
+ * Removes the given offset and its value from the array.
+ *
+ * @link http://php.net/manual/en/arrayaccess.offsetunset.php ArrayAccess::offsetUnset()
+ *
+ * @param array-key $offset The offset to remove from the array.
+ */
+ public function offsetUnset($offset): void
+ {
+ unset($this->data[$offset]);
+ }
+
+ /**
+ * Returns a serialized string representation of this array object.
+ *
+ * @link http://php.net/manual/en/serializable.serialize.php Serializable::serialize()
+ *
+ * @return string a PHP serialized string.
+ */
+ public function serialize(): string
+ {
+ return serialize($this->data);
+ }
+
+ public function __serialize()
+ {
+ return $this->serialize();
+ }
+
+ /**
+ * Converts a serialized string representation into an instance object.
+ *
+ * @link http://php.net/manual/en/serializable.unserialize.php Serializable::unserialize()
+ *
+ * @param string $serialized A PHP serialized string to unserialize.
+ *
+ * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ */
+ public function unserialize($serialized): void
+ {
+ /** @var array<array-key, T> $data */
+ $data = unserialize($serialized, ['allowed_classes' => false]);
+
+ $this->data = $data;
+ }
+
+ public function __unserialize(array $data)
+ {
+ $this->unserialize($data);
+ }
+
+ /**
+ * Returns the number of items in this array.
+ *
+ * @link http://php.net/manual/en/countable.count.php Countable::count()
+ */
+ public function count(): int
+ {
+ return count($this->data);
+ }
+
+ public function clear(): void
+ {
+ $this->data = [];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function toArray(): array
+ {
+ return $this->data;
+ }
+
+ public function isEmpty(): bool
+ {
+ return count($this->data) === 0;
+ }
+}
diff --git a/vendor/ramsey/collection/src/AbstractCollection.php b/vendor/ramsey/collection/src/AbstractCollection.php
new file mode 100644
index 0000000..f803f42
--- /dev/null
+++ b/vendor/ramsey/collection/src/AbstractCollection.php
@@ -0,0 +1,316 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection;
+
+use Closure;
+use Ramsey\Collection\Exception\CollectionMismatchException;
+use Ramsey\Collection\Exception\InvalidArgumentException;
+use Ramsey\Collection\Exception\InvalidSortOrderException;
+use Ramsey\Collection\Exception\OutOfBoundsException;
+use Ramsey\Collection\Tool\TypeTrait;
+use Ramsey\Collection\Tool\ValueExtractorTrait;
+use Ramsey\Collection\Tool\ValueToStringTrait;
+
+use function array_filter;
+use function array_map;
+use function array_merge;
+use function array_search;
+use function array_udiff;
+use function array_uintersect;
+use function current;
+use function end;
+use function in_array;
+use function reset;
+use function sprintf;
+use function unserialize;
+use function usort;
+
+/**
+ * This class provides a basic implementation of `CollectionInterface`, to
+ * minimize the effort required to implement this interface
+ *
+ * @template T
+ * @template-extends AbstractArray<T>
+ * @template-implements CollectionInterface<T>
+ */
+abstract class AbstractCollection extends AbstractArray implements CollectionInterface
+{
+ use TypeTrait;
+ use ValueToStringTrait;
+ use ValueExtractorTrait;
+
+ /**
+ * @inheritDoc
+ */
+ public function add($element): bool
+ {
+ $this[] = $element;
+
+ return true;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function contains($element, bool $strict = true): bool
+ {
+ return in_array($element, $this->data, $strict);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function offsetSet($offset, $value): void
+ {
+ if ($this->checkType($this->getType(), $value) === false) {
+ throw new InvalidArgumentException(
+ 'Value must be of type ' . $this->getType() . '; value is '
+ . $this->toolValueToString($value)
+ );
+ }
+
+ if ($offset === null) {
+ $this->data[] = $value;
+ } else {
+ $this->data[$offset] = $value;
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function remove($element): bool
+ {
+ if (($position = array_search($element, $this->data, true)) !== false) {
+ unset($this->data[$position]);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function column(string $propertyOrMethod): array
+ {
+ $temp = [];
+
+ foreach ($this->data as $item) {
+ /** @var mixed $value */
+ $value = $this->extractValue($item, $propertyOrMethod);
+
+ /** @psalm-suppress MixedAssignment */
+ $temp[] = $value;
+ }
+
+ return $temp;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function first()
+ {
+ if ($this->isEmpty()) {
+ throw new OutOfBoundsException('Can\'t determine first item. Collection is empty');
+ }
+
+ reset($this->data);
+
+ /** @var T $first */
+ $first = current($this->data);
+
+ return $first;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function last()
+ {
+ if ($this->isEmpty()) {
+ throw new OutOfBoundsException('Can\'t determine last item. Collection is empty');
+ }
+
+ /** @var T $item */
+ $item = end($this->data);
+ reset($this->data);
+
+ return $item;
+ }
+
+ public function sort(string $propertyOrMethod, string $order = self::SORT_ASC): CollectionInterface
+ {
+ if (!in_array($order, [self::SORT_ASC, self::SORT_DESC], true)) {
+ throw new InvalidSortOrderException('Invalid sort order given: ' . $order);
+ }
+
+ $collection = clone $this;
+
+ usort(
+ $collection->data,
+ /**
+ * @param T $a
+ * @param T $b
+ */
+ function ($a, $b) use ($propertyOrMethod, $order): int {
+ /** @var mixed $aValue */
+ $aValue = $this->extractValue($a, $propertyOrMethod);
+
+ /** @var mixed $bValue */
+ $bValue = $this->extractValue($b, $propertyOrMethod);
+
+ return ($aValue <=> $bValue) * ($order === self::SORT_DESC ? -1 : 1);
+ }
+ );
+
+ return $collection;
+ }
+
+ public function filter(callable $callback): CollectionInterface
+ {
+ $collection = clone $this;
+ $collection->data = array_merge([], array_filter($collection->data, $callback));
+
+ return $collection;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function where(string $propertyOrMethod, $value): CollectionInterface
+ {
+ return $this->filter(function ($item) use ($propertyOrMethod, $value) {
+ /** @var mixed $accessorValue */
+ $accessorValue = $this->extractValue($item, $propertyOrMethod);
+
+ return $accessorValue === $value;
+ });
+ }
+
+ public function map(callable $callback): CollectionInterface
+ {
+ return new Collection('mixed', array_map($callback, $this->data));
+ }
+
+ public function diff(CollectionInterface $other): CollectionInterface
+ {
+ $this->compareCollectionTypes($other);
+
+ $diffAtoB = array_udiff($this->data, $other->toArray(), $this->getComparator());
+ $diffBtoA = array_udiff($other->toArray(), $this->data, $this->getComparator());
+
+ /** @var array<array-key, T> $diff */
+ $diff = array_merge($diffAtoB, $diffBtoA);
+
+ $collection = clone $this;
+ $collection->data = $diff;
+
+ return $collection;
+ }
+
+ public function intersect(CollectionInterface $other): CollectionInterface
+ {
+ $this->compareCollectionTypes($other);
+
+ /** @var array<array-key, T> $intersect */
+ $intersect = array_uintersect($this->data, $other->toArray(), $this->getComparator());
+
+ $collection = clone $this;
+ $collection->data = $intersect;
+
+ return $collection;
+ }
+
+ public function merge(CollectionInterface ...$collections): CollectionInterface
+ {
+ $temp = [$this->data];
+
+ foreach ($collections as $index => $collection) {
+ if (!$collection instanceof static) {
+ throw new CollectionMismatchException(
+ sprintf('Collection with index %d must be of type %s', $index, static::class)
+ );
+ }
+
+ // When using generics (Collection.php, Set.php, etc),
+ // we also need to make sure that the internal types match each other
+ if ($collection->getType() !== $this->getType()) {
+ throw new CollectionMismatchException(
+ sprintf('Collection items in collection with index %d must be of type %s', $index, $this->getType())
+ );
+ }
+
+ $temp[] = $collection->toArray();
+ }
+
+ $merge = array_merge(...$temp);
+
+ $collection = clone $this;
+ $collection->data = $merge;
+
+ return $collection;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function unserialize($serialized): void
+ {
+ /** @var array<array-key, T> $data */
+ $data = unserialize($serialized, ['allowed_classes' => [$this->getType()]]);
+
+ $this->data = $data;
+ }
+
+ /**
+ * @param CollectionInterface<T> $other
+ */
+ private function compareCollectionTypes(CollectionInterface $other): void
+ {
+ if (!$other instanceof static) {
+ throw new CollectionMismatchException('Collection must be of type ' . static::class);
+ }
+
+ // When using generics (Collection.php, Set.php, etc),
+ // we also need to make sure that the internal types match each other
+ if ($other->getType() !== $this->getType()) {
+ throw new CollectionMismatchException('Collection items must be of type ' . $this->getType());
+ }
+ }
+
+ private function getComparator(): Closure
+ {
+ return /**
+ * @param T $a
+ * @param T $b
+ */
+ function ($a, $b): int {
+ // If the two values are object, we convert them to unique scalars.
+ // If the collection contains mixed values (unlikely) where some are objects
+ // and some are not, we leave them as they are.
+ // The comparator should still work and the result of $a < $b should
+ // be consistent but unpredictable since not documented.
+ if (is_object($a) && is_object($b)) {
+ $a = spl_object_id($a);
+ $b = spl_object_id($b);
+ }
+
+ return $a === $b ? 0 : ($a < $b ? 1 : -1);
+ };
+ }
+}
diff --git a/vendor/ramsey/collection/src/AbstractSet.php b/vendor/ramsey/collection/src/AbstractSet.php
new file mode 100644
index 0000000..3bd2296
--- /dev/null
+++ b/vendor/ramsey/collection/src/AbstractSet.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection;
+
+/**
+ * This class contains the basic implementation of a collection that does not
+ * allow duplicated values (a set), to minimize the effort required to implement
+ * this specific type of collection.
+ *
+ * @template T
+ * @template-extends AbstractCollection<T>
+ */
+abstract class AbstractSet extends AbstractCollection
+{
+ /**
+ * @inheritDoc
+ */
+ public function add($element): bool
+ {
+ if ($this->contains($element)) {
+ return false;
+ }
+
+ return parent::add($element);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function offsetSet($offset, $value): void
+ {
+ if ($this->contains($value)) {
+ return;
+ }
+
+ parent::offsetSet($offset, $value);
+ }
+}
diff --git a/vendor/ramsey/collection/src/ArrayInterface.php b/vendor/ramsey/collection/src/ArrayInterface.php
new file mode 100644
index 0000000..19fbff3
--- /dev/null
+++ b/vendor/ramsey/collection/src/ArrayInterface.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection;
+
+use ArrayAccess;
+use Countable;
+use IteratorAggregate;
+use Serializable;
+
+/**
+ * `ArrayInterface` provides traversable array functionality to data types.
+ *
+ * @template T
+ */
+interface ArrayInterface extends
+ ArrayAccess,
+ Countable,
+ IteratorAggregate,
+ Serializable
+{
+ /**
+ * Removes all items from this array.
+ */
+ public function clear(): void;
+
+ /**
+ * Returns a native PHP array representation of this array object.
+ *
+ * @return array<array-key, T>
+ */
+ public function toArray(): array;
+
+ /**
+ * Returns `true` if this array is empty.
+ */
+ public function isEmpty(): bool;
+}
diff --git a/vendor/ramsey/collection/src/Collection.php b/vendor/ramsey/collection/src/Collection.php
new file mode 100644
index 0000000..2f8dedd
--- /dev/null
+++ b/vendor/ramsey/collection/src/Collection.php
@@ -0,0 +1,106 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection;
+
+/**
+ * A collection represents a group of objects.
+ *
+ * Each object in the collection is of a specific, defined type.
+ *
+ * This is a direct implementation of `CollectionInterface`, provided for
+ * the sake of convenience.
+ *
+ * Example usage:
+ *
+ * ``` php
+ * $collection = new \Ramsey\Collection\Collection('My\\Foo');
+ * $collection->add(new \My\Foo());
+ * $collection->add(new \My\Foo());
+ *
+ * foreach ($collection as $foo) {
+ * // Do something with $foo
+ * }
+ * ```
+ *
+ * It is preferable to subclass `AbstractCollection` to create your own typed
+ * collections. For example:
+ *
+ * ``` php
+ * namespace My\Foo;
+ *
+ * class FooCollection extends \Ramsey\Collection\AbstractCollection
+ * {
+ * public function getType()
+ * {
+ * return 'My\\Foo';
+ * }
+ * }
+ * ```
+ *
+ * And then use it similarly to the earlier example:
+ *
+ * ``` php
+ * $fooCollection = new \My\Foo\FooCollection();
+ * $fooCollection->add(new \My\Foo());
+ * $fooCollection->add(new \My\Foo());
+ *
+ * foreach ($fooCollection as $foo) {
+ * // Do something with $foo
+ * }
+ * ```
+ *
+ * The benefit with this approach is that you may do type-checking on the
+ * collection object:
+ *
+ * ``` php
+ * if ($collection instanceof \My\Foo\FooCollection) {
+ * // the collection is a collection of My\Foo objects
+ * }
+ * ```
+ *
+ * @template T
+ * @template-extends AbstractCollection<T>
+ */
+class Collection extends AbstractCollection
+{
+ /**
+ * The type of elements stored in this collection.
+ *
+ * A collection's type is immutable once it is set. For this reason, this
+ * property is set private.
+ *
+ * @var string
+ */
+ private $collectionType;
+
+ /**
+ * Constructs a collection object of the specified type, optionally with the
+ * specified data.
+ *
+ * @param string $collectionType The type (FQCN) associated with this
+ * collection.
+ * @param array<array-key, T> $data The initial items to store in the collection.
+ */
+ public function __construct(string $collectionType, array $data = [])
+ {
+ $this->collectionType = $collectionType;
+ parent::__construct($data);
+ }
+
+ public function getType(): string
+ {
+ return $this->collectionType;
+ }
+}
diff --git a/vendor/ramsey/collection/src/CollectionInterface.php b/vendor/ramsey/collection/src/CollectionInterface.php
new file mode 100644
index 0000000..dfef6ca
--- /dev/null
+++ b/vendor/ramsey/collection/src/CollectionInterface.php
@@ -0,0 +1,205 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection;
+
+/**
+ * A collection represents a group of objects, known as its elements.
+ *
+ * Some collections allow duplicate elements and others do not. Some are ordered
+ * and others unordered.
+ *
+ * @template T
+ * @template-extends ArrayInterface<T>
+ */
+interface CollectionInterface extends ArrayInterface
+{
+ /**
+ * Ascending sort type.
+ */
+ public const SORT_ASC = 'asc';
+
+ /**
+ * Descending sort type.
+ */
+ public const SORT_DESC = 'desc';
+
+ /**
+ * Ensures that this collection contains the specified element (optional
+ * operation).
+ *
+ * Returns `true` if this collection changed as a result of the call.
+ * (Returns `false` if this collection does not permit duplicates and
+ * already contains the specified element.)
+ *
+ * Collections that support this operation may place limitations on what
+ * elements may be added to this collection. In particular, some
+ * collections will refuse to add `null` elements, and others will impose
+ * restrictions on the type of elements that may be added. Collection
+ * classes should clearly specify in their documentation any restrictions
+ * on what elements may be added.
+ *
+ * If a collection refuses to add a particular element for any reason other
+ * than that it already contains the element, it must throw an exception
+ * (rather than returning `false`). This preserves the invariant that a
+ * collection always contains the specified element after this call returns.
+ *
+ * @param T $element The element to add to the collection.
+ *
+ * @return bool `true` if this collection changed as a result of the call.
+ */
+ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ public function add($element): bool;
+
+ /**
+ * Returns `true` if this collection contains the specified element.
+ *
+ * @param T $element The element to check whether the collection contains.
+ * @param bool $strict Whether to perform a strict type check on the value.
+ */
+ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ public function contains($element, bool $strict = true): bool;
+
+ /**
+ * Returns the type associated with this collection.
+ */
+ public function getType(): string;
+
+ /**
+ * Removes a single instance of the specified element from this collection,
+ * if it is present.
+ *
+ * @param T $element The element to remove from the collection.
+ *
+ * @return bool `true` if an element was removed as a result of this call.
+ */
+ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ public function remove($element): bool;
+
+ /**
+ * Returns the values from the given property or method.
+ *
+ * @param string $propertyOrMethod The property or method name to filter by.
+ *
+ * @return list<mixed>
+ */
+ public function column(string $propertyOrMethod): array;
+
+ /**
+ * Returns the first item of the collection.
+ *
+ * @return T
+ */
+ public function first();
+
+ /**
+ * Returns the last item of the collection.
+ *
+ * @return T
+ */
+ public function last();
+
+ /**
+ * Sort the collection by a property or method with the given sort order.
+ *
+ * This will always leave the original collection untouched and will return
+ * a new one.
+ *
+ * @param string $propertyOrMethod The property or method to sort by.
+ * @param string $order The sort order for the resulting collection (one of
+ * this interface's `SORT_*` constants).
+ *
+ * @return CollectionInterface<T>
+ */
+ public function sort(string $propertyOrMethod, string $order = self::SORT_ASC): self;
+
+ /**
+ * Filter out items of the collection which don't match the criteria of
+ * given callback.
+ *
+ * This will always leave the original collection untouched and will return
+ * a new one.
+ *
+ * See the {@link http://php.net/manual/en/function.array-filter.php PHP array_filter() documentation}
+ * for examples of how the `$callback` parameter works.
+ *
+ * @param callable(T):bool $callback A callable to use for filtering elements.
+ *
+ * @return CollectionInterface<T>
+ */
+ public function filter(callable $callback): self;
+
+ /**
+ * Create a new collection where items match the criteria of given callback.
+ *
+ * This will always leave the original collection untouched and will return
+ * a new one.
+ *
+ * @param string $propertyOrMethod The property or method to evaluate.
+ * @param mixed $value The value to match.
+ *
+ * @return CollectionInterface<T>
+ */
+ public function where(string $propertyOrMethod, $value): self;
+
+ /**
+ * Apply a given callback method on each item of the collection.
+ *
+ * This will always leave the original collection untouched. The new
+ * collection is created by mapping the callback to each item of the
+ * original collection.
+ *
+ * See the {@link http://php.net/manual/en/function.array-map.php PHP array_map() documentation}
+ * for examples of how the `$callback` parameter works.
+ *
+ * @param callable(T):TCallbackReturn $callback A callable to apply to each
+ * item of the collection.
+ *
+ * @return CollectionInterface<TCallbackReturn>
+ *
+ * @template TCallbackReturn
+ */
+ public function map(callable $callback): self;
+
+ /**
+ * Create a new collection with divergent items between current and given
+ * collection.
+ *
+ * @param CollectionInterface<T> $other The collection to check for divergent
+ * items.
+ *
+ * @return CollectionInterface<T>
+ */
+ public function diff(CollectionInterface $other): self;
+
+ /**
+ * Create a new collection with intersecting item between current and given
+ * collection.
+ *
+ * @param CollectionInterface<T> $other The collection to check for
+ * intersecting items.
+ *
+ * @return CollectionInterface<T>
+ */
+ public function intersect(CollectionInterface $other): self;
+
+ /**
+ * Merge current items and items of given collections into a new one.
+ *
+ * @param CollectionInterface<T> ...$collections The collections to merge.
+ *
+ * @return CollectionInterface<T>
+ */
+ public function merge(CollectionInterface ...$collections): self;
+}
diff --git a/vendor/ramsey/collection/src/DoubleEndedQueue.php b/vendor/ramsey/collection/src/DoubleEndedQueue.php
new file mode 100644
index 0000000..6ebdca5
--- /dev/null
+++ b/vendor/ramsey/collection/src/DoubleEndedQueue.php
@@ -0,0 +1,187 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection;
+
+use Ramsey\Collection\Exception\InvalidArgumentException;
+use Ramsey\Collection\Exception\NoSuchElementException;
+
+/**
+ * This class provides a basic implementation of `DoubleEndedQueueInterface`, to
+ * minimize the effort required to implement this interface.
+ *
+ * @template T
+ * @template-extends Queue<T>
+ * @template-implements DoubleEndedQueueInterface<T>
+ */
+class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
+{
+ /**
+ * Index of the last element in the queue.
+ *
+ * @var int
+ */
+ private $tail = -1;
+
+ /**
+ * @inheritDoc
+ */
+ public function offsetSet($offset, $value): void
+ {
+ if ($this->checkType($this->getType(), $value) === false) {
+ throw new InvalidArgumentException(
+ 'Value must be of type ' . $this->getType() . '; value is '
+ . $this->toolValueToString($value)
+ );
+ }
+
+ $this->tail++;
+
+ $this->data[$this->tail] = $value;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function addFirst($element): bool
+ {
+ if ($this->checkType($this->getType(), $element) === false) {
+ throw new InvalidArgumentException(
+ 'Value must be of type ' . $this->getType() . '; value is '
+ . $this->toolValueToString($element)
+ );
+ }
+
+ $this->index--;
+
+ $this->data[$this->index] = $element;
+
+ return true;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function addLast($element): bool
+ {
+ return $this->add($element);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function offerFirst($element): bool
+ {
+ try {
+ return $this->addFirst($element);
+ } catch (InvalidArgumentException $e) {
+ return false;
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function offerLast($element): bool
+ {
+ return $this->offer($element);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function removeFirst()
+ {
+ return $this->remove();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function removeLast()
+ {
+ $tail = $this->pollLast();
+
+ if ($tail === null) {
+ throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
+ }
+
+ return $tail;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function pollFirst()
+ {
+ return $this->poll();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function pollLast()
+ {
+ if ($this->count() === 0) {
+ return null;
+ }
+
+ $tail = $this[$this->tail];
+
+ unset($this[$this->tail]);
+ $this->tail--;
+
+ return $tail;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function firstElement()
+ {
+ return $this->element();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function lastElement()
+ {
+ if ($this->count() === 0) {
+ throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
+ }
+
+ return $this->data[$this->tail];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function peekFirst()
+ {
+ return $this->peek();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function peekLast()
+ {
+ if ($this->count() === 0) {
+ return null;
+ }
+
+ return $this->data[$this->tail];
+ }
+}
diff --git a/vendor/ramsey/collection/src/DoubleEndedQueueInterface.php b/vendor/ramsey/collection/src/DoubleEndedQueueInterface.php
new file mode 100644
index 0000000..67aae5e
--- /dev/null
+++ b/vendor/ramsey/collection/src/DoubleEndedQueueInterface.php
@@ -0,0 +1,316 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection;
+
+use Ramsey\Collection\Exception\NoSuchElementException;
+
+/**
+ * A linear collection that supports element insertion and removal at both ends.
+ *
+ * Most `DoubleEndedQueueInterface` implementations place no fixed limits on the
+ * number of elements they may contain, but this interface supports
+ * capacity-restricted double-ended queues as well as those with no fixed size
+ * limit.
+ *
+ * This interface defines methods to access the elements at both ends of the
+ * double-ended queue. Methods are provided to insert, remove, and examine the
+ * element. Each of these methods exists in two forms: one throws an exception
+ * if the operation fails, the other returns a special value (either `null` or
+ * `false`, depending on the operation). The latter form of the insert operation
+ * is designed specifically for use with capacity-restricted implementations; in
+ * most implementations, insert operations cannot fail.
+ *
+ * The twelve methods described above are summarized in the following table:
+ *
+ * <table>
+ * <caption>Summary of DoubleEndedQueueInterface methods</caption>
+ * <thead>
+ * <tr>
+ * <th></th>
+ * <th colspan=2>First Element (Head)</th>
+ * <th colspan=2>Last Element (Tail)</th>
+ * </tr>
+ * <tr>
+ * <td></td>
+ * <td><em>Throws exception</em></td>
+ * <td><em>Special value</em></td>
+ * <td><em>Throws exception</em></td>
+ * <td><em>Special value</em></td>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <th>Insert</th>
+ * <td><code>addFirst()</code></td>
+ * <td><code>offerFirst()</code></td>
+ * <td><code>addLast()</code></td>
+ * <td><code>offerLast()</code></td>
+ * </tr>
+ * <tr>
+ * <th>Remove</th>
+ * <td><code>removeFirst()</code></td>
+ * <td><code>pollFirst()</code></td>
+ * <td><code>removeLast()</code></td>
+ * <td><code>pollLast()</code></td>
+ * </tr>
+ * <tr>
+ * <th>Examine</th>
+ * <td><code>firstElement()</code></td>
+ * <td><code>peekFirst()</code></td>
+ * <td><code>lastElement()</code></td>
+ * <td><code>peekLast()</code></td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * This interface extends the `QueueInterface`. When a double-ended queue is
+ * used as a queue, FIFO (first-in-first-out) behavior results. Elements are
+ * added at the end of the double-ended queue and removed from the beginning.
+ * The methods inherited from the `QueueInterface` are precisely equivalent to
+ * `DoubleEndedQueueInterface` methods as indicated in the following table:
+ *
+ * <table>
+ * <caption>Comparison of QueueInterface and DoubleEndedQueueInterface methods</caption>
+ * <thead>
+ * <tr>
+ * <th>QueueInterface Method</th>
+ * <th>DoubleEndedQueueInterface Method</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td><code>add()</code></td>
+ * <td><code>addLast()</code></td>
+ * </tr>
+ * <tr>
+ * <td><code>offer()</code></td>
+ * <td><code>offerLast()</code></td>
+ * </tr>
+ * <tr>
+ * <td><code>remove()</code></td>
+ * <td><code>removeFirst()</code></td>
+ * </tr>
+ * <tr>
+ * <td><code>poll()</code></td>
+ * <td><code>pollFirst()</code></td>
+ * </tr>
+ * <tr>
+ * <td><code>element()</code></td>
+ * <td><code>firstElement()</code></td>
+ * </tr>
+ * <tr>
+ * <td><code>peek()</code></td>
+ * <td><code>peekFirst()</code></td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * Double-ended queues can also be used as LIFO (last-in-first-out) stacks. When
+ * a double-ended queue is used as a stack, elements are pushed and popped from
+ * the beginning of the double-ended queue. Stack concepts are precisely
+ * equivalent to `DoubleEndedQueueInterface` methods as indicated in the table
+ * below:
+ *
+ * <table>
+ * <caption>Comparison of stack concepts and DoubleEndedQueueInterface methods</caption>
+ * <thead>
+ * <tr>
+ * <th>Stack concept</th>
+ * <th>DoubleEndedQueueInterface Method</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td><em>push</em></td>
+ * <td><code>addFirst()</code></td>
+ * </tr>
+ * <tr>
+ * <td><em>pop</em></td>
+ * <td><code>removeFirst()</code></td>
+ * </tr>
+ * <tr>
+ * <td><em>peek</em></td>
+ * <td><code>peekFirst()</code></td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * Note that the `peek()` method works equally well when a double-ended queue is
+ * used as a queue or a stack; in either case, elements are drawn from the
+ * beginning of the double-ended queue.
+ *
+ * While `DoubleEndedQueueInterface` implementations are not strictly required
+ * to prohibit the insertion of `null` elements, they are strongly encouraged to
+ * do so. Users of any `DoubleEndedQueueInterface` implementations that do allow
+ * `null` elements are strongly encouraged *not* to take advantage of the
+ * ability to insert nulls. This is so because `null` is used as a special
+ * return value by various methods to indicated that the double-ended queue is
+ * empty.
+ *
+ * @template T
+ * @template-extends QueueInterface<T>
+ */
+interface DoubleEndedQueueInterface extends QueueInterface
+{
+ /**
+ * Inserts the specified element at the front of this queue if it is
+ * possible to do so immediately without violating capacity restrictions.
+ *
+ * When using a capacity-restricted double-ended queue, it is generally
+ * preferable to use the `offerFirst()` method.
+ *
+ * @param T $element The element to add to the front of this queue.
+ *
+ * @return bool `true` if this queue changed as a result of the call.
+ *
+ * @throws \RuntimeException if a queue refuses to add a particular element
+ * for any reason other than that it already contains the element.
+ * Implementations should use a more-specific exception that extends
+ * `\RuntimeException`.
+ */
+ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ public function addFirst($element): bool;
+
+ /**
+ * Inserts the specified element at the end of this queue if it is possible
+ * to do so immediately without violating capacity restrictions.
+ *
+ * When using a capacity-restricted double-ended queue, it is generally
+ * preferable to use the `offerLast()` method.
+ *
+ * This method is equivalent to `add()`.
+ *
+ * @param T $element The element to add to the end of this queue.
+ *
+ * @return bool `true` if this queue changed as a result of the call.
+ *
+ * @throws \RuntimeException if a queue refuses to add a particular element
+ * for any reason other than that it already contains the element.
+ * Implementations should use a more-specific exception that extends
+ * `\RuntimeException`.
+ */
+ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ public function addLast($element): bool;
+
+ /**
+ * Inserts the specified element at the front of this queue if it is
+ * possible to do so immediately without violating capacity restrictions.
+ *
+ * When using a capacity-restricted queue, this method is generally
+ * preferable to `addFirst()`, which can fail to insert an element only by
+ * throwing an exception.
+ *
+ * @param T $element The element to add to the front of this queue.
+ *
+ * @return bool `true` if the element was added to this queue, else `false`.
+ */
+ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ public function offerFirst($element): bool;
+
+ /**
+ * Inserts the specified element at the end of this queue if it is possible
+ * to do so immediately without violating capacity restrictions.
+ *
+ * When using a capacity-restricted queue, this method is generally
+ * preferable to `addLast()` which can fail to insert an element only by
+ * throwing an exception.
+ *
+ * @param T $element The element to add to the end of this queue.
+ *
+ * @return bool `true` if the element was added to this queue, else `false`.
+ */
+ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ public function offerLast($element): bool;
+
+ /**
+ * Retrieves and removes the head of this queue.
+ *
+ * This method differs from `pollFirst()` only in that it throws an
+ * exception if this queue is empty.
+ *
+ * @return T the first element in this queue.
+ *
+ * @throws NoSuchElementException if this queue is empty.
+ */
+ public function removeFirst();
+
+ /**
+ * Retrieves and removes the tail of this queue.
+ *
+ * This method differs from `pollLast()` only in that it throws an exception
+ * if this queue is empty.
+ *
+ * @return T the last element in this queue.
+ *
+ * @throws NoSuchElementException if this queue is empty.
+ */
+ public function removeLast();
+
+ /**
+ * Retrieves and removes the head of this queue, or returns `null` if this
+ * queue is empty.
+ *
+ * @return T|null the head of this queue, or `null` if this queue is empty.
+ */
+ public function pollFirst();
+
+ /**
+ * Retrieves and removes the tail of this queue, or returns `null` if this
+ * queue is empty.
+ *
+ * @return T|null the tail of this queue, or `null` if this queue is empty.
+ */
+ public function pollLast();
+
+ /**
+ * Retrieves, but does not remove, the head of this queue.
+ *
+ * This method differs from `peekFirst()` only in that it throws an
+ * exception if this queue is empty.
+ *
+ * @return T the head of this queue.
+ *
+ * @throws NoSuchElementException if this queue is empty.
+ */
+ public function firstElement();
+
+ /**
+ * Retrieves, but does not remove, the tail of this queue.
+ *
+ * This method differs from `peekLast()` only in that it throws an exception
+ * if this queue is empty.
+ *
+ * @return T the tail of this queue.
+ *
+ * @throws NoSuchElementException if this queue is empty.
+ */
+ public function lastElement();
+
+ /**
+ * Retrieves, but does not remove, the head of this queue, or returns `null`
+ * if this queue is empty.
+ *
+ * @return T|null the head of this queue, or `null` if this queue is empty.
+ */
+ public function peekFirst();
+
+ /**
+ * Retrieves, but does not remove, the tail of this queue, or returns `null`
+ * if this queue is empty.
+ *
+ * @return T|null the tail of this queue, or `null` if this queue is empty.
+ */
+ public function peekLast();
+}
diff --git a/vendor/ramsey/collection/src/Exception/CollectionMismatchException.php b/vendor/ramsey/collection/src/Exception/CollectionMismatchException.php
new file mode 100644
index 0000000..d4b335f
--- /dev/null
+++ b/vendor/ramsey/collection/src/Exception/CollectionMismatchException.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection\Exception;
+
+/**
+ * Thrown when attempting to operate on collections of differing types.
+ */
+class CollectionMismatchException extends \RuntimeException
+{
+}
diff --git a/vendor/ramsey/collection/src/Exception/InvalidArgumentException.php b/vendor/ramsey/collection/src/Exception/InvalidArgumentException.php
new file mode 100644
index 0000000..dcc3eac
--- /dev/null
+++ b/vendor/ramsey/collection/src/Exception/InvalidArgumentException.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection\Exception;
+
+/**
+ * Thrown to indicate an argument is not of the expected type.
+ */
+class InvalidArgumentException extends \InvalidArgumentException
+{
+}
diff --git a/vendor/ramsey/collection/src/Exception/InvalidSortOrderException.php b/vendor/ramsey/collection/src/Exception/InvalidSortOrderException.php
new file mode 100644
index 0000000..9337ccc
--- /dev/null
+++ b/vendor/ramsey/collection/src/Exception/InvalidSortOrderException.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection\Exception;
+
+/**
+ * Thrown when attempting to use a sort order that is not recognized.
+ */
+class InvalidSortOrderException extends \RuntimeException
+{
+}
diff --git a/vendor/ramsey/collection/src/Exception/NoSuchElementException.php b/vendor/ramsey/collection/src/Exception/NoSuchElementException.php
new file mode 100644
index 0000000..9debe8f
--- /dev/null
+++ b/vendor/ramsey/collection/src/Exception/NoSuchElementException.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection\Exception;
+
+/**
+ * Thrown when attempting to access an element that does not exist.
+ */
+class NoSuchElementException extends \RuntimeException
+{
+}
diff --git a/vendor/ramsey/collection/src/Exception/OutOfBoundsException.php b/vendor/ramsey/collection/src/Exception/OutOfBoundsException.php
new file mode 100644
index 0000000..4e9d16f
--- /dev/null
+++ b/vendor/ramsey/collection/src/Exception/OutOfBoundsException.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection\Exception;
+
+/**
+ * Thrown when attempting to access an element out of the range of the collection.
+ */
+class OutOfBoundsException extends \OutOfBoundsException
+{
+}
diff --git a/vendor/ramsey/collection/src/Exception/UnsupportedOperationException.php b/vendor/ramsey/collection/src/Exception/UnsupportedOperationException.php
new file mode 100644
index 0000000..8f45e58
--- /dev/null
+++ b/vendor/ramsey/collection/src/Exception/UnsupportedOperationException.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection\Exception;
+
+/**
+ * Thrown to indicate that the requested operation is not supported.
+ */
+class UnsupportedOperationException extends \RuntimeException
+{
+}
diff --git a/vendor/ramsey/collection/src/Exception/ValueExtractionException.php b/vendor/ramsey/collection/src/Exception/ValueExtractionException.php
new file mode 100644
index 0000000..f6c6cb4
--- /dev/null
+++ b/vendor/ramsey/collection/src/Exception/ValueExtractionException.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection\Exception;
+
+/**
+ * Thrown when attempting to extract a value for a method or property that does not exist.
+ */
+class ValueExtractionException extends \RuntimeException
+{
+}
diff --git a/vendor/ramsey/collection/src/GenericArray.php b/vendor/ramsey/collection/src/GenericArray.php
new file mode 100644
index 0000000..9b95df3
--- /dev/null
+++ b/vendor/ramsey/collection/src/GenericArray.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection;
+
+/**
+ * `GenericArray` represents a standard array object.
+ *
+ * @template-extends AbstractArray<mixed>
+ */
+class GenericArray extends AbstractArray
+{
+}
diff --git a/vendor/ramsey/collection/src/Map/AbstractMap.php b/vendor/ramsey/collection/src/Map/AbstractMap.php
new file mode 100644
index 0000000..70f7116
--- /dev/null
+++ b/vendor/ramsey/collection/src/Map/AbstractMap.php
@@ -0,0 +1,162 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection\Map;
+
+use Ramsey\Collection\AbstractArray;
+use Ramsey\Collection\Exception\InvalidArgumentException;
+
+use function array_key_exists;
+use function array_keys;
+use function in_array;
+
+/**
+ * This class provides a basic implementation of `MapInterface`, to minimize the
+ * effort required to implement this interface.
+ *
+ * @template T
+ * @template-extends AbstractArray<T>
+ * @template-implements MapInterface<T>
+ */
+abstract class AbstractMap extends AbstractArray implements MapInterface
+{
+ /**
+ * @inheritDoc
+ */
+ public function offsetSet($offset, $value): void
+ {
+ if ($offset === null) {
+ throw new InvalidArgumentException(
+ 'Map elements are key/value pairs; a key must be provided for '
+ . 'value ' . var_export($value, true)
+ );
+ }
+
+ $this->data[$offset] = $value;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function containsKey($key): bool
+ {
+ return array_key_exists($key, $this->data);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function containsValue($value): bool
+ {
+ return in_array($value, $this->data, true);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function keys(): array
+ {
+ return array_keys($this->data);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function get($key, $defaultValue = null)
+ {
+ if (!$this->containsKey($key)) {
+ return $defaultValue;
+ }
+
+ return $this[$key];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function put($key, $value)
+ {
+ $previousValue = $this->get($key);
+ $this[$key] = $value;
+
+ return $previousValue;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function putIfAbsent($key, $value)
+ {
+ $currentValue = $this->get($key);
+
+ if ($currentValue === null) {
+ $this[$key] = $value;
+ }
+
+ return $currentValue;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function remove($key)
+ {
+ $previousValue = $this->get($key);
+ unset($this[$key]);
+
+ return $previousValue;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function removeIf($key, $value): bool
+ {
+ if ($this->get($key) === $value) {
+ unset($this[$key]);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function replace($key, $value)
+ {
+ $currentValue = $this->get($key);
+
+ if ($this->containsKey($key)) {
+ $this[$key] = $value;
+ }
+
+ return $currentValue;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function replaceIf($key, $oldValue, $newValue): bool
+ {
+ if ($this->get($key) === $oldValue) {
+ $this[$key] = $newValue;
+
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/vendor/ramsey/collection/src/Map/AbstractTypedMap.php b/vendor/ramsey/collection/src/Map/AbstractTypedMap.php
new file mode 100644
index 0000000..baa6793
--- /dev/null
+++ b/vendor/ramsey/collection/src/Map/AbstractTypedMap.php
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection\Map;
+
+use Ramsey\Collection\Exception\InvalidArgumentException;
+use Ramsey\Collection\Tool\TypeTrait;
+use Ramsey\Collection\Tool\ValueToStringTrait;
+
+/**
+ * This class provides a basic implementation of `TypedMapInterface`, to
+ * minimize the effort required to implement this interface.
+ *
+ * @template K
+ * @template T
+ * @template-extends AbstractMap<T>
+ * @template-implements TypedMapInterface<T>
+ */
+abstract class AbstractTypedMap extends AbstractMap implements TypedMapInterface
+{
+ use TypeTrait;
+ use ValueToStringTrait;
+
+ /**
+ * @param K|null $offset
+ * @param T $value
+ *
+ * @inheritDoc
+ *
+ * @psalm-suppress MoreSpecificImplementedParamType
+ */
+ public function offsetSet($offset, $value): void
+ {
+ if ($offset === null) {
+ throw new InvalidArgumentException(
+ 'Map elements are key/value pairs; a key must be provided for '
+ . 'value ' . var_export($value, true)
+ );
+ }
+
+ if ($this->checkType($this->getKeyType(), $offset) === false) {
+ throw new InvalidArgumentException(
+ 'Key must be of type ' . $this->getKeyType() . '; key is '
+ . $this->toolValueToString($offset)
+ );
+ }
+
+ if ($this->checkType($this->getValueType(), $value) === false) {
+ throw new InvalidArgumentException(
+ 'Value must be of type ' . $this->getValueType() . '; value is '
+ . $this->toolValueToString($value)
+ );
+ }
+
+ /** @psalm-suppress MixedArgumentTypeCoercion */
+ parent::offsetSet($offset, $value);
+ }
+}
diff --git a/vendor/ramsey/collection/src/Map/AssociativeArrayMap.php b/vendor/ramsey/collection/src/Map/AssociativeArrayMap.php
new file mode 100644
index 0000000..3274dc9
--- /dev/null
+++ b/vendor/ramsey/collection/src/Map/AssociativeArrayMap.php
@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection\Map;
+
+/**
+ * `AssociativeArrayMap` represents a standard associative array object.
+ *
+ * @template T
+ * @template-extends AbstractMap<T>
+ */
+class AssociativeArrayMap extends AbstractMap
+{
+}
diff --git a/vendor/ramsey/collection/src/Map/MapInterface.php b/vendor/ramsey/collection/src/Map/MapInterface.php
new file mode 100644
index 0000000..04e52a2
--- /dev/null
+++ b/vendor/ramsey/collection/src/Map/MapInterface.php
@@ -0,0 +1,149 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection\Map;
+
+use Ramsey\Collection\ArrayInterface;
+
+/**
+ * An object that maps keys to values.
+ *
+ * A map cannot contain duplicate keys; each key can map to at most one value.
+ *
+ * @template T
+ * @template-extends ArrayInterface<T>
+ */
+interface MapInterface extends ArrayInterface
+{
+ /**
+ * Returns `true` if this map contains a mapping for the specified key.
+ *
+ * @param array-key $key The key to check in the map.
+ */
+ public function containsKey($key): bool;
+
+ /**
+ * Returns `true` if this map maps one or more keys to the specified value.
+ *
+ * This performs a strict type check on the value.
+ *
+ * @param T $value The value to check in the map.
+ */
+ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ public function containsValue($value): bool;
+
+ /**
+ * Return an array of the keys contained in this map.
+ *
+ * @return list<array-key>
+ */
+ public function keys(): array;
+
+ /**
+ * Returns the value to which the specified key is mapped, `null` if this
+ * map contains no mapping for the key, or (optionally) `$defaultValue` if
+ * this map contains no mapping for the key.
+ *
+ * @param array-key $key The key to return from the map.
+ * @param T|null $defaultValue The default value to use if `$key` is not found.
+ *
+ * @return T|null the value or `null` if the key could not be found.
+ */
+ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ public function get($key, $defaultValue = null);
+
+ /**
+ * Associates the specified value with the specified key in this map.
+ *
+ * If the map previously contained a mapping for the key, the old value is
+ * replaced by the specified value.
+ *
+ * @param array-key $key The key to put or replace in the map.
+ * @param T $value The value to store at `$key`.
+ *
+ * @return T|null the previous value associated with key, or `null` if
+ * there was no mapping for `$key`.
+ */
+ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ public function put($key, $value);
+
+ /**
+ * Associates the specified value with the specified key in this map only if
+ * it is not already set.
+ *
+ * If there is already a value associated with `$key`, this returns that
+ * value without replacing it.
+ *
+ * @param array-key $key The key to put in the map.
+ * @param T $value The value to store at `$key`.
+ *
+ * @return T|null the previous value associated with key, or `null` if
+ * there was no mapping for `$key`.
+ */
+ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ public function putIfAbsent($key, $value);
+
+ /**
+ * Removes the mapping for a key from this map if it is present.
+ *
+ * @param array-key $key The key to remove from the map.
+ *
+ * @return T|null the previous value associated with key, or `null` if
+ * there was no mapping for `$key`.
+ */
+ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ public function remove($key);
+
+ /**
+ * Removes the entry for the specified key only if it is currently mapped to
+ * the specified value.
+ *
+ * This performs a strict type check on the value.
+ *
+ * @param array-key $key The key to remove from the map.
+ * @param T $value The value to match.
+ *
+ * @return bool true if the value was removed.
+ */
+ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ public function removeIf($key, $value): bool;
+
+ /**
+ * Replaces the entry for the specified key only if it is currently mapped
+ * to some value.
+ *
+ * @param array-key $key The key to replace.
+ * @param T $value The value to set at `$key`.
+ *
+ * @return T|null the previous value associated with key, or `null` if
+ * there was no mapping for `$key`.
+ */
+ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ public function replace($key, $value);
+
+ /**
+ * Replaces the entry for the specified key only if currently mapped to the
+ * specified value.
+ *
+ * This performs a strict type check on the value.
+ *
+ * @param array-key $key The key to remove from the map.
+ * @param T $oldValue The value to match.
+ * @param T $newValue The value to use as a replacement.
+ *
+ * @return bool true if the value was replaced.
+ */
+ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ public function replaceIf($key, $oldValue, $newValue): bool;
+}
diff --git a/vendor/ramsey/collection/src/Map/NamedParameterMap.php b/vendor/ramsey/collection/src/Map/NamedParameterMap.php
new file mode 100644
index 0000000..ecc52f7
--- /dev/null
+++ b/vendor/ramsey/collection/src/Map/NamedParameterMap.php
@@ -0,0 +1,120 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection\Map;
+
+use Ramsey\Collection\Exception\InvalidArgumentException;
+use Ramsey\Collection\Tool\TypeTrait;
+use Ramsey\Collection\Tool\ValueToStringTrait;
+
+use function array_combine;
+use function array_key_exists;
+use function is_int;
+
+/**
+ * `NamedParameterMap` represents a mapping of values to a set of named keys
+ * that may optionally be typed
+ *
+ * @template-extends AbstractMap<mixed>
+ */
+class NamedParameterMap extends AbstractMap
+{
+ use TypeTrait;
+ use ValueToStringTrait;
+
+ /**
+ * Named parameters defined for this map.
+ *
+ * @var array<string, string>
+ */
+ protected $namedParameters;
+
+ /**
+ * Constructs a new `NamedParameterMap`.
+ *
+ * @param array<array-key, string> $namedParameters The named parameters defined for this map.
+ * @param array<array-key, mixed> $data An initial set of data to set on this map.
+ */
+ public function __construct(array $namedParameters, array $data = [])
+ {
+ $this->namedParameters = $this->filterNamedParameters($namedParameters);
+ parent::__construct($data);
+ }
+
+ /**
+ * Returns named parameters set for this `NamedParameterMap`.
+ *
+ * @return array<string, string>
+ */
+ public function getNamedParameters(): array
+ {
+ return $this->namedParameters;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function offsetSet($offset, $value): void
+ {
+ if ($offset === null) {
+ throw new InvalidArgumentException(
+ 'Map elements are key/value pairs; a key must be provided for '
+ . 'value ' . var_export($value, true)
+ );
+ }
+
+ if (!array_key_exists($offset, $this->namedParameters)) {
+ throw new InvalidArgumentException(
+ 'Attempting to set value for unconfigured parameter \''
+ . $offset . '\''
+ );
+ }
+
+ if ($this->checkType($this->namedParameters[$offset], $value) === false) {
+ throw new InvalidArgumentException(
+ 'Value for \'' . $offset . '\' must be of type '
+ . $this->namedParameters[$offset] . '; value is '
+ . $this->toolValueToString($value)
+ );
+ }
+
+ $this->data[$offset] = $value;
+ }
+
+ /**
+ * Given an array of named parameters, constructs a proper mapping of
+ * named parameters to types.
+ *
+ * @param array<array-key, string> $namedParameters The named parameters to filter.
+ *
+ * @return array<string, string>
+ */
+ protected function filterNamedParameters(array $namedParameters): array
+ {
+ $names = [];
+ $types = [];
+
+ foreach ($namedParameters as $key => $value) {
+ if (is_int($key)) {
+ $names[] = $value;
+ $types[] = 'mixed';
+ } else {
+ $names[] = $key;
+ $types[] = $value;
+ }
+ }
+
+ return array_combine($names, $types) ?: [];
+ }
+}
diff --git a/vendor/ramsey/collection/src/Map/TypedMap.php b/vendor/ramsey/collection/src/Map/TypedMap.php
new file mode 100644
index 0000000..094551a
--- /dev/null
+++ b/vendor/ramsey/collection/src/Map/TypedMap.php
@@ -0,0 +1,137 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection\Map;
+
+use Ramsey\Collection\Tool\TypeTrait;
+
+/**
+ * A `TypedMap` represents a map of elements where key and value are typed.
+ *
+ * Each element is identified by a key with defined type and a value of defined
+ * type. The keys of the map must be unique. The values on the map can be=
+ * repeated but each with its own different key.
+ *
+ * The most common case is to use a string type key, but it's not limited to
+ * this type of keys.
+ *
+ * This is a direct implementation of `TypedMapInterface`, provided for the sake
+ * of convenience.
+ *
+ * Example usage:
+ *
+ * ```php
+ * $map = new TypedMap('string', Foo::class);
+ * $map['x'] = new Foo();
+ * foreach ($map as $key => $value) {
+ * // do something with $key, it will be a Foo::class
+ * }
+ *
+ * // this will throw an exception since key must be string
+ * $map[10] = new Foo();
+ *
+ * // this will throw an exception since value must be a Foo
+ * $map['bar'] = 'bar';
+ *
+ * // initialize map with contents
+ * $map = new TypedMap('string', Foo::class, [
+ * new Foo(), new Foo(), new Foo()
+ * ]);
+ * ```
+ *
+ * It is preferable to subclass `AbstractTypedMap` to create your own typed map
+ * implementation:
+ *
+ * ```php
+ * class FooTypedMap extends AbstractTypedMap
+ * {
+ * public function getKeyType()
+ * {
+ * return 'int';
+ * }
+ *
+ * public function getValueType()
+ * {
+ * return Foo::class;
+ * }
+ * }
+ * ```
+ *
+ * … but you also may use the `TypedMap` class:
+ *
+ * ```php
+ * class FooTypedMap extends TypedMap
+ * {
+ * public function __constructor(array $data = [])
+ * {
+ * parent::__construct('int', Foo::class, $data);
+ * }
+ * }
+ * ```
+ *
+ * @template K
+ * @template T
+ * @template-extends AbstractTypedMap<K, T>
+ */
+class TypedMap extends AbstractTypedMap
+{
+ use TypeTrait;
+
+ /**
+ * The data type of keys stored in this collection.
+ *
+ * A map key's type is immutable once it is set. For this reason, this
+ * property is set private.
+ *
+ * @var string data type of the map key.
+ */
+ private $keyType;
+
+ /**
+ * The data type of values stored in this collection.
+ *
+ * A map value's type is immutable once it is set. For this reason, this
+ * property is set private.
+ *
+ * @var string data type of the map value.
+ */
+ private $valueType;
+
+ /**
+ * Constructs a map object of the specified key and value types,
+ * optionally with the specified data.
+ *
+ * @param string $keyType The data type of the map's keys.
+ * @param string $valueType The data type of the map's values.
+ * @param array<K, T> $data The initial data to set for this map.
+ */
+ public function __construct(string $keyType, string $valueType, array $data = [])
+ {
+ $this->keyType = $keyType;
+ $this->valueType = $valueType;
+
+ /** @psalm-suppress MixedArgumentTypeCoercion */
+ parent::__construct($data);
+ }
+
+ public function getKeyType(): string
+ {
+ return $this->keyType;
+ }
+
+ public function getValueType(): string
+ {
+ return $this->valueType;
+ }
+}
diff --git a/vendor/ramsey/collection/src/Map/TypedMapInterface.php b/vendor/ramsey/collection/src/Map/TypedMapInterface.php
new file mode 100644
index 0000000..51b6a81
--- /dev/null
+++ b/vendor/ramsey/collection/src/Map/TypedMapInterface.php
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection\Map;
+
+/**
+ * A `TypedMapInterface` represents a map of elements where key and value are
+ * typed.
+ *
+ * @template T
+ * @template-extends MapInterface<T>
+ */
+interface TypedMapInterface extends MapInterface
+{
+ /**
+ * Return the type used on the key.
+ */
+ public function getKeyType(): string;
+
+ /**
+ * Return the type forced on the values.
+ */
+ public function getValueType(): string;
+}
diff --git a/vendor/ramsey/collection/src/Queue.php b/vendor/ramsey/collection/src/Queue.php
new file mode 100644
index 0000000..4af2fdf
--- /dev/null
+++ b/vendor/ramsey/collection/src/Queue.php
@@ -0,0 +1,169 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection;
+
+use Ramsey\Collection\Exception\InvalidArgumentException;
+use Ramsey\Collection\Exception\NoSuchElementException;
+use Ramsey\Collection\Tool\TypeTrait;
+use Ramsey\Collection\Tool\ValueToStringTrait;
+
+/**
+ * This class provides a basic implementation of `QueueInterface`, to minimize
+ * the effort required to implement this interface.
+ *
+ * @template T
+ * @template-extends AbstractArray<T>
+ * @template-implements QueueInterface<T>
+ */
+class Queue extends AbstractArray implements QueueInterface
+{
+ use TypeTrait;
+ use ValueToStringTrait;
+
+ /**
+ * The type of elements stored in this queue.
+ *
+ * A queue's type is immutable once it is set. For this reason, this
+ * property is set private.
+ *
+ * @var string
+ */
+ private $queueType;
+
+ /**
+ * The index of the head of the queue.
+ *
+ * @var int
+ */
+ protected $index = 0;
+
+ /**
+ * Constructs a queue object of the specified type, optionally with the
+ * specified data.
+ *
+ * @param string $queueType The type (FQCN) associated with this queue.
+ * @param array<array-key, T> $data The initial items to store in the collection.
+ */
+ public function __construct(string $queueType, array $data = [])
+ {
+ $this->queueType = $queueType;
+ parent::__construct($data);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Since arbitrary offsets may not be manipulated in a queue, this method
+ * serves only to fulfill the `ArrayAccess` interface requirements. It is
+ * invoked by other operations when adding values to the queue.
+ */
+ public function offsetSet($offset, $value): void
+ {
+ if ($this->checkType($this->getType(), $value) === false) {
+ throw new InvalidArgumentException(
+ 'Value must be of type ' . $this->getType() . '; value is '
+ . $this->toolValueToString($value)
+ );
+ }
+
+ $this->data[] = $value;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function add($element): bool
+ {
+ $this[] = $element;
+
+ return true;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function element()
+ {
+ $element = $this->peek();
+
+ if ($element === null) {
+ throw new NoSuchElementException(
+ 'Can\'t return element from Queue. Queue is empty.'
+ );
+ }
+
+ return $element;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function offer($element): bool
+ {
+ try {
+ return $this->add($element);
+ } catch (InvalidArgumentException $e) {
+ return false;
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function peek()
+ {
+ if ($this->count() === 0) {
+ return null;
+ }
+
+ return $this[$this->index];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function poll()
+ {
+ if ($this->count() === 0) {
+ return null;
+ }
+
+ $head = $this[$this->index];
+
+ unset($this[$this->index]);
+ $this->index++;
+
+ return $head;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function remove()
+ {
+ $head = $this->poll();
+
+ if ($head === null) {
+ throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
+ }
+
+ return $head;
+ }
+
+ public function getType(): string
+ {
+ return $this->queueType;
+ }
+}
diff --git a/vendor/ramsey/collection/src/QueueInterface.php b/vendor/ramsey/collection/src/QueueInterface.php
new file mode 100644
index 0000000..7ebbb5d
--- /dev/null
+++ b/vendor/ramsey/collection/src/QueueInterface.php
@@ -0,0 +1,203 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection;
+
+use Ramsey\Collection\Exception\NoSuchElementException;
+
+/**
+ * A queue is a collection in which the entities in the collection are kept in
+ * order.
+ *
+ * The principal operations on the queue are the addition of entities to the end
+ * (tail), also known as *enqueue*, and removal of entities from the front
+ * (head), also known as *dequeue*. This makes the queue a first-in-first-out
+ * (FIFO) data structure.
+ *
+ * Besides basic array operations, queues provide additional insertion,
+ * extraction, and inspection operations. Each of these methods exists in two
+ * forms: one throws an exception if the operation fails, the other returns a
+ * special value (either `null` or `false`, depending on the operation). The
+ * latter form of the insert operation is designed specifically for use with
+ * capacity-restricted `QueueInterface` implementations; in most
+ * implementations, insert operations cannot fail.
+ *
+ * <table>
+ * <caption>Summary of QueueInterface methods</caption>
+ * <thead>
+ * <tr>
+ * <td></td>
+ * <td><em>Throws exception</em></td>
+ * <td><em>Returns special value</em></td>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <th>Insert</th>
+ * <td><code>add()</code></td>
+ * <td><code>offer()</code></td>
+ * </tr>
+ * <tr>
+ * <th>Remove</th>
+ * <td><code>remove()</code></td>
+ * <td><code>poll()</code></td>
+ * </tr>
+ * <tr>
+ * <th>Examine</th>
+ * <td><code>element()</code></td>
+ * <td><code>peek()</code></td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * Queues typically, but do not necessarily, order elements in a FIFO
+ * (first-in-first-out) manner. Among the exceptions are priority queues, which
+ * order elements according to a supplied comparator, or the elements' natural
+ * ordering, and LIFO queues (or stacks) which order the elements LIFO
+ * (last-in-first-out). Whatever the ordering used, the head of the queue is
+ * that element which would be removed by a call to remove() or poll(). In a
+ * FIFO queue, all new elements are inserted at the tail of the queue. Other
+ * kinds of queues may use different placement rules. Every `QueueInterface`
+ * implementation must specify its ordering properties.
+ *
+ * The `offer()` method inserts an element if possible, otherwise returning
+ * `false`. This differs from the `add()` method, which can fail to add an
+ * element only by throwing an unchecked exception. The `offer()` method is
+ * designed for use when failure is a normal, rather than exceptional
+ * occurrence, for example, in fixed-capacity (or "bounded") queues.
+ *
+ * The `remove()` and `poll()` methods remove and return the head of the queue.
+ * Exactly which element is removed from the queue is a function of the queue's
+ * ordering policy, which differs from implementation to implementation. The
+ * `remove()` and `poll()` methods differ only in their behavior when the queue
+ * is empty: the `remove()` method throws an exception, while the `poll()`
+ * method returns `null`.
+ *
+ * The `element()` and `peek()` methods return, but do not remove, the head of
+ * the queue.
+ *
+ * `QueueInterface` implementations generally do not allow insertion of `null`
+ * elements, although some implementations do not prohibit insertion of `null`.
+ * Even in the implementations that permit it, `null` should not be inserted
+ * into a queue, as `null` is also used as a special return value by the
+ * `poll()` method to indicate that the queue contains no elements.
+ *
+ * @template T
+ * @template-extends ArrayInterface<T>
+ */
+interface QueueInterface extends ArrayInterface
+{
+ /**
+ * Ensures that this queue contains the specified element (optional
+ * operation).
+ *
+ * Returns `true` if this queue changed as a result of the call. (Returns
+ * `false` if this queue does not permit duplicates and already contains the
+ * specified element.)
+ *
+ * Queues that support this operation may place limitations on what elements
+ * may be added to this queue. In particular, some queues will refuse to add
+ * `null` elements, and others will impose restrictions on the type of
+ * elements that may be added. Queue classes should clearly specify in their
+ * documentation any restrictions on what elements may be added.
+ *
+ * If a queue refuses to add a particular element for any reason other than
+ * that it already contains the element, it must throw an exception (rather
+ * than returning `false`). This preserves the invariant that a queue always
+ * contains the specified element after this call returns.
+ *
+ * @see self::offer()
+ *
+ * @param T $element The element to add to this queue.
+ *
+ * @return bool `true` if this queue changed as a result of the call.
+ *
+ * @throws \RuntimeException if a queue refuses to add a particular element
+ * for any reason other than that it already contains the element.
+ * Implementations should use a more-specific exception that extends
+ * `\RuntimeException`.
+ */
+ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ public function add($element): bool;
+
+ /**
+ * Retrieves, but does not remove, the head of this queue.
+ *
+ * This method differs from `peek()` only in that it throws an exception if
+ * this queue is empty.
+ *
+ * @see self::peek()
+ *
+ * @return T the head of this queue.
+ *
+ * @throws NoSuchElementException if this queue is empty.
+ */
+ public function element();
+
+ /**
+ * Inserts the specified element into this queue if it is possible to do so
+ * immediately without violating capacity restrictions.
+ *
+ * When using a capacity-restricted queue, this method is generally
+ * preferable to `add()`, which can fail to insert an element only by
+ * throwing an exception.
+ *
+ * @see self::add()
+ *
+ * @param T $element The element to add to this queue.
+ *
+ * @return bool `true` if the element was added to this queue, else `false`.
+ */
+ // phpcs:ignore SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
+ public function offer($element): bool;
+
+ /**
+ * Retrieves, but does not remove, the head of this queue, or returns `null`
+ * if this queue is empty.
+ *
+ * @see self::element()
+ *
+ * @return T|null the head of this queue, or `null` if this queue is empty.
+ */
+ public function peek();
+
+ /**
+ * Retrieves and removes the head of this queue, or returns `null`
+ * if this queue is empty.
+ *
+ * @see self::remove()
+ *
+ * @return T|null the head of this queue, or `null` if this queue is empty.
+ */
+ public function poll();
+
+ /**
+ * Retrieves and removes the head of this queue.
+ *
+ * This method differs from `poll()` only in that it throws an exception if
+ * this queue is empty.
+ *
+ * @see self::poll()
+ *
+ * @return T the head of this queue.
+ *
+ * @throws NoSuchElementException if this queue is empty.
+ */
+ public function remove();
+
+ /**
+ * Returns the type associated with this queue.
+ */
+ public function getType(): string;
+}
diff --git a/vendor/ramsey/collection/src/Set.php b/vendor/ramsey/collection/src/Set.php
new file mode 100644
index 0000000..ac1c5cb
--- /dev/null
+++ b/vendor/ramsey/collection/src/Set.php
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection;
+
+/**
+ * A set is a collection that contains no duplicate elements.
+ *
+ * Great care must be exercised if mutable objects are used as set elements.
+ * The behavior of a set is not specified if the value of an object is changed
+ * in a manner that affects equals comparisons while the object is an element in
+ * the set.
+ *
+ * Example usage:
+ *
+ * ``` php
+ * $foo = new \My\Foo();
+ * $set = new Set(\My\Foo::class);
+ *
+ * $set->add($foo); // returns TRUE, the element don't exists
+ * $set->add($foo); // returns FALSE, the element already exists
+ *
+ * $bar = new \My\Foo();
+ * $set->add($bar); // returns TRUE, $bar !== $foo
+ * ```
+ *
+ * @template T
+ * @template-extends AbstractSet<T>
+ */
+class Set extends AbstractSet
+{
+ /**
+ * The type of elements stored in this set
+ *
+ * A set's type is immutable. For this reason, this property is private.
+ *
+ * @var string
+ */
+ private $setType;
+
+ /**
+ * Constructs a set object of the specified type, optionally with the
+ * specified data.
+ *
+ * @param string $setType The type (FQCN) associated with this set.
+ * @param array<array-key, T> $data The initial items to store in the set.
+ */
+ public function __construct(string $setType, array $data = [])
+ {
+ $this->setType = $setType;
+ parent::__construct($data);
+ }
+
+ public function getType(): string
+ {
+ return $this->setType;
+ }
+}
diff --git a/vendor/ramsey/collection/src/Tool/TypeTrait.php b/vendor/ramsey/collection/src/Tool/TypeTrait.php
new file mode 100644
index 0000000..8214e96
--- /dev/null
+++ b/vendor/ramsey/collection/src/Tool/TypeTrait.php
@@ -0,0 +1,73 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection\Tool;
+
+use function is_array;
+use function is_bool;
+use function is_callable;
+use function is_float;
+use function is_int;
+use function is_numeric;
+use function is_object;
+use function is_resource;
+use function is_scalar;
+use function is_string;
+
+/**
+ * Provides functionality to check values for specific types.
+ */
+trait TypeTrait
+{
+ /**
+ * Returns `true` if value is of the specified type.
+ *
+ * @param string $type The type to check the value against.
+ * @param mixed $value The value to check.
+ */
+ protected function checkType(string $type, $value): bool
+ {
+ switch ($type) {
+ case 'array':
+ return is_array($value);
+ case 'bool':
+ case 'boolean':
+ return is_bool($value);
+ case 'callable':
+ return is_callable($value);
+ case 'float':
+ case 'double':
+ return is_float($value);
+ case 'int':
+ case 'integer':
+ return is_int($value);
+ case 'null':
+ return $value === null;
+ case 'numeric':
+ return is_numeric($value);
+ case 'object':
+ return is_object($value);
+ case 'resource':
+ return is_resource($value);
+ case 'scalar':
+ return is_scalar($value);
+ case 'string':
+ return is_string($value);
+ case 'mixed':
+ return true;
+ default:
+ return $value instanceof $type;
+ }
+ }
+}
diff --git a/vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php b/vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php
new file mode 100644
index 0000000..f9be1be
--- /dev/null
+++ b/vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection\Tool;
+
+use Ramsey\Collection\Exception\ValueExtractionException;
+
+use function get_class;
+use function method_exists;
+use function property_exists;
+use function sprintf;
+
+/**
+ * Provides functionality to extract the value of a property or method from an object.
+ */
+trait ValueExtractorTrait
+{
+ /**
+ * Extracts the value of the given property or method from the object.
+ *
+ * @param mixed $object The object to extract the value from.
+ * @param string $propertyOrMethod The property or method for which the
+ * value should be extracted.
+ *
+ * @return mixed the value extracted from the specified property or method.
+ *
+ * @throws ValueExtractionException if the method or property is not defined.
+ */
+ protected function extractValue($object, string $propertyOrMethod)
+ {
+ if (!is_object($object)) {
+ throw new ValueExtractionException('Unable to extract a value from a non-object');
+ }
+
+ if (property_exists($object, $propertyOrMethod)) {
+ return $object->$propertyOrMethod;
+ }
+
+ if (method_exists($object, $propertyOrMethod)) {
+ return $object->{$propertyOrMethod}();
+ }
+
+ throw new ValueExtractionException(
+ sprintf('Method or property "%s" not defined in %s', $propertyOrMethod, get_class($object))
+ );
+ }
+}
diff --git a/vendor/ramsey/collection/src/Tool/ValueToStringTrait.php b/vendor/ramsey/collection/src/Tool/ValueToStringTrait.php
new file mode 100644
index 0000000..721ade0
--- /dev/null
+++ b/vendor/ramsey/collection/src/Tool/ValueToStringTrait.php
@@ -0,0 +1,94 @@
+<?php
+
+/**
+ * This file is part of the ramsey/collection library
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Collection\Tool;
+
+use DateTimeInterface;
+
+use function get_class;
+use function get_resource_type;
+use function is_array;
+use function is_bool;
+use function is_callable;
+use function is_resource;
+use function is_scalar;
+
+/**
+ * Provides functionality to express a value as string
+ */
+trait ValueToStringTrait
+{
+ /**
+ * Returns a string representation of the value.
+ *
+ * - null value: `'NULL'`
+ * - boolean: `'TRUE'`, `'FALSE'`
+ * - array: `'Array'`
+ * - scalar: converted-value
+ * - resource: `'(type resource #number)'`
+ * - object with `__toString()`: result of `__toString()`
+ * - object DateTime: ISO 8601 date
+ * - object: `'(className Object)'`
+ * - anonymous function: same as object
+ *
+ * @param mixed $value the value to return as a string.
+ */
+ protected function toolValueToString($value): string
+ {
+ // null
+ if ($value === null) {
+ return 'NULL';
+ }
+
+ // boolean constants
+ if (is_bool($value)) {
+ return $value ? 'TRUE' : 'FALSE';
+ }
+
+ // array
+ if (is_array($value)) {
+ return 'Array';
+ }
+
+ // scalar types (integer, float, string)
+ if (is_scalar($value)) {
+ return (string) $value;
+ }
+
+ // resource
+ if (is_resource($value)) {
+ return '(' . get_resource_type($value) . ' resource #' . (int) $value . ')';
+ }
+
+ // If we don't know what it is, use var_export().
+ if (!is_object($value)) {
+ return '(' . var_export($value, true) . ')';
+ }
+
+ // From here, $value should be an object.
+
+ // __toString() is implemented
+ if (is_callable([$value, '__toString'])) {
+ return (string) $value->__toString();
+ }
+
+ // object of type \DateTime
+ if ($value instanceof DateTimeInterface) {
+ return $value->format('c');
+ }
+
+ // unknown type
+ return '(' . get_class($value) . ' Object)';
+ }
+}