Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Pipeline;
4
 
5
use Closure;
6
use Illuminate\Contracts\Container\Container;
7
use Illuminate\Contracts\Pipeline\Pipeline as PipelineContract;
8
use RuntimeException;
9
use Throwable;
10
 
11
class Pipeline implements PipelineContract
12
{
13
    /**
14
     * The container implementation.
15
     *
16
     * @var \Illuminate\Contracts\Container\Container|null
17
     */
18
    protected $container;
19
 
20
    /**
21
     * The object being passed through the pipeline.
22
     *
23
     * @var mixed
24
     */
25
    protected $passable;
26
 
27
    /**
28
     * The array of class pipes.
29
     *
30
     * @var array
31
     */
32
    protected $pipes = [];
33
 
34
    /**
35
     * The method to call on each pipe.
36
     *
37
     * @var string
38
     */
39
    protected $method = 'handle';
40
 
41
    /**
42
     * Create a new class instance.
43
     *
44
     * @param  \Illuminate\Contracts\Container\Container|null  $container
45
     * @return void
46
     */
47
    public function __construct(Container $container = null)
48
    {
49
        $this->container = $container;
50
    }
51
 
52
    /**
53
     * Set the object being sent through the pipeline.
54
     *
55
     * @param  mixed  $passable
56
     * @return $this
57
     */
58
    public function send($passable)
59
    {
60
        $this->passable = $passable;
61
 
62
        return $this;
63
    }
64
 
65
    /**
66
     * Set the array of pipes.
67
     *
68
     * @param  array|mixed  $pipes
69
     * @return $this
70
     */
71
    public function through($pipes)
72
    {
73
        $this->pipes = is_array($pipes) ? $pipes : func_get_args();
74
 
75
        return $this;
76
    }
77
 
78
    /**
79
     * Push additional pipes onto the pipeline.
80
     *
81
     * @param  array|mixed  $pipes
82
     * @return $this
83
     */
84
    public function pipe($pipes)
85
    {
86
        array_push($this->pipes, ...(is_array($pipes) ? $pipes : func_get_args()));
87
 
88
        return $this;
89
    }
90
 
91
    /**
92
     * Set the method to call on the pipes.
93
     *
94
     * @param  string  $method
95
     * @return $this
96
     */
97
    public function via($method)
98
    {
99
        $this->method = $method;
100
 
101
        return $this;
102
    }
103
 
104
    /**
105
     * Run the pipeline with a final destination callback.
106
     *
107
     * @param  \Closure  $destination
108
     * @return mixed
109
     */
110
    public function then(Closure $destination)
111
    {
112
        $pipeline = array_reduce(
113
            array_reverse($this->pipes()), $this->carry(), $this->prepareDestination($destination)
114
        );
115
 
116
        return $pipeline($this->passable);
117
    }
118
 
119
    /**
120
     * Run the pipeline and return the result.
121
     *
122
     * @return mixed
123
     */
124
    public function thenReturn()
125
    {
126
        return $this->then(function ($passable) {
127
            return $passable;
128
        });
129
    }
130
 
131
    /**
132
     * Get the final piece of the Closure onion.
133
     *
134
     * @param  \Closure  $destination
135
     * @return \Closure
136
     */
137
    protected function prepareDestination(Closure $destination)
138
    {
139
        return function ($passable) use ($destination) {
140
            try {
141
                return $destination($passable);
142
            } catch (Throwable $e) {
143
                return $this->handleException($passable, $e);
144
            }
145
        };
146
    }
147
 
148
    /**
149
     * Get a Closure that represents a slice of the application onion.
150
     *
151
     * @return \Closure
152
     */
153
    protected function carry()
154
    {
155
        return function ($stack, $pipe) {
156
            return function ($passable) use ($stack, $pipe) {
157
                try {
158
                    if (is_callable($pipe)) {
159
                        // If the pipe is a callable, then we will call it directly, but otherwise we
160
                        // will resolve the pipes out of the dependency container and call it with
161
                        // the appropriate method and arguments, returning the results back out.
162
                        return $pipe($passable, $stack);
163
                    } elseif (! is_object($pipe)) {
164
                        [$name, $parameters] = $this->parsePipeString($pipe);
165
 
166
                        // If the pipe is a string we will parse the string and resolve the class out
167
                        // of the dependency injection container. We can then build a callable and
168
                        // execute the pipe function giving in the parameters that are required.
169
                        $pipe = $this->getContainer()->make($name);
170
 
171
                        $parameters = array_merge([$passable, $stack], $parameters);
172
                    } else {
173
                        // If the pipe is already an object we'll just make a callable and pass it to
174
                        // the pipe as-is. There is no need to do any extra parsing and formatting
175
                        // since the object we're given was already a fully instantiated object.
176
                        $parameters = [$passable, $stack];
177
                    }
178
 
179
                    $carry = method_exists($pipe, $this->method)
180
                                    ? $pipe->{$this->method}(...$parameters)
181
                                    : $pipe(...$parameters);
182
 
183
                    return $this->handleCarry($carry);
184
                } catch (Throwable $e) {
185
                    return $this->handleException($passable, $e);
186
                }
187
            };
188
        };
189
    }
190
 
191
    /**
192
     * Parse full pipe string to get name and parameters.
193
     *
194
     * @param  string  $pipe
195
     * @return array
196
     */
197
    protected function parsePipeString($pipe)
198
    {
199
        [$name, $parameters] = array_pad(explode(':', $pipe, 2), 2, []);
200
 
201
        if (is_string($parameters)) {
202
            $parameters = explode(',', $parameters);
203
        }
204
 
205
        return [$name, $parameters];
206
    }
207
 
208
    /**
209
     * Get the array of configured pipes.
210
     *
211
     * @return array
212
     */
213
    protected function pipes()
214
    {
215
        return $this->pipes;
216
    }
217
 
218
    /**
219
     * Get the container instance.
220
     *
221
     * @return \Illuminate\Contracts\Container\Container
222
     *
223
     * @throws \RuntimeException
224
     */
225
    protected function getContainer()
226
    {
227
        if (! $this->container) {
228
            throw new RuntimeException('A container instance has not been passed to the Pipeline.');
229
        }
230
 
231
        return $this->container;
232
    }
233
 
234
    /**
235
     * Set the container instance.
236
     *
237
     * @param  \Illuminate\Contracts\Container\Container  $container
238
     * @return $this
239
     */
240
    public function setContainer(Container $container)
241
    {
242
        $this->container = $container;
243
 
244
        return $this;
245
    }
246
 
247
    /**
248
     * Handle the value returned from each pipe before passing it to the next.
249
     *
250
     * @param  mixed  $carry
251
     * @return mixed
252
     */
253
    protected function handleCarry($carry)
254
    {
255
        return $carry;
256
    }
257
 
258
    /**
259
     * Handle the given exception.
260
     *
261
     * @param  mixed  $passable
262
     * @param  \Throwable  $e
263
     * @return mixed
264
     *
265
     * @throws \Throwable
266
     */
267
    protected function handleException($passable, Throwable $e)
268
    {
269
        throw $e;
270
    }
271
}