Passed
Push — master ( 457a90...753c96 )
by Sébastien
02:13
created

Pipeline::outlet()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Bdf\Pipeline;
4
5
use Bdf\Pipeline\Pipe\Pipe;
6
use Bdf\Pipeline\Processor\StackProcessor;
7
8
/**
9
 * Pipeline
10
 *
11
 * @author Sébastien Tanneux
12
 */
13
final class Pipeline implements PipeInterface
14
{
15
    /**
16
     * The pipe processor
17
     *
18
     * @var ProcessorInterface
19
     */
20
    private $processor;
21
22
    /**
23
     * The first pipe from the chain
24
     *
25
     * @var Pipe
26
     */
27
    private $first;
28
29
    /**
30
     * The last pipe from the chain
31
     *
32
     * @var Pipe
33
     */
34
    private $last;
35
36
    /**
37
     * The destination of the last pipe
38
     *
39
     * @var callable
40
     */
41
    private $outlet;
42
43
    /**
44
     * Pipeline constructor.
45
     *
46
     * @param array $pipes
47
     * @param ProcessorInterface $processor
48
     */
49
    public function __construct(array $pipes = [], ProcessorInterface $processor = null)
50
    {
51
        $this->processor = $processor ?: new StackProcessor();
52
53
        // Set the default outlet
54
        $this->outlet = function($payload) {
55
            return $payload;
56
        };
57
58
        foreach ($pipes as $pipe) {
59
            $this->pipe($pipe);
60
        }
61
    }
62
63
    /**
64
     * Add a pipe at the beginning of the chain
65
     *
66
     * @param callable $first
67
     */
68
    public function prepend($first)
69
    {
70
        $this->add($first, true);
71
    }
72
73
    /**
74
     * Add a pipe
75
     *
76
     * @param callable $last
77
     */
78
    public function pipe($last)
79
    {
80
        $this->add($last);
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     *
86
     * @internal
87
     */
88
    public function setNext(callable $pipe)
89
    {
90
        if ($pipe instanceof PipeInterface) {
91
            $this->add($pipe);
92
        } else {
93
            $this->outlet($pipe);
94
        }
95
    }
96
97
    /**
98
     * Add a pipe
99
     *
100
     * @param callable|PipeInterface $pipe
101
     * @param boolean $prepend
102
     */
103
    private function add($pipe, $prepend = false)
104
    {
105
        if (! $pipe instanceof PipeInterface) {
106
            $pipe = new Pipe($this->processor, $pipe);
107
        }
108
109
        // Set the outlet on last pipe
110
        $pipe->setNext($this->outlet);
111
112
        // Detect the first pipe
113
        if ($this->first === null) {
114
            $this->first = $pipe;
115
            $this->last = $pipe;
116
        } elseif ($prepend === false) {
117
            $this->last->setNext($pipe);
118
            $this->last = $pipe;
119
        } else {
120
            $pipe->setNext($this->first);
121
            $this->first = $pipe;
122
        }
123
    }
124
125
    /**
126
     * Set the pipeline outlet
127
     *
128
     * @param callable $outlet
129
     */
130
    public function outlet(callable $outlet)
131
    {
132
        $this->outlet = $outlet;
133
134
        if ($this->last !== null) {
135
            $this->last->setNext($outlet);
136
        }
137
    }
138
139
    /**
140
     * Send the payload into the pipeline.
141
     *
142
     * @param array $payload
143
     *
144
     * @return mixed
145
     */
146
    public function send(...$payload)
147
    {
148
        $callback = $this->first ?: $this->outlet;
149
150
        return $callback(...$payload);
151
    }
152
153
    /**
154
     * {@inheritdoc}
155
     */
156
    public function __invoke(...$payload)
157
    {
158
        return $this->send(...$payload);
159
    }
160
161
    /**
162
     * Clone the pipes
163
     */
164
    public function __clone()
165
    {
166
        if ($this->first !== null) {
167
            $this->first = clone $this->first;
168
        }
169
    }
170
}
171