-
Notifications
You must be signed in to change notification settings - Fork 81
/
RouteAction.php
111 lines (99 loc) · 3.38 KB
/
RouteAction.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<?php
namespace Illuminate\Routing;
use Illuminate\Support\Arr;
use Illuminate\Support\Reflector;
use Illuminate\Support\Str;
use LogicException;
use UnexpectedValueException;
class RouteAction
{
/**
* Parse the given action into an array.
*
* @param string $uri
* @param mixed $action
* @return array
*/
public static function parse($uri, $action)
{
// If no action is passed in right away, we assume the user will make use of
// fluent routing. In that case, we set a default closure, to be executed
// if the user never explicitly sets an action to handle the given uri.
if (is_null($action)) {
return static::missingAction($uri);
}
// If the action is already a Closure instance, we will just set that instance
// as the "uses" property, because there is nothing else we need to do when
// it is available. Otherwise we will need to find it in the action list.
if (Reflector::isCallable($action, true)) {
return ! is_array($action) ? ['uses' => $action] : [
'uses' => $action[0].'@'.$action[1],
'controller' => $action[0].'@'.$action[1],
];
}
// If no "uses" property has been set, we will dig through the array to find a
// Closure instance within this list. We will set the first Closure we come
// across into the "uses" property that will get fired off by this route.
elseif (! isset($action['uses'])) {
$action['uses'] = static::findCallable($action);
}
if (! static::containsSerializedClosure($action) && is_string($action['uses']) && ! str_contains($action['uses'], '@')) {
$action['uses'] = static::makeInvokable($action['uses']);
}
return $action;
}
/**
* Get an action for a route that has no action.
*
* @param string $uri
* @return array
*
* @throws \LogicException
*/
protected static function missingAction($uri)
{
return ['uses' => function () use ($uri) {
throw new LogicException("Route for [{$uri}] has no action.");
}];
}
/**
* Find the callable in an action array.
*
* @param array $action
* @return callable
*/
protected static function findCallable(array $action)
{
return Arr::first($action, function ($value, $key) {
return Reflector::isCallable($value) && is_numeric($key);
});
}
/**
* Make an action for an invokable controller.
*
* @param string $action
* @return string
*
* @throws \UnexpectedValueException
*/
protected static function makeInvokable($action)
{
if (! method_exists($action, '__invoke')) {
throw new UnexpectedValueException("Invalid route action: [{$action}].");
}
return $action.'@__invoke';
}
/**
* Determine if the given array actions contain a serialized Closure.
*
* @param array $action
* @return bool
*/
public static function containsSerializedClosure(array $action)
{
return is_string($action['uses']) && Str::startsWith($action['uses'], [
'O:47:"Laravel\\SerializableClosure\\SerializableClosure',
'O:55:"Laravel\\SerializableClosure\\UnsignedSerializableClosure',
]) !== false;
}
}