Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@
"tiny-blocks/mapper": "^3.2"
},
"require-dev": {
"ergebnis/composer-normalize": "^2.52",
"infection/infection": "^0.34",
"phpstan/phpstan": "^2.2",
"phpunit/phpunit": "^13.2",
"ergebnis/composer-normalize": "^2.54",
"infection/infection": "^0.35",
"phpstan/phpstan": "^2.3",
"phpunit/phpunit": "^13.4",
"slevomat/coding-standard": "^8.31",
"squizlabs/php_codesniffer": "^4.0",
"symfony/console": "^8.1",
Expand Down Expand Up @@ -76,7 +76,7 @@
"test-file": "@php ./vendor/bin/phpunit --configuration phpunit.xml --no-coverage --filter",
"tests": [
"@php -d memory_limit=2G ./vendor/bin/phpunit --configuration phpunit.xml tests",
"@php ./vendor/bin/infection --threads=max --logger-html=reports/coverage/mutation-report.html --coverage=reports/coverage"
"@php ./vendor/bin/infection --threads=max --logger-html=reports/coverage/mutation-report.html"
]
}
}
334 changes: 167 additions & 167 deletions src/Collectible.php

Large diffs are not rendered by default.

124 changes: 62 additions & 62 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ public static function createFrom(iterable $elements): static
return new static(pipeline: EagerPipeline::from(source: $elements));
}

public static function createLazyFrom(iterable $elements): static
{
return new static(pipeline: LazyPipeline::from(source: $elements));
}

public static function createFromEmpty(): static
{
return static::createFrom(elements: []);
Expand All @@ -57,11 +62,6 @@ public static function createFromClosure(Closure $factory): static
return new static(pipeline: EagerPipeline::fromClosure(factory: $factory));
}

public static function createLazyFrom(iterable $elements): static
{
return new static(pipeline: LazyPipeline::from(source: $elements));
}

public static function createLazyFromEmpty(): static
{
return static::createLazyFrom(elements: []);
Expand All @@ -72,116 +72,106 @@ public static function createLazyFromClosure(Closure $factory): static
return new static(pipeline: LazyPipeline::fromClosure(factory: $factory));
}

public function getIterator(): Traversable
{
return $this->pipeline->process();
}

public function add(mixed ...$elements): static
{
return new static(pipeline: $this->pipeline->pipe(operation: Add::these(newElements: $elements)));
}

public function merge(Collectible $other): static
public function map(Closure ...$transformations): static
{
return new static(pipeline: $this->pipeline->pipe(operation: Merge::with(other: $other)));
return new static(pipeline: $this->pipeline->pipe(operation: Map::using(...$transformations)));
}

public function contains(mixed $element): bool
public function each(Closure ...$actions): void
{
return Equality::exists(elements: $this->pipeline->process(), element: $element);
Each::on(actions: $actions, elements: $this->pipeline->process());
}

public function count(): int
public function last(mixed $defaultValueIfNotFound = null): mixed
{
return $this->pipeline->count();
return $this->pipeline->last(defaultValueIfNotFound: $defaultValueIfNotFound);
}

public function findBy(Closure ...$predicates): mixed
public function sort(Order $order = Order::ASCENDING_KEY, ?Closure $comparator = null): static
{
return Find::firstMatch(elements: $this->pipeline->process(), predicates: $predicates);
}
$operation = Rearrange::by(order: $order, comparator: $comparator);

public function each(Closure ...$actions): void
{
Each::on(elements: $this->pipeline->process(), actions: $actions);
return new static(pipeline: $this->pipeline->pipe(operation: $operation));
}

public function equals(Collectible $other): bool
public function count(): int
{
return Equality::compareAll(elements: $this->pipeline->process(), other: $other);
return $this->pipeline->count();
}

public function remove(mixed $element): static
public function first(mixed $defaultValueIfNotFound = null): mixed
{
return new static(pipeline: $this->pipeline->pipe(operation: Remove::element(element: $element)));
return $this->pipeline->first(defaultValueIfNotFound: $defaultValueIfNotFound);
}

