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
![]() |
|||
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 |