| 1 | <?php /** @noinspection PhpInternalEntityUsedInspection */ |
||
| 2 | |||
| 3 | declare(strict_types=1); |
||
| 4 | |||
| 5 | namespace Improved\IteratorPipeline; |
||
| 6 | |||
| 7 | use Improved as i; |
||
| 8 | use Improved\Iterator\CombineIterator; |
||
| 9 | use Improved\IteratorPipeline\PipelineBuilder\Stub; |
||
| 10 | use Improved\IteratorPipeline\Traits\FilteringTrait; |
||
| 11 | use Improved\IteratorPipeline\Traits\MappingTrait; |
||
| 12 | use Improved\IteratorPipeline\Traits\SortingTrait; |
||
| 13 | |||
| 14 | /** |
||
| 15 | * The `PipelineBuilder` can be used to create a blueprint for pipelines. |
||
| 16 | */ |
||
| 17 | class PipelineBuilder |
||
| 18 | { |
||
| 19 | use MappingTrait; |
||
| 20 | use FilteringTrait; |
||
| 21 | use SortingTrait; |
||
| 22 | |||
| 23 | /** |
||
| 24 | * @var array |
||
| 25 | */ |
||
| 26 | protected $steps = []; |
||
|
0 ignored issues
–
show
introduced
by
Loading history...
|
|||
| 27 | |||
| 28 | |||
| 29 | /** |
||
| 30 | * Define the next step via a callback that returns an array or Traversable object. |
||
| 31 | * |
||
| 32 | * @param callable $callback |
||
| 33 | * @param mixed ...$args |
||
| 34 | * @return static |
||
| 35 | */ |
||
| 36 | 9 | public function then(callable $callback, ...$args): self |
|
| 37 | { |
||
| 38 | 9 | $copy = clone $this; |
|
| 39 | |||
| 40 | 9 | if ($callback instanceof self) { |
|
| 41 | 2 | $copy->steps = array_merge($this->steps, $callback->steps); |
|
| 42 | } else { |
||
| 43 | 9 | $copy->steps[] = [$callback, $args]; |
|
| 44 | } |
||
| 45 | |||
| 46 | 9 | return $copy; |
|
| 47 | } |
||
| 48 | |||
| 49 | |||
| 50 | /** |
||
| 51 | * Add a stub, which does nothing but can be replaced later. |
||
| 52 | * |
||
| 53 | * @param string $name |
||
| 54 | * @return static |
||
| 55 | * @throw \BadMethodCallException if stub already exists |
||
| 56 | */ |
||
| 57 | 2 | public function stub(string $name): self |
|
| 58 | { |
||
| 59 | 2 | $hasStub = i\iterable_has_any($this->steps, function ($step) use ($name) { |
|
|
0 ignored issues
–
show
|
|||
| 60 | 2 | return $step[0] instanceof Stub && $step[0]->getName() === $name; |
|
| 61 | 2 | }); |
|
| 62 | |||
| 63 | 2 | if ($hasStub) { |
|
| 64 | 1 | throw new \BadMethodCallException("Pipeline builder already has '$name' stub"); |
|
| 65 | } |
||
| 66 | |||
| 67 | 2 | return $this->then(new Stub($name)); |
|
| 68 | } |
||
| 69 | |||
| 70 | /** |
||
| 71 | * Get a pipeline builder where a stub is replaced. |
||
| 72 | * |
||
| 73 | * @param string $name |
||
| 74 | * @param callable $callable |
||
| 75 | * @param mixed ...$args |
||
| 76 | * @return static |
||
| 77 | */ |
||
| 78 | 2 | public function unstub(string $name, callable $callable, ...$args): self |
|
| 79 | { |
||
| 80 | 2 | $index = i\iterable_find_key($this->steps, function ($step) use ($name) { |
|
|
0 ignored issues
–
show
|
|||
| 81 | 2 | return $step[0] instanceof Stub && $step[0]->getName() === $name; |
|
| 82 | 2 | }); |
|
| 83 | |||
| 84 | 2 | if ($index === null) { |
|
| 85 | 1 | throw new \BadMethodCallException("Pipeline builder doesn't have '$name' stub"); |
|
| 86 | } |
||
| 87 | |||
| 88 | 1 | $clone = clone $this; |
|
| 89 | 1 | $clone->steps[$index] = [$callable, $args]; |
|
| 90 | |||
| 91 | 1 | return $clone; |
|
| 92 | } |
||
| 93 | |||
| 94 | |||
| 95 | /** |
||
| 96 | * Create a new pipeline |
||
| 97 | * |
||
| 98 | * @param iterable $iterable |
||
| 99 | * @return Pipeline |
||
| 100 | */ |
||
| 101 | 7 | public function with(iterable $iterable): Pipeline |
|
|
0 ignored issues
–
show
|
|||
| 102 | { |
||
| 103 | 7 | $pipeline = new Pipeline($iterable); |
|
| 104 | |||
| 105 | 7 | foreach ($this->steps as [$callback, $args]) { |
|
| 106 | 7 | $pipeline = $pipeline->then($callback, ...$args); |
|
| 107 | } |
||
| 108 | |||
| 109 | 7 | return $pipeline; |
|
| 110 | } |
||
| 111 | |||
| 112 | /** |
||
| 113 | * Invoke the builder. |
||
| 114 | * |
||
| 115 | * @param iterable $iterable |
||
| 116 | * @return array |
||
| 117 | */ |
||
| 118 | 3 | public function __invoke(iterable $iterable): array |
|
|
0 ignored issues
–
show
|
|||
| 119 | { |
||
| 120 | 3 | return $this->with($iterable)->toArray(); |
|
| 121 | } |
||
| 122 | |||
| 123 | |||
| 124 | /** |
||
| 125 | * Use another iterator as keys and the current iterator as values. |
||
| 126 | * |
||
| 127 | * @param iterable $keys Keys will be turned into an array. |
||
| 128 | * @return static |
||
| 129 | */ |
||
| 130 | 1 | public function setKeys(iterable $keys) |
|
|
0 ignored issues
–
show
|
|||
| 131 | { |
||
| 132 | 1 | $combine = function ($values, $keys) { |
|
|
0 ignored issues
–
show
|
|||
| 133 | 1 | return new CombineIterator($keys, $values); |
|
| 134 | 1 | }; |
|
| 135 | |||
| 136 | 1 | return $this->then($combine, i\iterable_to_array($keys)); |
|
| 137 | } |
||
| 138 | } |
||
| 139 |