PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 2.3.0
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v2.3.0
2.4.0 2.3.0 2.2.5 2.2.0 2.1.2 2.1.1 trunk 1.10.0 1.10.01 1.10.02 1.5.0 1.5.01 1.5.02 1.5.1 1.5.10 1.5.20 1.5.21 1.5.22 1.5.23 1.5.24 1.5.25 1.6.0 1.7.0 1.7.1 1.7.2 All 33 releases
fluent-booking / vendor / wpfluent / framework / src / WPFluent / Support / Pipeline.php

Pipeline.php in Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution 2.3.0, at vendor/wpfluent/framework/src/WPFluent/Support/Pipeline.php

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