mirror of
https://gitlab.com/signalytic/client-external/streamline/streamline-emr.git
synced 2026-09-12 11:11:31 +00:00
Import latest app updates from streamline
An updated set of source files and initialization was provided by streamline to address issues observed during initial testing. These files have been updated in order to generate a new set of app images.
This commit is contained in:
@@ -1,171 +0,0 @@
|
||||
<?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 count;
|
||||
|
||||
/**
|
||||
* This class provides a basic implementation of `ArrayInterface`, to minimize
|
||||
* the effort required to implement this interface.
|
||||
*
|
||||
* @template T
|
||||
* @implements ArrayInterface<T>
|
||||
*/
|
||||
abstract class AbstractArray implements ArrayInterface
|
||||
{
|
||||
/**
|
||||
* The items of this array.
|
||||
*
|
||||
* @var array<array-key, T>
|
||||
*/
|
||||
protected array $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<array-key, 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(mixed $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 the value stored at the offset, or null if the offset
|
||||
* does not exist.
|
||||
*/
|
||||
public function offsetGet(mixed $offset): mixed
|
||||
{
|
||||
return $this->data[$offset];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public function offsetSet(mixed $offset, mixed $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(mixed $offset): void
|
||||
{
|
||||
unset($this->data[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns data suitable for PHP serialization.
|
||||
*
|
||||
* @link https://www.php.net/manual/en/language.oop5.magic.php#language.oop5.magic.serialize
|
||||
* @link https://www.php.net/serialize
|
||||
*
|
||||
* @return array<array-key, T>
|
||||
*/
|
||||
public function __serialize(): array
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds unserialized data to the object.
|
||||
*
|
||||
* @param array<array-key, T> $data
|
||||
*/
|
||||
public function __unserialize(array $data): void
|
||||
{
|
||||
$this->data = $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 $this->data === [];
|
||||
}
|
||||
}
|
||||
@@ -1,393 +0,0 @@
|
||||
<?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\InvalidPropertyOrMethod;
|
||||
use Ramsey\Collection\Exception\NoSuchElementException;
|
||||
use Ramsey\Collection\Exception\UnsupportedOperationException;
|
||||
use Ramsey\Collection\Tool\TypeTrait;
|
||||
use Ramsey\Collection\Tool\ValueExtractorTrait;
|
||||
use Ramsey\Collection\Tool\ValueToStringTrait;
|
||||
|
||||
use function array_filter;
|
||||
use function array_key_first;
|
||||
use function array_key_last;
|
||||
use function array_map;
|
||||
use function array_merge;
|
||||
use function array_reduce;
|
||||
use function array_search;
|
||||
use function array_udiff;
|
||||
use function array_uintersect;
|
||||
use function in_array;
|
||||
use function is_int;
|
||||
use function is_object;
|
||||
use function spl_object_id;
|
||||
use function sprintf;
|
||||
use function usort;
|
||||
|
||||
/**
|
||||
* This class provides a basic implementation of `CollectionInterface`, to
|
||||
* minimize the effort required to implement this interface
|
||||
*
|
||||
* @template T
|
||||
* @extends AbstractArray<T>
|
||||
* @implements CollectionInterface<T>
|
||||
*/
|
||||
abstract class AbstractCollection extends AbstractArray implements CollectionInterface
|
||||
{
|
||||
use TypeTrait;
|
||||
use ValueToStringTrait;
|
||||
use ValueExtractorTrait;
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if $element is of the wrong type.
|
||||
*/
|
||||
public function add(mixed $element): bool
|
||||
{
|
||||
$this[] = $element;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function contains(mixed $element, bool $strict = true): bool
|
||||
{
|
||||
return in_array($element, $this->data, $strict);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if $element is of the wrong type.
|
||||
*/
|
||||
public function offsetSet(mixed $offset, mixed $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;
|
||||
}
|
||||
}
|
||||
|
||||
public function remove(mixed $element): bool
|
||||
{
|
||||
if (($position = array_search($element, $this->data, true)) !== false) {
|
||||
unset($this[$position]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
|
||||
* on the elements in this collection.
|
||||
* @throws UnsupportedOperationException if unable to call column() on this
|
||||
* collection.
|
||||
*
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function column(string $propertyOrMethod): array
|
||||
{
|
||||
$temp = [];
|
||||
|
||||
foreach ($this->data as $item) {
|
||||
/** @psalm-suppress MixedAssignment */
|
||||
$temp[] = $this->extractValue($item, $propertyOrMethod);
|
||||
}
|
||||
|
||||
return $temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return T
|
||||
*
|
||||
* @throws NoSuchElementException if this collection is empty.
|
||||
*/
|
||||
public function first(): mixed
|
||||
{
|
||||
$firstIndex = array_key_first($this->data);
|
||||
|
||||
if ($firstIndex === null) {
|
||||
throw new NoSuchElementException('Can\'t determine first item. Collection is empty');
|
||||
}
|
||||
|
||||
return $this->data[$firstIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return T
|
||||
*
|
||||
* @throws NoSuchElementException if this collection is empty.
|
||||
*/
|
||||
public function last(): mixed
|
||||
{
|
||||
$lastIndex = array_key_last($this->data);
|
||||
|
||||
if ($lastIndex === null) {
|
||||
throw new NoSuchElementException('Can\'t determine last item. Collection is empty');
|
||||
}
|
||||
|
||||
return $this->data[$lastIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CollectionInterface<T>
|
||||
*
|
||||
* @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
|
||||
* on the elements in this collection.
|
||||
* @throws UnsupportedOperationException if unable to call sort() on this
|
||||
* collection.
|
||||
*/
|
||||
public function sort(?string $propertyOrMethod = null, Sort $order = Sort::Ascending): CollectionInterface
|
||||
{
|
||||
$collection = clone $this;
|
||||
|
||||
usort(
|
||||
$collection->data,
|
||||
/**
|
||||
* @param T $a
|
||||
* @param T $b
|
||||
*/
|
||||
function (mixed $a, mixed $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 === Sort::Descending ? -1 : 1);
|
||||
},
|
||||
);
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable(T): bool $callback A callable to use for filtering elements.
|
||||
*
|
||||
* @return CollectionInterface<T>
|
||||
*/
|
||||
public function filter(callable $callback): CollectionInterface
|
||||
{
|
||||
$collection = clone $this;
|
||||
$collection->data = array_merge([], array_filter($collection->data, $callback));
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CollectionInterface<T>
|
||||
*
|
||||
* @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
|
||||
* on the elements in this collection.
|
||||
* @throws UnsupportedOperationException if unable to call where() on this
|
||||
* collection.
|
||||
*/
|
||||
public function where(?string $propertyOrMethod, mixed $value): CollectionInterface
|
||||
{
|
||||
return $this->filter(
|
||||
/**
|
||||
* @param T $item
|
||||
*/
|
||||
function (mixed $item) use ($propertyOrMethod, $value): bool {
|
||||
/** @var mixed $accessorValue */
|
||||
$accessorValue = $this->extractValue($item, $propertyOrMethod);
|
||||
|
||||
return $accessorValue === $value;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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): CollectionInterface
|
||||
{
|
||||
/** @var Collection<TCallbackReturn> */
|
||||
return new Collection('mixed', array_map($callback, $this->data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable(TCarry, T): TCarry $callback A callable to apply to each
|
||||
* item of the collection to reduce it to a single value.
|
||||
* @param TCarry $initial This is the initial value provided to the callback.
|
||||
*
|
||||
* @return TCarry
|
||||
*
|
||||
* @template TCarry
|
||||
*/
|
||||
public function reduce(callable $callback, mixed $initial): mixed
|
||||
{
|
||||
/** @var TCarry */
|
||||
return array_reduce($this->data, $callback, $initial);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CollectionInterface<T> $other The collection to check for divergent
|
||||
* items.
|
||||
*
|
||||
* @return CollectionInterface<T>
|
||||
*
|
||||
* @throws CollectionMismatchException if the compared collections are of
|
||||
* differing types.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CollectionInterface<T> $other The collection to check for
|
||||
* intersecting items.
|
||||
*
|
||||
* @return CollectionInterface<T>
|
||||
*
|
||||
* @throws CollectionMismatchException if the compared collections are of
|
||||
* differing types.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CollectionInterface<T> ...$collections The collections to merge.
|
||||
*
|
||||
* @return CollectionInterface<T>
|
||||
*
|
||||
* @throws CollectionMismatchException if unable to merge any of the given
|
||||
* collections or items within the given collections due to type
|
||||
* mismatch errors.
|
||||
*/
|
||||
public function merge(CollectionInterface ...$collections): CollectionInterface
|
||||
{
|
||||
$mergedCollection = clone $this;
|
||||
|
||||
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 ($this->getUniformType($collection) !== $this->getUniformType($this)) {
|
||||
throw new CollectionMismatchException(
|
||||
sprintf(
|
||||
'Collection items in collection with index %d must be of type %s',
|
||||
$index,
|
||||
$this->getType(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($collection as $key => $value) {
|
||||
if (is_int($key)) {
|
||||
$mergedCollection[] = $value;
|
||||
} else {
|
||||
$mergedCollection[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $mergedCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CollectionInterface<T> $other
|
||||
*
|
||||
* @throws CollectionMismatchException
|
||||
*/
|
||||
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 ($this->getUniformType($other) !== $this->getUniformType($this)) {
|
||||
throw new CollectionMismatchException('Collection items must be of type ' . $this->getType());
|
||||
}
|
||||
}
|
||||
|
||||
private function getComparator(): Closure
|
||||
{
|
||||
return /**
|
||||
* @param T $a
|
||||
* @param T $b
|
||||
*/
|
||||
function (mixed $a, mixed $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);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CollectionInterface<mixed> $collection
|
||||
*/
|
||||
private function getUniformType(CollectionInterface $collection): string
|
||||
{
|
||||
return match ($collection->getType()) {
|
||||
'integer' => 'int',
|
||||
'boolean' => 'bool',
|
||||
'double' => 'float',
|
||||
default => $collection->getType(),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
<?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
|
||||
* @extends AbstractCollection<T>
|
||||
*/
|
||||
abstract class AbstractSet extends AbstractCollection
|
||||
{
|
||||
public function add(mixed $element): bool
|
||||
{
|
||||
if ($this->contains($element)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return parent::add($element);
|
||||
}
|
||||
|
||||
public function offsetSet(mixed $offset, mixed $value): void
|
||||
{
|
||||
if ($this->contains($value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
parent::offsetSet($offset, $value);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* `ArrayInterface` provides traversable array functionality to data types.
|
||||
*
|
||||
* @template T
|
||||
* @extends ArrayAccess<array-key, T>
|
||||
* @extends IteratorAggregate<array-key, T>
|
||||
*/
|
||||
interface ArrayInterface extends
|
||||
ArrayAccess,
|
||||
Countable,
|
||||
IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
<?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
|
||||
* @extends AbstractCollection<T>
|
||||
*/
|
||||
class Collection extends AbstractCollection
|
||||
{
|
||||
/**
|
||||
* Constructs a collection object of the specified type, optionally with the
|
||||
* specified data.
|
||||
*
|
||||
* @param string $collectionType The type or class name associated with this
|
||||
* collection.
|
||||
* @param array<array-key, T> $data The initial items to store in the collection.
|
||||
*/
|
||||
public function __construct(private readonly string $collectionType, array $data = [])
|
||||
{
|
||||
parent::__construct($data);
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->collectionType;
|
||||
}
|
||||
}
|
||||
@@ -1,253 +0,0 @@
|
||||
<?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\CollectionMismatchException;
|
||||
use Ramsey\Collection\Exception\InvalidArgumentException;
|
||||
use Ramsey\Collection\Exception\InvalidPropertyOrMethod;
|
||||
use Ramsey\Collection\Exception\NoSuchElementException;
|
||||
use Ramsey\Collection\Exception\UnsupportedOperationException;
|
||||
|
||||
/**
|
||||
* A collection represents a group of values, known as its elements.
|
||||
*
|
||||
* Some collections allow duplicate elements and others do not. Some are ordered
|
||||
* and others unordered.
|
||||
*
|
||||
* @template T
|
||||
* @extends ArrayInterface<T>
|
||||
*/
|
||||
interface CollectionInterface extends ArrayInterface
|
||||
{
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @throws InvalidArgumentException if the collection refuses to add the
|
||||
* $element for any reason other than that it already contains the element.
|
||||
*/
|
||||
public function add(mixed $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.
|
||||
*/
|
||||
public function contains(mixed $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.
|
||||
*/
|
||||
public function remove(mixed $element): bool;
|
||||
|
||||
/**
|
||||
* Returns the values from the given property, method, or array key.
|
||||
*
|
||||
* @param string $propertyOrMethod The name of the property, method, or
|
||||
* array key to evaluate and return.
|
||||
*
|
||||
* @return array<int, mixed>
|
||||
*
|
||||
* @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
|
||||
* on the elements in this collection.
|
||||
* @throws UnsupportedOperationException if unable to call column() on this
|
||||
* collection.
|
||||
*/
|
||||
public function column(string $propertyOrMethod): array;
|
||||
|
||||
/**
|
||||
* Returns the first item of the collection.
|
||||
*
|
||||
* @return T
|
||||
*
|
||||
* @throws NoSuchElementException if this collection is empty.
|
||||
*/
|
||||
public function first(): mixed;
|
||||
|
||||
/**
|
||||
* Returns the last item of the collection.
|
||||
*
|
||||
* @return T
|
||||
*
|
||||
* @throws NoSuchElementException if this collection is empty.
|
||||
*/
|
||||
public function last(): mixed;
|
||||
|
||||
/**
|
||||
* Sort the collection by a property, method, or array key with the given
|
||||
* sort order.
|
||||
*
|
||||
* If $propertyOrMethod is `null`, this will sort by comparing each element.
|
||||
*
|
||||
* This will always leave the original collection untouched and will return
|
||||
* a new one.
|
||||
*
|
||||
* @param string | null $propertyOrMethod The property, method, or array key
|
||||
* to sort by.
|
||||
* @param Sort $order The sort order for the resulting collection.
|
||||
*
|
||||
* @return CollectionInterface<T>
|
||||
*
|
||||
* @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
|
||||
* on the elements in this collection.
|
||||
* @throws UnsupportedOperationException if unable to call sort() on this
|
||||
* collection.
|
||||
*/
|
||||
public function sort(?string $propertyOrMethod = null, Sort $order = Sort::Ascending): 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 the result of the given property, method,
|
||||
* or array key of each item in the collection equals the given value.
|
||||
*
|
||||
* This will always leave the original collection untouched and will return
|
||||
* a new one.
|
||||
*
|
||||
* @param string | null $propertyOrMethod The property, method, or array key
|
||||
* to evaluate. If `null`, the element itself is compared to $value.
|
||||
* @param mixed $value The value to match.
|
||||
*
|
||||
* @return CollectionInterface<T>
|
||||
*
|
||||
* @throws InvalidPropertyOrMethod if the $propertyOrMethod does not exist
|
||||
* on the elements in this collection.
|
||||
* @throws UnsupportedOperationException if unable to call where() on this
|
||||
* collection.
|
||||
*/
|
||||
public function where(?string $propertyOrMethod, mixed $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;
|
||||
|
||||
/**
|
||||
* Apply a given callback method on each item of the collection
|
||||
* to reduce it to a single value.
|
||||
*
|
||||
* See the {@link http://php.net/manual/en/function.array-reduce.php PHP array_reduce() documentation}
|
||||
* for examples of how the `$callback` and `$initial` parameters work.
|
||||
*
|
||||
* @param callable(TCarry, T): TCarry $callback A callable to apply to each
|
||||
* item of the collection to reduce it to a single value.
|
||||
* @param TCarry $initial This is the initial value provided to the callback.
|
||||
*
|
||||
* @return TCarry
|
||||
*
|
||||
* @template TCarry
|
||||
*/
|
||||
public function reduce(callable $callback, mixed $initial): mixed;
|
||||
|
||||
/**
|
||||
* 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>
|
||||
*
|
||||
* @throws CollectionMismatchException if the compared collections are of
|
||||
* differing types.
|
||||
*/
|
||||
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>
|
||||
*
|
||||
* @throws CollectionMismatchException if the compared collections are of
|
||||
* differing types.
|
||||
*/
|
||||
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>
|
||||
*
|
||||
* @throws CollectionMismatchException if unable to merge any of the given
|
||||
* collections or items within the given collections due to type
|
||||
* mismatch errors.
|
||||
*/
|
||||
public function merge(CollectionInterface ...$collections): self;
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
<?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 function array_key_last;
|
||||
use function array_pop;
|
||||
use function array_unshift;
|
||||
|
||||
/**
|
||||
* This class provides a basic implementation of `DoubleEndedQueueInterface`, to
|
||||
* minimize the effort required to implement this interface.
|
||||
*
|
||||
* @template T
|
||||
* @extends Queue<T>
|
||||
* @implements DoubleEndedQueueInterface<T>
|
||||
*/
|
||||
class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
|
||||
{
|
||||
/**
|
||||
* Constructs a double-ended queue (dequeue) object of the specified type,
|
||||
* optionally with the specified data.
|
||||
*
|
||||
* @param string $queueType The type or class name associated with this dequeue.
|
||||
* @param array<array-key, T> $data The initial items to store in the dequeue.
|
||||
*/
|
||||
public function __construct(private readonly string $queueType, array $data = [])
|
||||
{
|
||||
parent::__construct($this->queueType, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if $element is of the wrong type
|
||||
*/
|
||||
public function addFirst(mixed $element): bool
|
||||
{
|
||||
if ($this->checkType($this->getType(), $element) === false) {
|
||||
throw new InvalidArgumentException(
|
||||
'Value must be of type ' . $this->getType() . '; value is '
|
||||
. $this->toolValueToString($element),
|
||||
);
|
||||
}
|
||||
|
||||
array_unshift($this->data, $element);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if $element is of the wrong type
|
||||
*/
|
||||
public function addLast(mixed $element): bool
|
||||
{
|
||||
return $this->add($element);
|
||||
}
|
||||
|
||||
public function offerFirst(mixed $element): bool
|
||||
{
|
||||
try {
|
||||
return $this->addFirst($element);
|
||||
} catch (InvalidArgumentException) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function offerLast(mixed $element): bool
|
||||
{
|
||||
return $this->offer($element);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return T the first element in this queue.
|
||||
*
|
||||
* @throws NoSuchElementException if the queue is empty
|
||||
*/
|
||||
public function removeFirst(): mixed
|
||||
{
|
||||
return $this->remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return T the last element in this queue.
|
||||
*
|
||||
* @throws NoSuchElementException if this queue is empty.
|
||||
*/
|
||||
public function removeLast(): mixed
|
||||
{
|
||||
return $this->pollLast() ?? throw new NoSuchElementException(
|
||||
'Can\'t return element from Queue. Queue is empty.',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return T | null the head of this queue, or `null` if this queue is empty.
|
||||
*/
|
||||
public function pollFirst(): mixed
|
||||
{
|
||||
return $this->poll();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return T | null the tail of this queue, or `null` if this queue is empty.
|
||||
*/
|
||||
public function pollLast(): mixed
|
||||
{
|
||||
return array_pop($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return T the head of this queue.
|
||||
*
|
||||
* @throws NoSuchElementException if this queue is empty.
|
||||
*/
|
||||
public function firstElement(): mixed
|
||||
{
|
||||
return $this->element();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return T the tail of this queue.
|
||||
*
|
||||
* @throws NoSuchElementException if this queue is empty.
|
||||
*/
|
||||
public function lastElement(): mixed
|
||||
{
|
||||
return $this->peekLast() ?? throw new NoSuchElementException(
|
||||
'Can\'t return element from Queue. Queue is empty.',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return T | null the head of this queue, or `null` if this queue is empty.
|
||||
*/
|
||||
public function peekFirst(): mixed
|
||||
{
|
||||
return $this->peek();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return T | null the tail of this queue, or `null` if this queue is empty.
|
||||
*/
|
||||
public function peekLast(): mixed
|
||||
{
|
||||
$lastIndex = array_key_last($this->data);
|
||||
|
||||
if ($lastIndex === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->data[$lastIndex];
|
||||
}
|
||||
}
|
||||
-313
@@ -1,313 +0,0 @@
|
||||
<?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;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @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`.
|
||||
*/
|
||||
public function addFirst(mixed $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`.
|
||||
*/
|
||||
public function addLast(mixed $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`.
|
||||
*/
|
||||
public function offerFirst(mixed $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`.
|
||||
*/
|
||||
public function offerLast(mixed $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(): mixed;
|
||||
|
||||
/**
|
||||
* 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(): mixed;
|
||||
|
||||
/**
|
||||
* 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(): mixed;
|
||||
|
||||
/**
|
||||
* 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(): mixed;
|
||||
|
||||
/**
|
||||
* 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(): mixed;
|
||||
|
||||
/**
|
||||
* 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(): mixed;
|
||||
|
||||
/**
|
||||
* 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(): mixed;
|
||||
|
||||
/**
|
||||
* 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(): mixed;
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
<?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;
|
||||
|
||||
use Throwable;
|
||||
|
||||
interface CollectionException extends Throwable
|
||||
{
|
||||
}
|
||||
Vendored
-24
@@ -1,24 +0,0 @@
|
||||
<?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;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Thrown when attempting to operate on collections of differing types.
|
||||
*/
|
||||
class CollectionMismatchException extends RuntimeException implements CollectionException
|
||||
{
|
||||
}
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
<?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;
|
||||
|
||||
use InvalidArgumentException as PhpInvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Thrown to indicate an argument is not of the expected type.
|
||||
*/
|
||||
class InvalidArgumentException extends PhpInvalidArgumentException implements CollectionException
|
||||
{
|
||||
}
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
<?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;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Thrown when attempting to evaluate a property, method, or array key
|
||||
* that doesn't exist on an element or cannot otherwise be evaluated in the
|
||||
* current context.
|
||||
*/
|
||||
class InvalidPropertyOrMethod extends RuntimeException implements CollectionException
|
||||
{
|
||||
}
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
<?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;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Thrown when attempting to access an element that does not exist.
|
||||
*/
|
||||
class NoSuchElementException extends RuntimeException implements CollectionException
|
||||
{
|
||||
}
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
<?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;
|
||||
|
||||
use OutOfBoundsException as PhpOutOfBoundsException;
|
||||
|
||||
/**
|
||||
* Thrown when attempting to access an element out of the range of the collection.
|
||||
*/
|
||||
class OutOfBoundsException extends PhpOutOfBoundsException implements CollectionException
|
||||
{
|
||||
}
|
||||
Vendored
-24
@@ -1,24 +0,0 @@
|
||||
<?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;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Thrown to indicate that the requested operation is not supported.
|
||||
*/
|
||||
class UnsupportedOperationException extends RuntimeException implements CollectionException
|
||||
{
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<?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.
|
||||
*
|
||||
* @extends AbstractArray<mixed>
|
||||
*/
|
||||
class GenericArray extends AbstractArray
|
||||
{
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
<?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 Traversable;
|
||||
|
||||
use function array_key_exists;
|
||||
use function array_keys;
|
||||
use function in_array;
|
||||
use function var_export;
|
||||
|
||||
/**
|
||||
* This class provides a basic implementation of `MapInterface`, to minimize the
|
||||
* effort required to implement this interface.
|
||||
*
|
||||
* @template K of array-key
|
||||
* @template T
|
||||
* @extends AbstractArray<T>
|
||||
* @implements MapInterface<K, T>
|
||||
*/
|
||||
abstract class AbstractMap extends AbstractArray implements MapInterface
|
||||
{
|
||||
/**
|
||||
* @param array<K, T> $data The initial items to add to this map.
|
||||
*/
|
||||
public function __construct(array $data = [])
|
||||
{
|
||||
parent::__construct($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Traversable<K, T>
|
||||
*/
|
||||
public function getIterator(): Traversable
|
||||
{
|
||||
return parent::getIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param K $offset The offset to set
|
||||
* @param T $value The value to set at the given offset.
|
||||
*
|
||||
* @inheritDoc
|
||||
* @psalm-suppress MoreSpecificImplementedParamType,DocblockTypeContradiction
|
||||
*/
|
||||
public function offsetSet(mixed $offset, mixed $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;
|
||||
}
|
||||
|
||||
public function containsKey(int | string $key): bool
|
||||
{
|
||||
return array_key_exists($key, $this->data);
|
||||
}
|
||||
|
||||
public function containsValue(mixed $value): bool
|
||||
{
|
||||
return in_array($value, $this->data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function keys(): array
|
||||
{
|
||||
return array_keys($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param K $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.
|
||||
*/
|
||||
public function get(int | string $key, mixed $defaultValue = null): mixed
|
||||
{
|
||||
return $this[$key] ?? $defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param K $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`.
|
||||
*/
|
||||
public function put(int | string $key, mixed $value): mixed
|
||||
{
|
||||
$previousValue = $this->get($key);
|
||||
$this[$key] = $value;
|
||||
|
||||
return $previousValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param K $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`.
|
||||
*/
|
||||
public function putIfAbsent(int | string $key, mixed $value): mixed
|
||||
{
|
||||
$currentValue = $this->get($key);
|
||||
|
||||
if ($currentValue === null) {
|
||||
$this[$key] = $value;
|
||||
}
|
||||
|
||||
return $currentValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param K $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`.
|
||||
*/
|
||||
public function remove(int | string $key): mixed
|
||||
{
|
||||
$previousValue = $this->get($key);
|
||||
unset($this[$key]);
|
||||
|
||||
return $previousValue;
|
||||
}
|
||||
|
||||
public function removeIf(int | string $key, mixed $value): bool
|
||||
{
|
||||
if ($this->get($key) === $value) {
|
||||
unset($this[$key]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param K $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`.
|
||||
*/
|
||||
public function replace(int | string $key, mixed $value): mixed
|
||||
{
|
||||
$currentValue = $this->get($key);
|
||||
|
||||
if ($this->containsKey($key)) {
|
||||
$this[$key] = $value;
|
||||
}
|
||||
|
||||
return $currentValue;
|
||||
}
|
||||
|
||||
public function replaceIf(int | string $key, mixed $oldValue, mixed $newValue): bool
|
||||
{
|
||||
if ($this->get($key) === $oldValue) {
|
||||
$this[$key] = $newValue;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<K, T>
|
||||
*/
|
||||
public function __serialize(): array
|
||||
{
|
||||
return parent::__serialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<K, T>
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return parent::toArray();
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
<?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 of array-key
|
||||
* @template T
|
||||
* @extends AbstractMap<K, T>
|
||||
* @implements TypedMapInterface<K, T>
|
||||
*/
|
||||
abstract class AbstractTypedMap extends AbstractMap implements TypedMapInterface
|
||||
{
|
||||
use TypeTrait;
|
||||
use ValueToStringTrait;
|
||||
|
||||
/**
|
||||
* @param K $offset
|
||||
* @param T $value
|
||||
*
|
||||
* @inheritDoc
|
||||
* @psalm-suppress MoreSpecificImplementedParamType
|
||||
*/
|
||||
public function offsetSet(mixed $offset, mixed $value): void
|
||||
{
|
||||
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),
|
||||
);
|
||||
}
|
||||
|
||||
parent::offsetSet($offset, $value);
|
||||
}
|
||||
}
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
<?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.
|
||||
*
|
||||
* @extends AbstractMap<string, mixed>
|
||||
*/
|
||||
class AssociativeArrayMap extends AbstractMap
|
||||
{
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
<?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 K of array-key
|
||||
* @template T
|
||||
* @extends ArrayInterface<T>
|
||||
*/
|
||||
interface MapInterface extends ArrayInterface
|
||||
{
|
||||
/**
|
||||
* Returns `true` if this map contains a mapping for the specified key.
|
||||
*
|
||||
* @param K $key The key to check in the map.
|
||||
*/
|
||||
public function containsKey(int | string $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.
|
||||
*/
|
||||
public function containsValue(mixed $value): bool;
|
||||
|
||||
/**
|
||||
* Return an array of the keys contained in this map.
|
||||
*
|
||||
* @return list<K>
|
||||
*/
|
||||
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 K $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.
|
||||
*/
|
||||
public function get(int | string $key, mixed $defaultValue = null): mixed;
|
||||
|
||||
/**
|
||||
* 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 K $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`.
|
||||
*/
|
||||
public function put(int | string $key, mixed $value): mixed;
|
||||
|
||||
/**
|
||||
* 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 K $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`.
|
||||
*/
|
||||
public function putIfAbsent(int | string $key, mixed $value): mixed;
|
||||
|
||||
/**
|
||||
* Removes the mapping for a key from this map if it is present.
|
||||
*
|
||||
* @param K $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`.
|
||||
*/
|
||||
public function remove(int | string $key): mixed;
|
||||
|
||||
/**
|
||||
* 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 K $key The key to remove from the map.
|
||||
* @param T $value The value to match.
|
||||
*
|
||||
* @return bool true if the value was removed.
|
||||
*/
|
||||
public function removeIf(int | string $key, mixed $value): bool;
|
||||
|
||||
/**
|
||||
* Replaces the entry for the specified key only if it is currently mapped
|
||||
* to some value.
|
||||
*
|
||||
* @param K $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`.
|
||||
*/
|
||||
public function replace(int | string $key, mixed $value): mixed;
|
||||
|
||||
/**
|
||||
* 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 K $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.
|
||||
*/
|
||||
public function replaceIf(int | string $key, mixed $oldValue, mixed $newValue): bool;
|
||||
}
|
||||
-110
@@ -1,110 +0,0 @@
|
||||
<?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
|
||||
*
|
||||
* @extends AbstractMap<string, mixed>
|
||||
*/
|
||||
class NamedParameterMap extends AbstractMap
|
||||
{
|
||||
use TypeTrait;
|
||||
use ValueToStringTrait;
|
||||
|
||||
/**
|
||||
* Named parameters defined for this map.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private readonly array $namedParameters;
|
||||
|
||||
/**
|
||||
* Constructs a new `NamedParameterMap`.
|
||||
*
|
||||
* @param array<array-key, string> $namedParameters The named parameters defined for this map.
|
||||
* @param array<string, 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;
|
||||
}
|
||||
|
||||
public function offsetSet(mixed $offset, mixed $value): void
|
||||
{
|
||||
if (!array_key_exists($offset, $this->namedParameters)) {
|
||||
throw new InvalidArgumentException(
|
||||
'Attempting to set value for unconfigured parameter \''
|
||||
. $this->toolValueToString($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) ?: [];
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
<?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 `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 of array-key
|
||||
* @template T
|
||||
* @extends AbstractTypedMap<K, T>
|
||||
*/
|
||||
class TypedMap extends AbstractTypedMap
|
||||
{
|
||||
/**
|
||||
* 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(
|
||||
private readonly string $keyType,
|
||||
private readonly string $valueType,
|
||||
array $data = [],
|
||||
) {
|
||||
parent::__construct($data);
|
||||
}
|
||||
|
||||
public function getKeyType(): string
|
||||
{
|
||||
return $this->keyType;
|
||||
}
|
||||
|
||||
public function getValueType(): string
|
||||
{
|
||||
return $this->valueType;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
<?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 K of array-key
|
||||
* @template T
|
||||
* @extends MapInterface<K, 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;
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
<?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;
|
||||
|
||||
use function array_key_first;
|
||||
|
||||
/**
|
||||
* This class provides a basic implementation of `QueueInterface`, to minimize
|
||||
* the effort required to implement this interface.
|
||||
*
|
||||
* @template T
|
||||
* @extends AbstractArray<T>
|
||||
* @implements QueueInterface<T>
|
||||
*/
|
||||
class Queue extends AbstractArray implements QueueInterface
|
||||
{
|
||||
use TypeTrait;
|
||||
use ValueToStringTrait;
|
||||
|
||||
/**
|
||||
* Constructs a queue object of the specified type, optionally with the
|
||||
* specified data.
|
||||
*
|
||||
* @param string $queueType The type or class name associated with this queue.
|
||||
* @param array<array-key, T> $data The initial items to store in the queue.
|
||||
*/
|
||||
public function __construct(private readonly string $queueType, array $data = [])
|
||||
{
|
||||
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.
|
||||
*
|
||||
* @throws InvalidArgumentException if $value is of the wrong type.
|
||||
*/
|
||||
public function offsetSet(mixed $offset, mixed $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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if $value is of the wrong type.
|
||||
*/
|
||||
public function add(mixed $element): bool
|
||||
{
|
||||
$this[] = $element;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return T
|
||||
*
|
||||
* @throws NoSuchElementException if this queue is empty.
|
||||
*/
|
||||
public function element(): mixed
|
||||
{
|
||||
return $this->peek() ?? throw new NoSuchElementException(
|
||||
'Can\'t return element from Queue. Queue is empty.',
|
||||
);
|
||||
}
|
||||
|
||||
public function offer(mixed $element): bool
|
||||
{
|
||||
try {
|
||||
return $this->add($element);
|
||||
} catch (InvalidArgumentException) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return T | null
|
||||
*/
|
||||
public function peek(): mixed
|
||||
{
|
||||
$index = array_key_first($this->data);
|
||||
|
||||
if ($index === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this[$index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return T | null
|
||||
*/
|
||||
public function poll(): mixed
|
||||
{
|
||||
$index = array_key_first($this->data);
|
||||
|
||||
if ($index === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$head = $this[$index];
|
||||
unset($this[$index]);
|
||||
|
||||
return $head;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return T
|
||||
*
|
||||
* @throws NoSuchElementException if this queue is empty.
|
||||
*/
|
||||
public function remove(): mixed
|
||||
{
|
||||
return $this->poll() ?? throw new NoSuchElementException(
|
||||
'Can\'t return element from Queue. Queue is empty.',
|
||||
);
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->queueType;
|
||||
}
|
||||
}
|
||||
@@ -1,202 +0,0 @@
|
||||
<?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;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @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`.
|
||||
*/
|
||||
public function add(mixed $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(): mixed;
|
||||
|
||||
/**
|
||||
* 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`.
|
||||
*/
|
||||
public function offer(mixed $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(): mixed;
|
||||
|
||||
/**
|
||||
* 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(): mixed;
|
||||
|
||||
/**
|
||||
* 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(): mixed;
|
||||
|
||||
/**
|
||||
* Returns the type associated with this queue.
|
||||
*/
|
||||
public function getType(): string;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
<?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 doesn't exist
|
||||
* $set->add($foo); // returns FALSE, the element already exists
|
||||
*
|
||||
* $bar = new \My\Foo();
|
||||
* $set->add($bar); // returns TRUE, $bar !== $foo
|
||||
* ```
|
||||
*
|
||||
* @template T
|
||||
* @extends AbstractSet<T>
|
||||
*/
|
||||
class Set extends AbstractSet
|
||||
{
|
||||
/**
|
||||
* Constructs a set object of the specified type, optionally with the
|
||||
* specified data.
|
||||
*
|
||||
* @param string $setType The type or class name associated with this set.
|
||||
* @param array<array-key, T> $data The initial items to store in the set.
|
||||
*/
|
||||
public function __construct(private readonly string $setType, array $data = [])
|
||||
{
|
||||
parent::__construct($data);
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->setType;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Collection sorting
|
||||
*/
|
||||
enum Sort: string
|
||||
{
|
||||
/**
|
||||
* Sort items in a collection in ascending order.
|
||||
*/
|
||||
case Ascending = 'asc';
|
||||
|
||||
/**
|
||||
* Sort items in a collection in descending order.
|
||||
*/
|
||||
case Descending = 'desc';
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
<?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, mixed $value): bool
|
||||
{
|
||||
return match ($type) {
|
||||
'array' => is_array($value),
|
||||
'bool', 'boolean' => is_bool($value),
|
||||
'callable' => is_callable($value),
|
||||
'float', 'double' => is_float($value),
|
||||
'int', 'integer' => is_int($value),
|
||||
'null' => $value === null,
|
||||
'numeric' => is_numeric($value),
|
||||
'object' => is_object($value),
|
||||
'resource' => is_resource($value),
|
||||
'scalar' => is_scalar($value),
|
||||
'string' => is_string($value),
|
||||
'mixed' => true,
|
||||
default => $value instanceof $type,
|
||||
};
|
||||
}
|
||||
}
|
||||
-81
@@ -1,81 +0,0 @@
|
||||
<?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\InvalidPropertyOrMethod;
|
||||
use Ramsey\Collection\Exception\UnsupportedOperationException;
|
||||
|
||||
use function is_array;
|
||||
use function is_object;
|
||||
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, method, or array key from the
|
||||
* element.
|
||||
*
|
||||
* If `$propertyOrMethod` is `null`, we return the element as-is.
|
||||
*
|
||||
* @param mixed $element The element to extract the value from.
|
||||
* @param string | null $propertyOrMethod The property or method for which the
|
||||
* value should be extracted.
|
||||
*
|
||||
* @return mixed the value extracted from the specified property, method,
|
||||
* or array key, or the element itself.
|
||||
*
|
||||
* @throws InvalidPropertyOrMethod
|
||||
* @throws UnsupportedOperationException
|
||||
*/
|
||||
protected function extractValue(mixed $element, ?string $propertyOrMethod): mixed
|
||||
{
|
||||
if ($propertyOrMethod === null) {
|
||||
return $element;
|
||||
}
|
||||
|
||||
if (!is_object($element) && !is_array($element)) {
|
||||
throw new UnsupportedOperationException(sprintf(
|
||||
'The collection type "%s" does not support the $propertyOrMethod parameter',
|
||||
$this->getType(),
|
||||
));
|
||||
}
|
||||
|
||||
if (is_array($element)) {
|
||||
return $element[$propertyOrMethod] ?? throw new InvalidPropertyOrMethod(sprintf(
|
||||
'Key or index "%s" not found in collection elements',
|
||||
$propertyOrMethod,
|
||||
));
|
||||
}
|
||||
|
||||
if (property_exists($element, $propertyOrMethod)) {
|
||||
return $element->$propertyOrMethod;
|
||||
}
|
||||
|
||||
if (method_exists($element, $propertyOrMethod)) {
|
||||
return $element->{$propertyOrMethod}();
|
||||
}
|
||||
|
||||
throw new InvalidPropertyOrMethod(sprintf(
|
||||
'Method or property "%s" not defined in %s',
|
||||
$propertyOrMethod,
|
||||
$element::class,
|
||||
));
|
||||
}
|
||||
}
|
||||
-91
@@ -1,91 +0,0 @@
|
||||
<?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 assert;
|
||||
use function get_resource_type;
|
||||
use function is_array;
|
||||
use function is_bool;
|
||||
use function is_callable;
|
||||
use function is_object;
|
||||
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(mixed $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 . ')';
|
||||
}
|
||||
|
||||
// From here, $value should be an object.
|
||||
assert(is_object($value));
|
||||
|
||||
// __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 '(' . $value::class . ' Object)';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user