public function removeAll(?Closure $predicate = null): static
public function getBy(int $index, mixed $defaultValueIfNotFound = null): mixed
{
return new static(pipeline: $this->pipeline->pipe(operation: RemoveAll::matching(predicate: $predicate)));
return $this->pipeline->getBy(index: $index, defaultValueIfNotFound: $defaultValueIfNotFound);
}

public function filter(?Closure ...$predicates): static
public function merge(Collectible $other): static
{
return new static(pipeline: $this->pipeline->pipe(operation: Filter::matching(...$predicates)));
return new static(pipeline: $this->pipeline->pipe(operation: Merge::with(other: $other)));
}

public function first(mixed $defaultValueIfNotFound = null): mixed
public function slice(int $offset, int $length = -1): static
{
return $this->pipeline->first(defaultValueIfNotFound: $defaultValueIfNotFound);
return new static(pipeline: $this->pipeline->pipe(operation: Segment::from(length: $length, offset: $offset)));
}

public function flatten(): static
public function equals(Collectible $other): bool
{
return new static(pipeline: $this->pipeline->pipe(operation: FlatMap::oneLevel()));
return Equality::compareAll(other: $other, elements: $this->pipeline->process());
}

public function getBy(int $index, mixed $defaultValueIfNotFound = null): mixed
public function filter(?Closure ...$predicates): static
{
return $this->pipeline->getBy(index: $index, defaultValueIfNotFound: $defaultValueIfNotFound);
return new static(pipeline: $this->pipeline->pipe(operation: Filter::matching(...$predicates)));
}

public function groupBy(Closure $classifier): static
public function findBy(Closure ...$predicates): mixed
{
return new static(pipeline: $this->pipeline->pipe(operation: GroupInto::by(classifier: $classifier)));
return Find::firstMatch(elements: $this->pipeline->process(), predicates: $predicates);
}

public function isEmpty(): bool
public function reduce(Closure $accumulator, mixed $initial): mixed
{
return $this->pipeline->isEmpty();
return Reduce::from(initial: $initial, elements: $this->pipeline->process(), accumulator: $accumulator);
}

public function joinToString(string $separator): string
public function remove(mixed $element): static
{
return Join::elements(elements: $this->pipeline->process(), separator: $separator);
return new static(pipeline: $this->pipeline->pipe(operation: Remove::element(element: $element)));
}

public function last(mixed $defaultValueIfNotFound = null): mixed
public function toJson(KeyPreservation $keyPreservation = KeyPreservation::PRESERVE): string
{
return $this->pipeline->last(defaultValueIfNotFound: $defaultValueIfNotFound);
}
$configuration = match ($keyPreservation) {
KeyPreservation::DISCARD => Configuration::default()->discardingKeys(),
KeyPreservation::PRESERVE => Configuration::default()
};

public function map(Closure ...$transformations): static
{
return new static(pipeline: $this->pipeline->pipe(operation: Map::using(...$transformations)));
return Mapper::create()->toJson(source: $this, configuration: $configuration);
}

public function reduce(Closure $accumulator, mixed $initial): mixed
public function flatten(): static
{
return Reduce::from(elements: $this->pipeline->process(), accumulator: $accumulator, initial: $initial);
return new static(pipeline: $this->pipeline->pipe(operation: FlatMap::oneLevel()));
}

public function sort(Order $order = Order::ASCENDING_KEY, ?Closure $comparator = null): static
public function groupBy(Closure $classifier): static
{
$operation = Rearrange::by(order: $order, comparator: $comparator);

return new static(pipeline: $this->pipeline->pipe(operation: $operation));
return new static(pipeline: $this->pipeline->pipe(operation: GroupInto::by(classifier: $classifier)));
}

public function slice(int $offset, int $length = -1): static
public function isEmpty(): bool
{
return new static(pipeline: $this->pipeline->pipe(operation: Segment::from(offset: $offset, length: $length)));
return $this->pipeline->isEmpty();
}

public function toArray(KeyPreservation $keyPreservation = KeyPreservation::PRESERVE): array
Expand All @@ -194,13 +184,23 @@ public function toArray(KeyPreservation $keyPreservation = KeyPreservation::PRES
return Mapper::create()->toArray(source: $this, configuration: $configuration);
}

