Pipeline   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 165
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 13
eloc 38
c 1
b 0
f 0
dl 0
loc 165
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A then() 0 7 1
A parsePipeString() 0 9 2
A prepareDestination() 0 4 1
A through() 0 5 2
A send() 0 5 1
A carry() 0 30 4
A via() 0 5 1
A with() 0 5 1
1
<?php
2
/**
3
 *
4
 * KNUT7 K7F (https://marciozebedeu.com/)
5
 * KNUT7 K7F (tm) : Rapid Development Framework (https://marciozebedeu.com/)
6
 *
7
 * Licensed under The MIT License
8
 * For full copyright and license information, please see the LICENSE.txt
9
 * Redistributions of files must retain the above copyright notice.
10
 *
11
 * @link      https://github.com/knut7/framework/ for the canonical source repository
12
 * @copyright (c) 2015.  KNUT7  Software Technologies AO Inc. (https://marciozebedeu.com/)
13
 * @license   https://marciozebedeu.com/license/new-bsd New BSD License
14
 * @author    Marcio Zebedeu - [email protected]
15
 * @version   1.0.7
16
 *
17
 *
18
 */
19
20
namespace Ballybran\Core\Http;
21
22
use Closure;
23
24
class Pipeline
25
{
26
27
    /**
28
     * The object being passed through the pipeline.
29
     *
30
     * @var mixed
31
     */
32
    protected $passable;
33
34
    /**
35
     * The array of class pipes.
36
     *
37
     * @var array
38
     */
39
    protected $pipes = [];
40
41
    /**
42
     * The additional parameters.
43
     *
44
     * @var array
45
     */
46
    protected $parameters = [];
47
48
    /**
49
     * The method to call on each pipe.
50
     *
51
     * @var string
52
     */
53
    protected $method = 'handle';
54
55
    /**
56
     * Set the object being sent through the pipeline.
57
     *
58
     * @param  mixed  $passable
59
     * @return $this
60
     */
61
    public function send(...$passable) : self
62
    {
63
        $this->passable = $passable;
64
65
        return $this;
66
    }
67
68
    /**
69
     * Set the array of pipes.
70
     *
71
     * @param  array|mixed  $pipes
72
     * @return $this
73
     */
74
    public function through($pipes) : self
75
    {
76
        $this->pipes = is_array($pipes) ? $pipes : func_get_args();
77
78
        return $this;
79
    }
80
81
    /**
82
     * Set the method to call on the pipes.
83
     *
84
     * @param  string  $method
85
     * @return $this
86
     */
87
    public function via($method) : self
88
    {
89
        $this->method = $method;
90
91
        return $this;
92
    }
93
94
    /**
95
     * Set the additional parameters to send
96
     *
97
     * @param  mixed  $parameters
98
     * @return $this
99
     */
100
    public function with(...$parameters) : self
101
    {
102
        $this->parameters = $parameters;
103
104
        return $this;
105
    }
106
107
    /**
108
     * Run the pipeline with a final destination callback.
109
     *
110
     * @param  \Closure  $destination
111
     * @return mixed
112
     */
113
    public function then(Closure $destination)
114
    {
115
        $pipeline = array_reduce(
116
            array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination)
117
        );
118
119
        return call_user_func_array($pipeline, $this->passable);
120
    }
121
122
    /**
123
     * Get the final piece of the Closure onion.
124
     *
125
     * @param  \Closure  $destination
126
     * @return \Closure
127
     */
128
    protected function prepareDestination(Closure $destination) : Closure
129
    {
130
        return function() use ($destination) {
131
            return call_user_func_array($destination, func_get_args());
132
        };
133
    }
134
135
    /**
136
     * Get a Closure that represents a slice of the application onion.
137
     *
138
     * @return \Closure
139
     */
140
    protected function carry() : Closure
141
    {
142
        return function($stack, $pipe) {
143
            return function() use ($stack, $pipe) {
144
                $passable = func_get_args();
145
                $passable[] = $stack;
146
                $passable = array_merge($passable, $this->parameters);
147
148
                if (is_callable($pipe)) {
149
                    // If the pipe is an instance of a Closure, we will just call it directly but
150
                    // otherwise we'll resolve the pipes out of the container and call it with
151
                    // the appropriate method and arguments, returning the results back out.
152
                    return call_user_func_array($pipe, $passable);
153
                } elseif (!is_object($pipe)) {
154
                    list($name, $parameters) = $this->parsePipeString($pipe);
155
                    // If the pipe is a string we will parse the string and resolve the class out
156
                    // of the dependency injection container. We can then build a callable and
157
                    // execute the pipe function giving in the parameters that are required.
158
                    $pipe = new $name();
159
                    $parameters = array_merge($passable, $parameters);
160
                } else {
161
                    // If the pipe is already an object we'll just make a callable and pass it to
162
                    // the pipe as-is. There is no need to do any extra parsing and formatting
163
                    // since the object we're given was already a fully instantiated object.
164
                    $parameters = $passable;
165
                }
166
167
                return method_exists($pipe, $this->method)
168
                    ? call_user_func_array([$pipe, $this->method], $parameters)
169
                    : $pipe(...$parameters);
170
            };
171
        };
172
    }
173
174
    /**
175
     * Parse full pipe string to get name and parameters.
176
     *
177
     * @param  string $pipe
178
     * @return array
179
     */
180
    protected function parsePipeString(string $pipe) : array
181
    {
182
        list($name, $parameters) = array_pad(explode(':', $pipe, 2), 2, []);
183
184
        if (is_string($parameters)) {
185
            $parameters = explode(',', $parameters);
186
        }
187
188
        return [$name, $parameters];
189
    }
190
}