Passed
Push — master ( e65d14...ed7f33 )
by Arnold
01:53
created

PipelineBuilder::unstub()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 2
nop 3
dl 0
loc 14
ccs 8
cts 8
cp 1
crap 3
rs 10
c 0
b 0
f 0
1
<?php
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 = [];
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 8
    public function then(callable $callback, ...$args): self
37
    {
38 8
        $copy = clone $this;
39
40 8
        if ($callback instanceof self) {
41 2
            $copy->steps = array_merge($this->steps, $callback->steps);
42
        } else {
43 8
            $copy->steps[] = [$callback, $args];
44
        }
45
46 8
        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
        $hasStub = i\iterable_has_any($this->steps, function($step) use ($name) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
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
        $index = i\iterable_find_key($this->steps, function($step) use ($name) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
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 6
    public function with(iterable $iterable): Pipeline
102
    {
103 6
        $pipeline = new Pipeline($iterable);
104
105 6
        foreach ($this->steps as [$callback, $args]) {
106 6
            $pipeline->then($callback, ...$args);
107
        }
108
109 6
        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
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)
131
    {
132
        $combine = function ($values, $keys) {
133 1
            return new CombineIterator($keys, $values);
134 1
        };
135
136 1
        return $this->then($combine, i\iterable_to_array($keys));
137
    }
138
}
139