public function toJson(KeyPreservation $keyPreservation = KeyPreservation::PRESERVE): string
public function contains(mixed $element): bool
{
$configuration = match ($keyPreservation) {
KeyPreservation::DISCARD => Configuration::default()->discardingKeys(),
KeyPreservation::PRESERVE => Configuration::default()
};
return Equality::exists(element: $element, elements: $this->pipeline->process());
}

return Mapper::create()->toJson(source: $this, configuration: $configuration);
public function removeAll(?Closure $predicate = null): static
{
return new static(pipeline: $this->pipeline->pipe(operation: RemoveAll::matching(predicate: $predicate)));
}

public function getIterator(): Traversable
{
return $this->pipeline->process();
}

public function joinToString(string $separator): string
{
return Join::elements(elements: $this->pipeline->process(), separator: $separator);
}
}
28 changes: 14 additions & 14 deletions src/Internal/EagerPipeline.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ public static function fromClosure(Closure $factory): EagerPipeline
return new EagerPipeline(materialization: Materialization::from(source: $elements, stages: []));
}

public function last(mixed $defaultValueIfNotFound = null): mixed
{
$elements = $this->materialization->elements();

return $elements === []
? $defaultValueIfNotFound
: $elements[array_key_last($elements)];
}

public function pipe(Operation $operation): Pipeline
{
return new EagerPipeline(materialization: $this->materialization->withStage(operation: $operation));
Expand All @@ -56,11 +65,6 @@ public function count(): int
return count($this->materialization->elements());
}

public function isEmpty(): bool
{
return $this->materialization->elements() === [];
}

public function first(mixed $defaultValueIfNotFound = null): mixed
{
$elements = $this->materialization->elements();
Expand All @@ -70,15 +74,6 @@ public function first(mixed $defaultValueIfNotFound = null): mixed
: $elements[array_key_first($elements)];
}

public function last(mixed $defaultValueIfNotFound = null): mixed
{
$elements = $this->materialization->elements();

return $elements === []
? $defaultValueIfNotFound
: $elements[array_key_last($elements)];
}

public function getBy(int $index, mixed $defaultValueIfNotFound = null): mixed
{
$elements = $this->materialization->elements();
Expand All @@ -88,6 +83,11 @@ public function getBy(int $index, mixed $defaultValueIfNotFound = null): mixed
: $defaultValueIfNotFound;
}

public function isEmpty(): bool
{
return $this->materialization->elements() === [];
}

public function process(): Generator
{
/** @var array<int, TValue> $elements */
Expand Down
32 changes: 16 additions & 16 deletions src/Internal/LazyPipeline.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ public static function fromClosure(Closure $factory): LazyPipeline
return new LazyPipeline(source: $factory);
}

public function last(mixed $defaultValueIfNotFound = null): mixed
{
$last = $defaultValueIfNotFound;

foreach ($this->process() as $element) {
$last = $element;
}

return $last;
}

public function pipe(Operation $operation): Pipeline
{
$stages = $this->stages;
Expand All @@ -63,22 +74,6 @@ public function first(mixed $defaultValueIfNotFound = null): mixed
return $defaultValueIfNotFound;
}

public function isEmpty(): bool
{
return !$this->process()->valid();
}

public function last(mixed $defaultValueIfNotFound = null): mixed
{
$last = $defaultValueIfNotFound;

foreach ($this->process() as $element) {
$last = $element;
}

return $last;
}

public function getBy(int $index, mixed $defaultValueIfNotFound = null): mixed
{
foreach ($this->process() as $currentIndex => $value) {
Expand All @@ -90,6 +85,11 @@ public function getBy(int $index, mixed $defaultValueIfNotFound = null): mixed
return $defaultValueIfNotFound;
}

public function isEmpty(): bool
{
return !$this->process()->valid();
}

public function process(): Generator
{
/** @var iterable<int|string, TValue> $elements */
Expand Down
2 changes: 1 addition & 1 deletion src/Internal/Operations/Resolving/Each.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ private function __construct()
{
}

public static function on(iterable $elements, array $actions): void
public static function on(array $actions, iterable $elements): void
{
foreach ($elements as $key => $value) {
foreach ($actions as $action) {
Expand Down
Loading