1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* |
4
|
|
|
*/ |
5
|
|
|
|
6
|
|
|
namespace Mvc5\Resolver; |
7
|
|
|
|
8
|
|
|
use Closure; |
9
|
|
|
use Mvc5\Arg; |
10
|
|
|
use Mvc5\Event\Event; |
11
|
|
|
use Mvc5\Plugin\Gem\Args; |
12
|
|
|
use Mvc5\Plugin\Gem\Call; |
13
|
|
|
use Mvc5\Plugin\Gem\Calls; |
14
|
|
|
use Mvc5\Plugin\Gem\Child; |
15
|
|
|
use Mvc5\Plugin\Gem\Config; |
16
|
|
|
use Mvc5\Plugin\Gem\Copy; |
17
|
|
|
use Mvc5\Plugin\Gem\Factory; |
18
|
|
|
use Mvc5\Plugin\Gem\FileInclude; |
19
|
|
|
use Mvc5\Plugin\Gem\Filter; |
20
|
|
|
use Mvc5\Plugin\Gem\Gem; |
21
|
|
|
use Mvc5\Plugin\Gem\Invokable; |
22
|
|
|
use Mvc5\Plugin\Gem\Invoke; |
23
|
|
|
use Mvc5\Plugin\Gem\Link; |
24
|
|
|
use Mvc5\Plugin\Gem\Param; |
25
|
|
|
use Mvc5\Plugin\Gem\Plug; |
26
|
|
|
use Mvc5\Plugin\Gem\Plugin; |
27
|
|
|
use Mvc5\Plugin\Gem\Provide; |
28
|
|
|
use Mvc5\Plugin\Gem\Scoped; |
29
|
|
|
use Mvc5\Plugin\Gem\Shared; |
30
|
|
|
use Mvc5\Plugin\Gem\SignalArgs; |
31
|
|
|
use Mvc5\Plugin\Gem\Value; |
32
|
|
|
use Mvc5\Resolvable; |
33
|
|
|
use Mvc5\Service\Config\Container; |
34
|
|
|
|
35
|
|
|
trait Resolver |
36
|
|
|
{ |
37
|
|
|
/** |
38
|
|
|
* |
39
|
|
|
*/ |
40
|
|
|
use Build; |
41
|
|
|
use Container; |
42
|
|
|
use Generator; |
43
|
|
|
use Initializer; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @var callable |
47
|
|
|
*/ |
48
|
|
|
protected $provider; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @var object |
52
|
|
|
*/ |
53
|
|
|
protected $scope; |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* @var bool |
57
|
|
|
*/ |
58
|
|
|
protected $strict = false; |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* @param array|\ArrayAccess $config |
62
|
|
|
* @param callable $provider |
63
|
|
|
* @param object $scope |
64
|
|
|
* @param bool $strict |
65
|
283 |
|
*/ |
66
|
|
|
function __construct($config = null, callable $provider = null, $scope = null, $strict = false) |
|
|
|
|
67
|
283 |
|
{ |
68
|
|
|
$config && $this->config = $config; |
|
|
|
|
69
|
283 |
|
|
70
|
3 |
|
isset($config[Arg::CONTAINER]) |
71
|
|
|
&& $this->container = $config[Arg::CONTAINER]; |
72
|
283 |
|
|
73
|
32 |
|
isset($config[Arg::EVENTS]) |
74
|
|
|
&& $this->events = $config[Arg::EVENTS]; |
75
|
283 |
|
|
76
|
74 |
|
isset($config[Arg::SERVICES]) |
77
|
|
|
&& $this->services = $config[Arg::SERVICES]; |
78
|
283 |
|
|
79
|
|
|
$provider && $this->provider = $this->resolve($provider); |
|
|
|
|
80
|
283 |
|
|
81
|
|
|
$scope && $this->scope = $this->resolve($scope); |
|
|
|
|
82
|
283 |
|
|
83
|
283 |
|
$strict && $this->strict = $strict; |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* @param $args |
88
|
|
|
* @return array|callable|null|object|string |
89
|
60 |
|
*/ |
90
|
|
|
protected function args($args) |
91
|
60 |
|
{ |
92
|
33 |
|
if (!$args) { |
93
|
|
|
return $args; |
94
|
|
|
} |
95
|
41 |
|
|
96
|
2 |
|
if (!is_array($args)) { |
97
|
|
|
return $this->resolve($args); |
98
|
|
|
} |
99
|
39 |
|
|
100
|
39 |
|
foreach($args as $index => $value) { |
101
|
|
|
$value instanceof Resolvable && $args[$index] = $this->resolve($value); |
102
|
|
|
} |
103
|
39 |
|
|
104
|
|
|
return $args; |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @param array $child |
109
|
|
|
* @param array $parent |
110
|
|
|
* @return array |
111
|
28 |
|
*/ |
112
|
|
|
protected function arguments(array $child, array $parent) |
113
|
28 |
|
{ |
114
|
28 |
|
return !$parent ? $child : ( |
115
|
|
|
!$child ? $parent : (is_string(key($child)) ? $child + $parent : array_merge($child, $parent)) |
116
|
|
|
); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* @param Closure $callback |
121
|
|
|
* @param $scope |
122
|
|
|
* @return Closure |
123
|
5 |
|
*/ |
124
|
|
|
protected function bind(Closure $callback, $scope) |
125
|
5 |
|
{ |
126
|
|
|
return Closure::bind($callback, $scope, $scope); |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* @param array|callable|object|string $config |
131
|
|
|
* @param array $args |
132
|
|
|
* @param callable $callback |
133
|
|
|
* @return callable|mixed|null|object |
134
|
64 |
|
*/ |
135
|
|
|
function call($config, array $args = [], callable $callback = null) |
|
|
|
|
136
|
64 |
|
{ |
137
|
46 |
|
if (is_string($config)) { |
138
|
|
|
return $this->transmit(explode(Arg::CALL_SEPARATOR, $config), $args, $callback); |
139
|
|
|
} |
140
|
21 |
|
|
141
|
1 |
|
if ($config instanceof Event) { |
142
|
|
|
return $this->event($config, $args, $callback); |
143
|
|
|
} |
144
|
20 |
|
|
145
|
|
|
return $this->invoke($config instanceof Resolvable ? $this->resolve($config) : $config, $args, $callback); |
|
|
|
|
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* @param array|callable|object|string $config |
150
|
|
|
* @return callable|null |
151
|
|
|
*/ |
152
|
|
|
protected function callable($config) : callable |
153
|
53 |
|
{ |
154
|
|
|
if (is_string($config)) { |
155
|
21 |
|
return function(...$args) use($config) { |
156
|
22 |
|
return $this->call($config, $this->variadic($args)); |
157
|
|
|
}; |
158
|
|
|
} |
159
|
35 |
|
|
160
|
3 |
|
if (is_array($config)) { |
161
|
|
|
return is_string($config[0]) ? $config : [$this->resolve($config[0]), $config[1]]; |
162
|
|
|
} |
163
|
32 |
|
|
164
|
|
|
return $config instanceof Closure ? $config : $this->listener($this->resolve($config)); |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* @param Child $config |
169
|
|
|
* @param array $args |
170
|
|
|
* @return array|callable|object|string |
171
|
3 |
|
*/ |
172
|
|
|
protected function child(Child $config, array $args = []) |
173
|
3 |
|
{ |
174
|
|
|
return $this->provide($this->merge(clone $this->parent($config->parent()), $config), $args); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* @param $name |
179
|
|
|
* @return callable|mixed|object |
180
|
7 |
|
*/ |
181
|
|
|
protected function fallback($name) |
182
|
7 |
|
{ |
183
|
|
|
return $this(Arg::EVENT_MODEL, [Arg::EVENT => $name]) ?: Unresolvable::plugin($name); |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* @param array|callable|null|object|string $value |
188
|
|
|
* @param array|\Traversable $filters |
189
|
|
|
* @param array $args |
190
|
|
|
* @param $param |
191
|
|
|
* @return mixed |
192
|
10 |
|
*/ |
193
|
|
|
protected function filter($value, $filters = [], array $args = [], $param = null) |
194
|
10 |
|
{ |
195
|
|
|
$result = $value; |
196
|
10 |
|
|
197
|
9 |
|
foreach($filters as $filter) { |
198
|
9 |
|
$value = $this->invoke( |
199
|
|
|
$this->callable($filter), $param ? [$param => $result] + $args : array_merge([$result], $args) |
|
|
|
|
200
|
|
|
); |
201
|
9 |
|
|
202
|
1 |
|
if (false === $value) { |
203
|
|
|
return $result; |
204
|
|
|
} |
205
|
9 |
|
|
206
|
1 |
|
if (null === $value) { |
207
|
|
|
return null; |
208
|
|
|
} |
209
|
9 |
|
|
210
|
|
|
$result = $value; |
211
|
|
|
} |
212
|
8 |
|
|
213
|
|
|
return $result; |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
/** |
217
|
|
|
* @param Filter $config |
218
|
|
|
* @param array $args |
219
|
|
|
* @return mixed |
220
|
9 |
|
*/ |
221
|
|
|
protected function filterable(Filter $config, array $args = []) |
222
|
9 |
|
{ |
223
|
9 |
|
return $this->filter( |
224
|
|
|
$this->resolve($config->config()), $this->resolve($config->filter()), $args, $config->param() |
|
|
|
|
225
|
|
|
); |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
/** |
229
|
|
|
* @param $config |
230
|
|
|
* @param array $args |
231
|
|
|
* @return mixed|callable |
232
|
64 |
|
*/ |
233
|
|
|
protected function gem($config, array $args = []) |
234
|
64 |
|
{ |
235
|
1 |
|
if ($config instanceof Factory) { |
236
|
|
|
return $this->invoke($this->child($config, $args)); |
|
|
|
|
237
|
|
|
} |
238
|
63 |
|
|
239
|
1 |
|
if ($config instanceof Calls) { |
240
|
|
|
return $this->hydrate($config, $this->resolve($config->name(), $args)); |
|
|
|
|
241
|
|
|
} |
242
|
63 |
|
|
243
|
1 |
|
if ($config instanceof Child) { |
244
|
|
|
return $this->child($config, $args); |
245
|
|
|
} |
246
|
62 |
|
|
247
|
25 |
|
if ($config instanceof Plugin) { |
248
|
|
|
return $this->provide($config, $args); |
249
|
|
|
} |
250
|
53 |
|
|
251
|
5 |
|
if ($config instanceof Shared) { |
252
|
|
|
return $this->shared($config->name(), $config->config()); |
253
|
|
|
} |
254
|
51 |
|
|
255
|
3 |
|
if ($config instanceof Param) { |
256
|
|
|
return $this->resolve($this->param($config->name()), $args); |
257
|
|
|
} |
258
|
50 |
|
|
259
|
9 |
|
if ($config instanceof Call) { |
260
|
|
|
return $this->call($this->resolve($config->config()), $this->vars($args, $config->args())); |
|
|
|
|
261
|
|
|
} |
262
|
47 |
|
|
263
|
12 |
|
if ($config instanceof Args) { |
264
|
|
|
return $this->args($config->config()); |
265
|
|
|
} |
266
|
41 |
|
|
267
|
2 |
|
if ($config instanceof Config) { |
268
|
|
|
return $this->config(); |
269
|
|
|
} |
270
|
39 |
|
|
271
|
6 |
|
if ($config instanceof Link) { |
272
|
|
|
return $this; |
273
|
|
|
} |
274
|
34 |
|
|
275
|
8 |
|
if ($config instanceof Filter) { |
276
|
|
|
return $this->filterable($config, $this->vars($args, $config->args())); |
277
|
|
|
} |
278
|
26 |
|
|
279
|
3 |
|
if ($config instanceof Plug) { |
280
|
|
|
return $this->configured($config->name()); |
281
|
|
|
} |
282
|
24 |
|
|
283
|
|
|
if ($config instanceof Invoke) { |
284
|
8 |
|
return function(...$args) use ($config) { |
285
|
8 |
|
return $this->call( |
286
|
|
|
$this->resolve($config->config()), $this->vars($this->variadic($args), $config->args()) |
|
|
|
|
287
|
8 |
|
); |
288
|
|
|
}; |
289
|
|
|
} |
290
|
19 |
|
|
291
|
|
|
if ($config instanceof Invokable) { |
292
|
3 |
|
return function(...$args) use ($config) { |
293
|
3 |
|
return $this->resolve($config->config(), $this->vars($this->variadic($args), $config->args())); |
294
|
|
|
}; |
295
|
|
|
} |
296
|
16 |
|
|
297
|
|
|
if ($config instanceof FileInclude) { |
298
|
1 |
|
$include = new class() { |
299
|
1 |
|
function __invoke($file) { |
|
|
|
|
300
|
|
|
return include $file; |
301
|
|
|
} |
302
|
|
|
}; |
303
|
1 |
|
|
304
|
|
|
return $include($this->resolve($config->config())); |
305
|
|
|
} |
306
|
15 |
|
|
307
|
1 |
|
if ($config instanceof Copy) { |
308
|
|
|
return clone $this->resolve($config->config(), $args); |
309
|
|
|
} |
310
|
14 |
|
|
311
|
10 |
|
if ($config instanceof Value) { |
312
|
|
|
return $config->config(); |
313
|
|
|
} |
314
|
4 |
|
|
315
|
3 |
|
if ($config instanceof Scoped) { |
316
|
|
|
return $this->scoped($config->closure()); |
317
|
|
|
} |
318
|
1 |
|
|
319
|
|
|
if ($config instanceof Provide) { |
320
|
|
|
return ($this->provider() ?: new Unresolvable)($config->config(), $this->vars($args, $config->args())); |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
return Unresolvable::plugin($config); |
324
|
|
|
} |
325
|
20 |
|
|
326
|
|
|
/** |
327
|
20 |
|
* @param string $name |
328
|
|
|
* @return mixed |
329
|
|
|
*/ |
330
|
|
|
function get($name) |
331
|
|
|
{ |
332
|
|
|
return $this->stored($name) ?? $this($name); |
333
|
|
|
} |
334
|
|
|
|
335
|
37 |
|
/** |
336
|
|
|
* @param Plugin $config |
337
|
37 |
|
* @param object $service |
338
|
11 |
|
* @return object |
339
|
6 |
|
*/ |
340
|
2 |
|
protected function hydrate(Plugin $config, $service) |
341
|
2 |
|
{ |
342
|
|
|
foreach($config->calls() as $method => $args) { |
343
|
|
|
if (is_string($method)) { |
344
|
4 |
|
if (Arg::INDEX == $method[0]) { |
345
|
2 |
|
$service[substr($method, 1)] = $this->resolve($args); |
346
|
2 |
|
continue; |
347
|
|
|
} |
348
|
|
|
|
349
|
2 |
|
if (Arg::PROPERTY == $method[0]) { |
350
|
2 |
|
$service->{substr($method, 1)} = $this->resolve($args); |
351
|
|
|
continue; |
352
|
|
|
} |
353
|
5 |
|
|
354
|
4 |
|
$service->$method($this->resolve($args)); |
355
|
4 |
|
continue; |
356
|
|
|
} |
357
|
4 |
|
|
358
|
2 |
|
if (is_array($args)) { |
359
|
2 |
|
$method = array_shift($args); |
360
|
|
|
$param = $config->param(); |
361
|
|
|
|
362
|
4 |
|
if (is_string($method) && Arg::PROPERTY == $method[0]) { |
363
|
4 |
|
$param = substr($method, 1); |
364
|
4 |
|
$method = array_shift($args); |
365
|
|
|
} |
366
|
|
|
|
367
|
4 |
|
$this->invoke( |
368
|
|
|
is_string($method) ? [$service, $method] : $this->callable($method), |
|
|
|
|
369
|
|
|
($param && (!$args || is_string(key($args))) ? [$param => $service] : []) + $this->args($args) |
|
|
|
|
370
|
1 |
|
); |
371
|
|
|
|
372
|
|
|
continue; |
373
|
37 |
|
} |
374
|
|
|
|
375
|
|
|
$this->resolve($args); |
376
|
|
|
} |
377
|
|
|
|
378
|
|
|
return $service; |
379
|
|
|
} |
380
|
53 |
|
|
381
|
|
|
/** |
382
|
53 |
|
* @param array|callable|object|string $name |
383
|
53 |
|
* @return callable|null |
384
|
|
|
*/ |
385
|
|
|
protected function invokable($name) |
386
|
|
|
{ |
387
|
|
|
return Arg::CALL === $name[0] ? substr($name, 1) : |
388
|
|
|
$this->listener($this->plugin($name, [], $this) ?: $this->fallback($name)); |
|
|
|
|
389
|
|
|
} |
390
|
|
|
|
391
|
|
|
/** |
392
|
85 |
|
* @param array|callable|object|string $config |
393
|
|
|
* @param array $args |
394
|
85 |
|
* @param callable $callback |
395
|
|
|
* @return array|callable|object|string |
396
|
|
|
*/ |
397
|
|
|
protected function invoke($config, array $args = [], callable $callback = null) |
398
|
|
|
{ |
399
|
|
|
return $this->signal($config, $args, $callback ?? $this); |
400
|
|
|
} |
401
|
52 |
|
|
402
|
|
|
/** |
403
|
|
|
* @param $plugin |
404
|
26 |
|
* @return callable|null |
405
|
52 |
|
*/ |
406
|
|
|
protected function listener($plugin) |
407
|
|
|
{ |
408
|
|
|
return !$plugin instanceof Event ? $plugin : function(...$args) use ($plugin) { |
409
|
|
|
return $this->event($plugin, $this->variadic($args)); |
410
|
|
|
}; |
411
|
|
|
} |
412
|
|
|
|
413
|
|
|
/** |
414
|
11 |
|
* @param Plugin $parent |
415
|
|
|
* @param Plugin $config |
416
|
11 |
|
* @param null|string $name |
417
|
3 |
|
* @return Plugin |
418
|
|
|
*/ |
419
|
11 |
|
protected function merge(Plugin $parent, Plugin $config, $name = null) |
420
|
5 |
|
{ |
421
|
|
|
!$parent->name() && |
422
|
11 |
|
$parent[Arg::NAME] = $name ?? $this->resolve($config->name()); |
423
|
2 |
|
|
424
|
|
|
$config->args() && |
425
|
11 |
|
$parent[Arg::ARGS] = is_string(key($config->args())) ? $config->args() + $parent->args() : $config->args(); |
426
|
8 |
|
|
427
|
|
|
$config->calls() && |
428
|
11 |
|
$parent[Arg::CALLS] = $config->merge() ? array_merge($parent->calls(), $config->calls()) : $config->calls(); |
429
|
|
|
|
430
|
|
|
$config->param() && |
431
|
|
|
$parent[Arg::PARAM] = $config->param(); |
432
|
|
|
|
433
|
|
|
return $parent; |
434
|
|
|
} |
435
|
5 |
|
|
436
|
|
|
/** |
437
|
5 |
|
* @param string $name |
438
|
5 |
|
* @return mixed |
439
|
|
|
*/ |
440
|
5 |
|
function param($name) |
441
|
1 |
|
{ |
442
|
|
|
$name = explode(Arg::CALL_SEPARATOR, $name); |
443
|
|
|
$value = $this->config()[array_shift($name)]; |
444
|
5 |
|
|
445
|
|
|
foreach($name as $n) { |
446
|
|
|
$value = $value[$n]; |
447
|
|
|
} |
448
|
|
|
|
449
|
|
|
return $value; |
450
|
|
|
} |
451
|
4 |
|
|
452
|
|
|
/** |
453
|
4 |
|
* @param $config |
454
|
|
|
* @return array|callable|Plugin|null|object|string |
455
|
|
|
*/ |
456
|
|
|
protected function parent($config) |
457
|
|
|
{ |
458
|
|
|
return $this->configured($this->resolve($config)); |
|
|
|
|
459
|
|
|
} |
460
|
|
|
|
461
|
|
|
/** |
462
|
|
|
* @param string $config |
463
|
128 |
|
* @param array $args |
464
|
|
|
* @param callable|null $callback |
465
|
128 |
|
* @param null|string $previous |
466
|
1 |
|
* @return array|callable|null|object|string |
467
|
|
|
*/ |
468
|
|
|
function plugin($config, array $args = [], callable $callback = null, $previous = null) |
469
|
127 |
|
{ |
470
|
115 |
|
if (!$config) { |
471
|
|
|
return $config; |
472
|
|
|
} |
473
|
50 |
|
|
474
|
6 |
|
if (is_string($config)) { |
475
|
|
|
return $this->build(explode(Arg::SERVICE_SEPARATOR, $config), $args, $callback); |
476
|
|
|
} |
477
|
46 |
|
|
478
|
18 |
|
if (is_array($config)) { |
479
|
|
|
return $this->pluginArray(array_shift($config), $args + $this->args($config), $callback, $previous); |
|
|
|
|
480
|
|
|
} |
481
|
32 |
|
|
482
|
|
|
if ($config instanceof Closure) { |
483
|
|
|
return $this->invoke($this->scoped($config), $args); |
484
|
|
|
} |
485
|
|
|
|
486
|
|
|
return $this->resolve($config, $args); |
487
|
|
|
} |
488
|
|
|
|
489
|
|
|
/** |
490
|
|
|
* @param $config |
491
|
7 |
|
* @param array $args |
492
|
|
|
* @param callable|null $callback |
493
|
7 |
|
* @param null $previous |
494
|
7 |
|
* @return array|callable|null|object|string |
495
|
|
|
*/ |
496
|
|
|
protected function pluginArray($config, array $args = [], callable $callback = null, $previous = null) |
497
|
|
|
{ |
498
|
|
|
return $previous && $previous === $config ? |
499
|
|
|
$this->callback($config, true, $args, $callback) : $this->plugin($config, $args, $callback); |
500
|
|
|
} |
501
|
|
|
|
502
|
28 |
|
/** |
503
|
|
|
* @param Plugin $config |
504
|
28 |
|
* @param array $args |
505
|
28 |
|
* @return callable|null|object |
506
|
|
|
*/ |
507
|
28 |
|
protected function provide(Plugin $config, array $args = []) |
508
|
|
|
{ |
509
|
28 |
|
$name = $this->resolve($config->name()); |
510
|
|
|
$parent = $this->configured($name); |
|
|
|
|
511
|
28 |
|
|
512
|
25 |
|
$args && is_string(key($args)) && $config->args() && $args += $this->args($config->args()); |
|
|
|
|
513
|
|
|
|
514
|
|
|
!$args && $args = $this->args($config->args()); |
515
|
5 |
|
|
516
|
3 |
|
if (!$parent) { |
517
|
3 |
|
return $this->hydrate($config, $this->combine(explode(Arg::SERVICE_SEPARATOR, $name), $args)); |
|
|
|
|
518
|
|
|
} |
519
|
|
|
|
520
|
|
|
if (!$parent instanceof Plugin) { |
521
|
2 |
|
return $this->hydrate( |
522
|
1 |
|
$config, $name === $parent ? $this->make($name, $args) : $this->plugin($this->resolve($parent), $args) |
|
|
|
|
523
|
|
|
); |
524
|
|
|
} |
525
|
1 |
|
|
526
|
|
|
if ($name == $parent->name()) { |
527
|
|
|
return $this->hydrate($config, $this->make($name, $args)); |
|
|
|
|
528
|
|
|
} |
529
|
|
|
|
530
|
|
|
return $this->provide($this->merge(clone $parent, $config, $name), $args); |
|
|
|
|
531
|
46 |
|
} |
532
|
|
|
|
533
|
46 |
|
/** |
534
|
|
|
* @return callable |
535
|
|
|
*/ |
536
|
|
|
protected function provider() |
537
|
|
|
{ |
538
|
|
|
return $this->provider; |
539
|
|
|
} |
540
|
|
|
|
541
|
|
|
/** |
542
|
|
|
* @param $plugin |
543
|
48 |
|
* @param array $config |
544
|
|
|
* @param array $args |
545
|
48 |
|
* @param callable|null $callback |
546
|
47 |
|
* @return array|callable|object|string |
547
|
|
|
*/ |
548
|
|
|
protected function relay($plugin, array $config = [], array $args = [], callable $callback = null) |
549
|
|
|
{ |
550
|
|
|
return !$config ? $this->invoke($plugin, $args, $callback) : |
551
|
|
|
$this->repeat($plugin, array_shift($config), $config, $args, $callback); |
552
|
|
|
} |
553
|
|
|
|
554
|
|
|
/** |
555
|
|
|
* @param $plugin |
556
|
|
|
* @param $name |
557
|
3 |
|
* @param array $config |
558
|
|
|
* @param array $args |
559
|
3 |
|
* @param callable|null $callback |
560
|
3 |
|
* @return array|callable|object|string |
561
|
|
|
*/ |
562
|
|
|
protected function repeat($plugin, $name, array $config = [], array $args = [], callable $callback = null) |
563
|
|
|
{ |
564
|
|
|
return !$config ? $this->invoke([$plugin, $name], $args, $callback) : $this->repeat( |
565
|
|
|
$this->invoke([$plugin, $name], $args, $callback), array_shift($config), $config, $args, $callback |
566
|
|
|
); |
567
|
|
|
} |
568
|
|
|
|
569
|
|
|
/** |
570
|
|
|
* @param $config |
571
|
123 |
|
* @param array $args |
572
|
|
|
* @param callable $callback |
573
|
123 |
|
* @param int $c |
574
|
42 |
|
* @return array|callable|Plugin|null|object|Resolvable|string |
575
|
123 |
|
*/ |
576
|
|
|
protected function resolvable($config, array $args = [], callable $callback = null, $c = 0) |
577
|
|
|
{ |
578
|
|
|
return !$config instanceof Resolvable ? $config : ( |
579
|
|
|
$c > Arg::MAX_RECURSION ? Unresolvable::plugin($config) : |
580
|
|
|
$this->resolvable($this->solve($config, $args, $callback), $args, $callback, ++$c) |
581
|
|
|
); |
582
|
|
|
} |
583
|
|
|
|
584
|
122 |
|
/** |
585
|
|
|
* @param $config |
586
|
122 |
|
* @param array $args |
587
|
|
|
* @return array|callable|Plugin|null|object|Resolvable|string |
588
|
|
|
*/ |
589
|
|
|
protected function resolve($config, array $args = []) |
590
|
|
|
{ |
591
|
|
|
return $this->resolvable($config, $args); |
592
|
|
|
} |
593
|
|
|
|
594
|
4 |
|
/** |
595
|
|
|
* @param $config |
596
|
4 |
|
* @param array $args |
597
|
|
|
* @return callable|mixed|null|object |
598
|
|
|
*/ |
599
|
|
|
protected function resolver($config, array $args = []) |
600
|
|
|
{ |
601
|
|
|
return $this->call($this->provider() ?: Arg::SERVICE_RESOLVER, [$config, $args]); |
602
|
|
|
} |
603
|
|
|
|
604
|
|
|
/** |
605
|
45 |
|
* @param $config |
606
|
|
|
* @param array $args |
607
|
45 |
|
* @param callable $callback |
608
|
45 |
|
* @return mixed|callable |
609
|
|
|
*/ |
610
|
|
|
protected function solve($config, array $args = [], callable $callback = null) |
611
|
|
|
{ |
612
|
|
|
return $config instanceof Gem ? $this->gem($config, $args) : ( |
613
|
|
|
$callback ? $callback($config, $args) : $this->resolver($config, $args) |
614
|
|
|
); |
615
|
|
|
} |
616
|
13 |
|
|
617
|
|
|
/** |
618
|
13 |
|
* @param object $scope |
619
|
|
|
* @return object |
620
|
|
|
*/ |
621
|
|
|
function scope($scope = null) |
622
|
|
|
{ |
623
|
|
|
return null !== $scope ? $this->scope = $scope : $this->scope; |
624
|
|
|
} |
625
|
21 |
|
|
626
|
|
|
/** |
627
|
21 |
|
* @param Closure $callback |
628
|
|
|
* @return Closure |
629
|
|
|
*/ |
630
|
|
|
protected function scoped(Closure $callback) |
631
|
|
|
{ |
632
|
|
|
return $this->scope ? $this->bind($callback, $this->scope === true ? $this : $this->scope) : $callback; |
633
|
|
|
} |
634
|
|
|
|
635
|
8 |
|
/** |
636
|
|
|
* @return string |
637
|
8 |
|
*/ |
638
|
|
|
function serialize() |
639
|
|
|
{ |
640
|
|
|
return serialize([$this->config, $this->events, $this->provider, $this->scope, $this->services, $this->strict]); |
641
|
|
|
} |
642
|
|
|
|
643
|
100 |
|
/** |
644
|
|
|
* @param $name |
645
|
100 |
|
* @param null $config |
646
|
|
|
* @return callable|mixed|null|object |
647
|
|
|
*/ |
648
|
|
|
function shared($name, $config = null) |
649
|
|
|
{ |
650
|
|
|
return $this->stored($name) ?? $this->initialize($name, $config); |
651
|
|
|
} |
652
|
|
|
|
653
|
|
|
/** |
654
|
47 |
|
* @return bool |
655
|
|
|
*/ |
656
|
47 |
|
protected function strict() |
657
|
|
|
{ |
658
|
|
|
return $this->strict; |
659
|
|
|
} |
660
|
|
|
|
661
|
|
|
/** |
662
|
|
|
* @param array $config |
663
|
|
|
* @param array $args |
664
|
|
|
* @param callable|null $callback |
665
|
8 |
|
* @return array|callable|object|string |
666
|
|
|
*/ |
667
|
8 |
|
protected function transmit(array $config = [], array $args = [], callable $callback = null) |
668
|
|
|
{ |
669
|
|
|
return $this->relay($this->invokable(array_shift($config)), $config, $args, $callback); |
670
|
|
|
} |
671
|
|
|
|
672
|
|
|
/** |
673
|
|
|
* @param array|object|string|\Traversable $event |
674
|
40 |
|
* @param array $args |
675
|
|
|
* @param callable $callback |
676
|
40 |
|
* @return mixed|null |
677
|
|
|
*/ |
678
|
|
|
function trigger($event, array $args = [], callable $callback = null) |
679
|
|
|
{ |
680
|
|
|
return $this->event($event instanceof Event ? $event : $this($event) ?? $event, $args, $callback); |
681
|
|
|
} |
682
|
|
|
|
683
|
|
|
/** |
684
|
27 |
|
* @param string $serialized |
685
|
|
|
*/ |
686
|
27 |
|
function unserialize($serialized) |
687
|
|
|
{ |
688
|
|
|
list( |
689
|
|
|
$this->config, $this->events, $this->provider, $this->scope, $this->services, $this->strict |
690
|
|
|
) = unserialize($serialized); |
691
|
|
|
} |
692
|
12 |
|
|
693
|
|
|
/** |
694
|
12 |
|
* @param array $args |
695
|
2 |
|
* @return array |
696
|
|
|
*/ |
697
|
12 |
|
protected function variadic(array $args) |
698
|
2 |
|
{ |
699
|
|
|
return $args && $args[0] instanceof SignalArgs ? $args[0]->args() : $args; |
|
|
|
|
700
|
2 |
|
} |
701
|
1 |
|
|
702
|
|
|
/** |
703
|
|
|
* @param array $child |
704
|
|
|
* @param array $parent |
705
|
12 |
|
* @return array |
706
|
2 |
|
*/ |
707
|
|
|
protected function vars(array $child = [], array $parent = []) |
708
|
2 |
|
{ |
709
|
1 |
|
return $this->arguments($child, $this->args($parent)); |
|
|
|
|
710
|
|
|
} |
711
|
|
|
|
712
|
|
|
/** |
713
|
12 |
|
* |
714
|
2 |
|
*/ |
715
|
|
|
function __clone() |
716
|
2 |
|
{ |
717
|
1 |
|
is_object($this->config) && |
718
|
|
|
$this->config = clone $this->config; |
719
|
|
|
|
720
|
|
|
if (is_object($this->container)) { |
721
|
12 |
|
$this->container = clone $this->container; |
722
|
2 |
|
|
723
|
12 |
|
if (isset($this->config[Arg::CONTAINER])) { |
724
|
|
|
$this->config[Arg::CONTAINER] = $this->container; |
725
|
|
|
} |
726
|
|
|
} |
727
|
|
|
|
728
|
|
|
if (is_object($this->events)) { |
729
|
|
|
$this->events = clone $this->events; |
730
|
|
|
|
731
|
|
|
if (isset($this->config[Arg::EVENTS])) { |
732
|
|
|
$this->config[Arg::EVENTS] = $this->events; |
733
|
|
|
} |
734
|
|
|
} |
735
|
|
|
|
736
|
|
|
if (is_object($this->services)) { |
737
|
|
|
$this->services = clone $this->services; |
738
|
|
|
|
739
|
|
|
if (isset($this->config[Arg::SERVICES])) { |
740
|
|
|
$this->config[Arg::SERVICES] = $this->services; |
741
|
|
|
} |
742
|
|
|
} |
743
|
|
|
|
744
|
|
|
is_object($this->scope) && |
745
|
|
|
$this->scope = clone $this->scope; |
746
|
|
|
} |
747
|
|
|
|
748
|
|
|
/** |
749
|
|
|
* @param string $name |
750
|
|
|
* @param array $args |
751
|
|
|
* @return array|callable|null|object|string |
752
|
|
|
*/ |
753
|
|
|
function __invoke($name, array $args = []) |
754
|
|
|
{ |
755
|
|
|
return $this->plugin($name, $args, $this->provider() ?? function(){}); |
756
|
|
|
} |
757
|
|
|
} |
758
|
|
|
|
Adding explicit visibility (
private
,protected
, orpublic
) is generally recommend to communicate to other developers how, and from where this method is intended to be used.