diff --git a/src/Collections/Collection.php b/src/Collections/Collection.php index ea98db6..f7fec10 100644 --- a/src/Collections/Collection.php +++ b/src/Collections/Collection.php @@ -2,52 +2,55 @@ namespace jrosset\Collections; +use Closure; + /** * A collection * - * @psalm-template TKey of array-key - * @template-covariant TValue - * @template-extends ImmutableCollection - * @template-implements ICollection + * @template TKey of array-key + * @template TValue + * + * @implements ImmutableCollection + * @implements ICollection */ class Collection extends ImmutableCollection implements ICollection { /** * @inheritDoc */ - public function set (int|string $key, mixed $value): self { + public function set ($key, $value): static { return $this->_set($key, $value); } /** * @inheritDoc */ - public function merge (IImmutableCollection ...$collections): ICollection { + public function merge (IImmutableCollection ...$collections): static { return $this->_merge(...$collections); } /** * @inheritDoc */ - public function add (mixed ...$values): self { + public function add (...$values): static { return $this->_add(...$values); } /** * @inheritDoc */ - public function addCollection (IImmutableCollection ...$collections): ICollection { + public function addCollection (IImmutableCollection ...$collections): static { return $this->_addCollection(...$collections); } /** * @inheritDoc */ - public function prepend (mixed ...$values): ICollection { + public function prepend (...$values): static { array_unshift($this->elements, ...$values); return $this; } /** * @inheritDoc */ - public function prependCollection (IImmutableCollection ...$collections): ICollection { + public function prependCollection (IImmutableCollection ...$collections): static { $prepend = array_merge( ...array_map( function (IImmutableCollection $collection): array { @@ -62,21 +65,21 @@ class Collection extends ImmutableCollection implements ICollection { /** * @inheritDoc */ - public function clear (): self { + public function clear (): static { $this->_initialize(); return $this; } /** * @inheritDoc */ - public function remove (int|string $key): self { + public function remove ($key): static { unset($this->elements[$this->_normalizeKey($key)]); return $this; } /** * @inheritDoc */ - public function removeValue (mixed $value, bool $strict = false): self { + public function removeValue ($value, bool $strict = false): static { foreach ($this->elements as $currentKey => $currentValue) { if (($strict && $value === $currentValue) || (!$strict && $value == $currentValue)) { unset($this->elements[$currentKey]); @@ -97,4 +100,50 @@ class Collection extends ImmutableCollection implements ICollection { public function offsetUnset (mixed $offset): void { $this->remove($offset); } + + /** + * @inheritDoc + */ + public function sliceSelf (int $offset, ?int $length = null): static { + $this->elements = array_slice($this->elements, $offset, $length, true); + return $this; + } + + /** + * @inheritDoc + */ + public function filterSelf (Closure $filter): static { + $this->elements = array_filter($this->elements, $filter); + return $this; + } + /** + * @inheritDoc + */ + public function removeEmpties (): static { + return $this->filterSelf(function ($value) { + return empty($value); + }); + } + /** + * @inheritDoc + */ + public function mapSelf (Closure $process): static { + $this->elements = array_map($process, $this->elements); + return $this; + } + + /** + * @inheritDoc + */ + public function sortSelf (Closure|IComparator|null $sorter = null): static { + uasort($this->elements, $sorter); + return $this; + } + /** + * @inheritDoc + */ + public function sortSelfByKey (Closure|IComparator $sorter): static { + uksort($this->elements, $sorter); + return $this; + } } \ No newline at end of file diff --git a/src/Collections/IArrayCast.php b/src/Collections/IArrayCast.php index 2226353..e7225ef 100644 --- a/src/Collections/IArrayCast.php +++ b/src/Collections/IArrayCast.php @@ -5,15 +5,14 @@ namespace jrosset\Collections; /** * Interface for PHP-native array cast * - * @psalm-template TKey of array-key - * @template-covariant TValue + * @template TKey of array-key + * @template TValue */ interface IArrayCast { /** * Transform to a PHP-native array * - * @return array The native array - * @psalm-return array + * @return array The native array */ public function toArray (): array; } \ No newline at end of file diff --git a/src/Collections/ICollection.php b/src/Collections/ICollection.php index cabb3b3..d6c6b4c 100644 --- a/src/Collections/ICollection.php +++ b/src/Collections/ICollection.php @@ -2,98 +2,156 @@ namespace jrosset\Collections; +use Closure; +use Throwable; + /** * Interface for a collection * - * @psalm-template TKey of array-key - * @template-covariant TValue - * @template-extends IImmutableCollection + * @template TKey of array-key + * @template TValue + * + * @implements IImmutableCollection */ interface ICollection extends IImmutableCollection { /** * Set a value to a key * - * @param array-key $key The key - * @param mixed $value The value - * - * @psalm-param TKey $key - * @psalm-param TValue $value + * @param TKey $key The key + * @param TValue $value The value * * @return $this */ - public function set (int|string $key, mixed $value): self; + public function set ($key, $value): static; /** - * Merge one or multiple collections in the current one + * Merge one or multiple collections into the current one * - * @param IImmutableCollection ...$collections The collections to merge + * @param IImmutableCollection ...$collections The collections to merge * * @return $this */ - public function merge (IImmutableCollection ...$collections): self; + public function merge (IImmutableCollection ...$collections): static; /** * Add one or multiple values * - * @param mixed ...$values The values - * - * @psalm-param TValue ...$values + * @param TValue ...$values The values * * @return $this */ - public function add (mixed ...$values): self; + public function add (...$values): static; /** * Add the values of one or multiple collections * - * @param IImmutableCollection ...$collections The collections to add + * @param IImmutableCollection ...$collections The collections to add * - * @return mixed + * @return $this */ - public function addCollection (IImmutableCollection ...$collections): self; + public function addCollection (IImmutableCollection ...$collections): static; /** * Add one or multiple values at the beginning of the current collection * - * @param mixed ...$values The values - * - * @psalm-param TValue ...$values + * @param TValue ...$values The values * * @return $this */ - public function prepend (mixed ...$values): self; + public function prepend (...$values): static; /** * Add the values of one or multiple collections at the beginning of the current collection * - * @param IImmutableCollection ...$collections The collections to add + * @param IImmutableCollection ...$collections The collections to add * - * @return mixed + * @return $this */ - public function prependCollection (IImmutableCollection ...$collections): self; + public function prependCollection (IImmutableCollection ...$collections): static; /** - * Empties the collection + * Empty the collection * * @return $this */ - public function clear (): self; + public function clear (): static; /** - * Delete a key - * - * @param array-key $key The key + * Remove a value from it's key * - * @psalm-param TKey $key + * @param TKey $key The key * * @return $this */ - public function remove (int|string $key): self; + public function remove ($key): static; /** * Delete all instances of a value * - * @param mixed $value The value - * @param bool $strict Strict comparison ? + * @param TValue $value The value + * @param bool $strict Strict comparison ? + * + * @return $this + */ + public function removeValue ($value, bool $strict = false): static; + + /** + * Keep only a slice of the collection + * + * Preserves the keys * - * @psalm-param TValue $value + * @param int $offset The start offset + * @param int|null $length The maximum length. Null if until end of the collection * * @return $this */ - public function removeValue (mixed $value, bool $strict = false): self; + public function sliceSelf (int $offset, ?int $length = null): static; + + /** + * Keep only elements that satisfy predicate $filter + * + * @param Closure(TKey, TValue):bool $filter The filtering predicate + * + * @return $this + */ + public function filterSelf (Closure $filter): static; + /** + * Keep only non-empty elements + * + * Use {@see https://www.php.net/manual/function.empty.php empty} to check if element is empty or not + * + * @return $this + */ + public function removeEmpties (): static; + /** + * Applied $process on all elements + * + * @param Closure(TKey, TValue): TValue $process The process function to apply on each element + * + * @return $this + */ + public function mapSelf (Closure $process): static; + + /** + * Sort the elements (by value) + * + * @param null|IComparator|Closure(TValue, TValue):int $sorter The sorting method ; Null if values are object implementing {@see IComparable}. + *
Return : + *
< 0 if value1 is before value2 + *
= 0 if value1 equals value2 + *
> 0 if value1 is after value2 + * + * @return $this + * + * @throws Throwable If an error occurs + */ + public function sortSelf (Closure|IComparator|null $sorter = null): static; + /** + * Sort the elements by key + * + * @param IComparator|Closure(TKey, TKey):int $sorter The sorting method. Return : + *
< 0 if key1 is before key2 + *
= 0 if key1 equals key2 + *
> 0 if key1 is after key2 + * + * @return $this + * + * @throws Throwable If an error occurs + */ + public function sortSelfByKey (Closure|IComparator $sorter): static; } \ No newline at end of file diff --git a/src/Collections/IImmutableCollection.php b/src/Collections/IImmutableCollection.php index 348ffbe..7022274 100644 --- a/src/Collections/IImmutableCollection.php +++ b/src/Collections/IImmutableCollection.php @@ -12,11 +12,12 @@ use Throwable; /** * Interface for an immutable (read-only) collection * - * @psalm-template TKey of array-key - * @template-covariant TValue - * @template-extends IteratorAggregate - * @template-extends ArrayAccess - * @template-extends IArrayCast + * @template TKey of array-key + * @template TValue + * + * @implements IteratorAggregate + * @implements ArrayAccess + * @implements IArrayCast */ interface IImmutableCollection extends IteratorAggregate, JsonSerializable, Countable, ArrayAccess, IArrayCast { /** @@ -29,48 +30,38 @@ interface IImmutableCollection extends IteratorAggregate, JsonSerializable, Coun /** * Checks if a key exists * - * @param array-key $key The key - * - * @psalm-param TKey $key + * @param TKey $key The key * * @return bool TRUE if the key exists, FALSE otherwise */ - public function exists (int|string $key): bool; + public function exists ($key): bool; /** * Checks if contains a value * - * @param mixed $value The value - * @param bool $strict Strict comparison ? - * - * @psalm-param TValue $value + * @param TValue $value The value + * @param bool $strict Strict comparison ? * * @return bool TRUE if the value exists, FALSE otherwise */ - public function contains (mixed $value, bool $strict = false): bool; + public function contains ($value, bool $strict = false): bool; /** * Get the value of a key or null if not found * - * @param array-key $key The key + * @param TKey $key The key * - * @psalm-param TKey $key - * - * @return mixed The value - * @psalm-return TValue|null + * @return TValue|null The value */ - public function get (int|string $key): mixed; + public function get ($key): mixed; /** * Get the first key of a value or null if not found * - * @param mixed $value The value - * @param bool $strict Strict comparison ? - * - * @psalm-param TValue $value + * @param TValue $value The value + * @param bool $strict Strict comparison ? * - * @return array-key|null - * @psalm-return TKey|null + * @return TKey|null */ - public function key (mixed $value, bool $strict = false): int|string|null; + public function key ($value, bool $strict = false); /** * Extract a slice of the collection @@ -80,54 +71,39 @@ interface IImmutableCollection extends IteratorAggregate, JsonSerializable, Coun * @param int $offset The start offset * @param int|null $length The maximum length. Null if until end of the collection * - * @return static - * @psalm-return static + * @return static The result collection */ - public function slice (int $offset, ?int $length = null): self; + public function slice (int $offset, ?int $length = null): static; /** * Get a collection of all elements that satisfy predicate $filter * - * @param Closure $filter The filtering predicate - * - * @psalm-param Closure(TKey, TValue):bool $filter + * @param Closure(TKey, TValue):bool $filter The filtering predicate * - * @return static The result collection - * @psalm-return static + * @return static The result collection */ - public function filter (Closure $filter): self; + public function filter (Closure $filter): static; /** * Get a collection of all not empty elements * * Use {@see https://www.php.net/manual/function.empty.php empty} to check if element is empty or not * - * @return static The result collection + * @return static The result collection */ - public function withoutEmpties (): self; + public function withoutEmpties (): static; /** - * Remove all empty elements on current collection - * - * Use {@see https://www.php.net/manual/function.empty.php empty} to check if element is empty or not - * - * @return $this - */ - public function removeEmpties (): self; - /** - * A new collection with $process applied on all elements - * - * @psalm-template TResultValue + * A new collection with $process applied on all elements * - * @param Closure $process The process function to apply on each element + * @template TResultValue * - * @psalm-param Closure(TKey, TValue): TResultValue $process + * @param Closure(TKey, TValue): TResultValue $process The process function to apply on each element * - * @return static - * @psalm-return static + * @return static The result collection */ - public function map (Closure $process): self; + public function map (Closure $process): static; /** - * Sort the elements (by value) + * Get a collection with the elements sorted (by value) * * @param null|IComparator|Closure(TValue, TValue):int $sorter The sorting method ; Null if values are object implementing {@see IComparable}. *
Return : @@ -135,22 +111,20 @@ interface IImmutableCollection extends IteratorAggregate, JsonSerializable, Coun *
= 0 if value1 equals value2 *
> 0 if value1 is after value2 * - * @return static The sorted collection - * @psalm-return static + * @return static The result collection * * @throws Throwable If an error occurs */ public function sort (Closure|IComparator|null $sorter = null): static; /** - * Sort the elements by key + * Get a collection with the elements sorted by key * * @param IComparator|Closure(TKey, TKey):int $sorter The sorting method. Return : *
< 0 if key1 is before key2 *
= 0 if key1 equals key2 *
> 0 if key1 is after key2 * - * @return static The sorted collection - * @psalm-return static + * @return static The result collection * * @throws Throwable If an error occurs */ @@ -159,17 +133,15 @@ interface IImmutableCollection extends IteratorAggregate, JsonSerializable, Coun /** * The list of all keys * - * @return static The list of all keys - * @psalm-return static + * @return IImmutableCollection The list of all keys */ - public function keys (): self; + public function keys (): IImmutableCollection; /** * The list of all values * - * @return static The list of all values - * @psalm-return static + * @return static The list of all values */ - public function values (): self; + public function values (): static; /** * Join all values with a separator @@ -185,16 +157,16 @@ interface IImmutableCollection extends IteratorAggregate, JsonSerializable, Coun * @param string $value The value to split * @param string $separator The split separator * - * @return static + * @return static The result collection */ - public static function split (string $value, string $separator): self; + public static function split (string $value, string $separator): static; /** - * Combine the current collection with one or multiple other collections + * Merge the current collection with one or multiple collections * - * @param IImmutableCollection ...$collections The other collections to combine + * @param IImmutableCollection ...$collections The other collections to merge * - * @return static The combined collection + * @return static The result collection */ - public function combineWith (IImmutableCollection ...$collections): self; + public function mergeWith (IImmutableCollection ...$collections): static; } \ No newline at end of file diff --git a/src/Collections/ImmutableCollection.php b/src/Collections/ImmutableCollection.php index 82f6da6..353a155 100644 --- a/src/Collections/ImmutableCollection.php +++ b/src/Collections/ImmutableCollection.php @@ -10,25 +10,21 @@ use Traversable; /** * An immutable collection * - * @psalm-template TKey of array-key - * @template-covariant TValue - * @template-implements IImmutableCollection + * @template TKey of array-key + * @template TValue + * + * @implements IImmutableCollection */ class ImmutableCollection implements IImmutableCollection { /** - * @var array The internal array of elements - * @psalm-var array - * - * @internal + * @var array The internal array of elements */ protected array $elements; /** * Initialise a new collection * - * @param iterable|null $other The initial values - * - * @psalm-param array|Traversable|null $other + * @param iterable|null $other The initial values * * @throws InvalidArgumentException If the initial values aren't valid */ @@ -39,11 +35,10 @@ class ImmutableCollection implements IImmutableCollection { /** * Initialise the internals elements * - * @param iterable|null $other The initial values - * - * @psalm-param array|Traversable|null $other + * @param iterable|null $other The initial values * * @throws InvalidArgumentException If the initial values aren't valid + * * @internal */ protected function _initialize (?iterable $other = null): void { @@ -61,17 +56,14 @@ class ImmutableCollection implements IImmutableCollection { /** * Internally set a value to a key * - * @param array-key $key The key - * @param mixed $value The value - * - * @psalm-param TKey $key - * @psalm-param TValue $value + * @param TKey $key The key + * @param TValue $value The value * * @return $this - * @internal * + * @internal */ - protected function _set (int|string $key, mixed $value): self { + protected function _set ($key, $value): static { $this->elements[$this->_normalizeKey($key)] = $value; return $this; } @@ -81,8 +73,10 @@ class ImmutableCollection implements IImmutableCollection { * @param IImmutableCollection ...$collections The collections to merge * * @return $this + * + * @internal */ - protected function _merge (IImmutableCollection ...$collections): self { + protected function _merge (IImmutableCollection ...$collections): static { foreach ($collections as $collection) { foreach ($collection as $key => $value) { $this->_set($key, $value); @@ -93,15 +87,13 @@ class ImmutableCollection implements IImmutableCollection { /** * Internally add a value * - * @param mixed ...$values The value - * - * @psalm-param TValue ...$value + * @param TValue ...$values The value * * @return $this - * @internal * + * @internal */ - protected function _add (mixed ...$values): self { + protected function _add (...$values): static { foreach ($values as $value) { $this->elements[] = $value; } @@ -112,9 +104,9 @@ class ImmutableCollection implements IImmutableCollection { * * @param IImmutableCollection ...$collections The collections to add * - * @return mixed + * @return $this */ - protected function _addCollection (IImmutableCollection ...$collections): self { + protected function _addCollection (IImmutableCollection ...$collections): static { foreach ($collections as $collection) { foreach ($collection as $value) { $this->_add($value); @@ -125,14 +117,11 @@ class ImmutableCollection implements IImmutableCollection { /** * Normalize a key * - * @param array-key $key The key to normalize - * - * @psalm-param TKey $key + * @param TKey $key The key to normalize * - * @return array-key The normalized key - * @psalm-return TKey + * @return TKey The normalized key */ - protected function _normalizeKey (int|string $key): int|string { + protected function _normalizeKey ($key) { return $key; } @@ -212,26 +201,26 @@ class ImmutableCollection implements IImmutableCollection { /** * @inheritDoc */ - public function exists (int|string $key): bool { + public function exists ($key): bool { return isset($this->elements[$this->_normalizeKey($key)]); } /** * @inheritDoc */ - public function contains (mixed $value, bool $strict = false): bool { + public function contains ($value, bool $strict = false): bool { return in_array($value, $this->elements, $strict); } /** * @inheritDoc */ - public function get (int|string $key): mixed { + public function get ($key): mixed { return $this->elements[$this->_normalizeKey($key)] ?? null; } /** * @inheritDoc */ - public function key (mixed $value, bool $strict = false): int|string|null { + public function key ($value, bool $strict = false) { foreach ($this->elements as $currentKey => $currentValue) { if (($strict && $value === $currentValue) || (!$strict && $value == $currentValue)) { return $currentKey; @@ -243,7 +232,7 @@ class ImmutableCollection implements IImmutableCollection { /** * @inheritDoc */ - public function slice (int $offset, ?int $length = null): self { + public function slice (int $offset, ?int $length = null): static { $output = new static(); $currentIndex = 0; @@ -264,7 +253,7 @@ class ImmutableCollection implements IImmutableCollection { /** * @inheritDoc */ - public function filter (Closure $filter): self { + public function filter (Closure $filter): static { $output = new static(); foreach ($this->elements as $key => $value) { if (!$filter($key, $value)) { @@ -277,7 +266,7 @@ class ImmutableCollection implements IImmutableCollection { /** * @inheritDoc */ - public function withoutEmpties (): self { + public function withoutEmpties (): static { return $this->filter(function ($value) { return empty($value); }); @@ -285,14 +274,7 @@ class ImmutableCollection implements IImmutableCollection { /** * @inheritDoc */ - public function removeEmpties (): self { - $this->_initialize($this->withoutEmpties()); - return $this; - } - /** - * @inheritDoc - */ - public function map (Closure $process): self { + public function map (Closure $process): static { $output = new static(); foreach ($this->elements as $key => $value) { $output->_set($key, $process($key, $value)); @@ -339,13 +321,13 @@ class ImmutableCollection implements IImmutableCollection { /** * @inheritDoc */ - public function keys (): self { + public function keys (): IImmutableCollection { return new static(array_keys($this->elements)); } /** * @inheritDoc */ - public function values (): self { + public function values (): static { return new static(array_values($this->elements)); } @@ -365,14 +347,14 @@ class ImmutableCollection implements IImmutableCollection { /** * @inheritDoc */ - public static function split (string $value, string $separator): self { + public static function split (string $value, string $separator): static { return new static (explode($separator, $value)); } /** * @inheritDoc */ - public function combineWith (IImmutableCollection ...$collections): IImmutableCollection { + public function mergeWith (IImmutableCollection ...$collections): static { return (clone $this)->_merge(...$collections); } } \ No newline at end of file diff --git a/src/Collections/InsensitiveCaseKeyCollection.php b/src/Collections/InsensitiveCaseKeyCollection.php index 12b6321..534e3bb 100644 --- a/src/Collections/InsensitiveCaseKeyCollection.php +++ b/src/Collections/InsensitiveCaseKeyCollection.php @@ -5,9 +5,10 @@ namespace jrosset\Collections; /** * A collection with insensitive case keys * - * @psalm-template TKey of array-key - * @template-covariant TValue - * @template-extends Collection + * @template TKey of array-key + * @template TValue + * + * @implements Collection */ class InsensitiveCaseKeyCollection extends Collection { use TInsensitiveCaseKey; diff --git a/src/Collections/InsensitiveCaseKeyImmutableCollection.php b/src/Collections/InsensitiveCaseKeyImmutableCollection.php index 166b202..b561f18 100644 --- a/src/Collections/InsensitiveCaseKeyImmutableCollection.php +++ b/src/Collections/InsensitiveCaseKeyImmutableCollection.php @@ -5,9 +5,10 @@ namespace jrosset\Collections; /** * An immutable collection with insensitive case keys * - * @psalm-template TKey of array-key - * @template-covariant TValue - * @template-extends ImmutableCollection + * @template TKey of array-key + * @template TValue + * + * @implements ImmutableCollection */ class InsensitiveCaseKeyImmutableCollection extends ImmutableCollection implements IImmutableCollection { use TInsensitiveCaseKey; diff --git a/src/Collections/TUniqueValues.php b/src/Collections/TUniqueValues.php index 622ecff..16605fd 100644 --- a/src/Collections/TUniqueValues.php +++ b/src/Collections/TUniqueValues.php @@ -5,9 +5,8 @@ namespace jrosset\Collections; /** * Implementation for unique collection * - * @psalm-template TKey of array-key - * @template-covariant TValue - * @template-extends ImmutableCollection + * @template TKey of array-key + * @template TValue */ trait TUniqueValues { /** diff --git a/src/Collections/UniqueCollection.php b/src/Collections/UniqueCollection.php index 905f7b4..64005b7 100644 --- a/src/Collections/UniqueCollection.php +++ b/src/Collections/UniqueCollection.php @@ -5,10 +5,11 @@ namespace jrosset\Collections; /** * A collection with unique values * - * @psalm-template TKey of array-key - * @template-covariant TValue - * @template-extends Collection - * @template-extends TUniqueValues + * @template TKey of array-key + * @template TValue + * + * @implements Collection + * @implements TUniqueValues */ class UniqueCollection extends Collection { use TUniqueValues; diff --git a/src/Collections/UniqueImmutableCollection.php b/src/Collections/UniqueImmutableCollection.php index 6ce640d..af137ce 100644 --- a/src/Collections/UniqueImmutableCollection.php +++ b/src/Collections/UniqueImmutableCollection.php @@ -5,10 +5,11 @@ namespace jrosset\Collections; /** * An immutable collection with unique values * - * @psalm-template TKey of array-key - * @template-covariant TValue - * @template-extends ImmutableCollection - * @template-extends TUniqueValues + * @template TKey of array-key + * @template TValue + * + * @implements ImmutableCollection + * @implements TUniqueValues */ class UniqueImmutableCollection extends ImmutableCollection { use TUniqueValues;