1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Spatie\ResourceLinks\LinkTypes; |
4
|
|
|
|
5
|
|
|
use Exception; |
6
|
|
|
use Illuminate\Support\Arr; |
7
|
|
|
use Illuminate\Support\Str; |
8
|
|
|
use Illuminate\Routing\Route; |
9
|
|
|
use Illuminate\Routing\Router; |
10
|
|
|
use Illuminate\Support\Collection; |
11
|
|
|
use Illuminate\Database\Eloquent\Model; |
12
|
|
|
|
13
|
|
|
class ControllerLinkType extends LinkType |
14
|
|
|
{ |
15
|
|
|
/** @var string */ |
16
|
|
|
private $controller; |
17
|
|
|
|
18
|
|
|
/** @var array */ |
19
|
|
|
private $methods = []; |
20
|
|
|
|
21
|
|
|
/** @var array */ |
22
|
|
|
private static $cachedRoutes = []; |
23
|
|
|
|
24
|
|
|
/** @var array */ |
25
|
|
|
private $names = []; |
26
|
|
|
|
27
|
|
|
public static function make(string $controller): ControllerLinkType |
28
|
|
|
{ |
29
|
|
|
return new ControllerLinkType($controller); |
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
public function __construct(string $controller) |
33
|
|
|
{ |
34
|
|
|
$this->controller = $controller; |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
public function methods($methods): ControllerLinkType |
38
|
|
|
{ |
39
|
|
|
$this->methods = Arr::wrap($methods); |
40
|
|
|
|
41
|
|
|
return $this; |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
public function names(array $names): ControllerLinkType |
45
|
|
|
{ |
46
|
|
|
$this->names = $names; |
47
|
|
|
|
48
|
|
|
return $this; |
49
|
|
|
} |
50
|
|
|
|
51
|
|
View Code Duplication |
public function getLinks(Model $model = null): array |
|
|
|
|
52
|
|
|
{ |
53
|
|
|
$this->ensureUserDefinedMethodsExist(); |
54
|
|
|
|
55
|
|
|
$methodsToInclude = empty($this->methods) |
56
|
|
|
? ['show', 'edit', 'update', 'destroy'] |
57
|
|
|
: $this->methods; |
58
|
|
|
|
59
|
|
|
return $this->resolveLinks($methodsToInclude, $model); |
60
|
|
|
} |
61
|
|
|
|
62
|
|
View Code Duplication |
public function getCollectionLinks(): array |
|
|
|
|
63
|
|
|
{ |
64
|
|
|
$this->ensureUserDefinedMethodsExist(); |
65
|
|
|
|
66
|
|
|
$methodsToInclude = empty($this->methods) |
67
|
|
|
? ['index', 'store', 'create'] |
68
|
|
|
: $this->methods; |
69
|
|
|
|
70
|
|
|
return $this->resolveLinks($methodsToInclude); |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
public static function clearCache(): void |
74
|
|
|
{ |
75
|
|
|
self::$cachedRoutes = []; |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
private function resolveLinks(array $methodsToInclude, Model $model = null): array |
79
|
|
|
{ |
80
|
|
|
$links = self::getRoutesForController($this->controller) |
81
|
|
|
->filter(function (Route $route) use ($methodsToInclude) { |
82
|
|
|
return in_array($route->getActionMethod(), $methodsToInclude); |
83
|
|
|
}) |
84
|
|
|
->map(function (Route $route) use ($model) { |
85
|
|
|
$route = RouteLinkType::make($route) |
86
|
|
|
->parameters($this->parameters) |
87
|
|
|
->name($this->resolveNameForRoute($route)) |
88
|
|
|
->prefix($this->prefix) |
89
|
|
|
->query($this->query) |
90
|
|
|
->serializer($this->serializer) |
91
|
|
|
->getLinks($model); |
92
|
|
|
|
93
|
|
|
return $route; |
94
|
|
|
}) |
95
|
|
|
->toArray(); |
96
|
|
|
|
97
|
|
|
return ! empty($links) |
98
|
|
|
? array_merge_recursive(...$links) |
99
|
|
|
: []; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
private static function getRoutesForController(string $controller): Collection |
103
|
|
|
{ |
104
|
|
|
if (array_key_exists($controller, self::$cachedRoutes)) { |
105
|
|
|
return self::$cachedRoutes[$controller]; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
$routes = collect(resolve(Router::class)->getRoutes()->getRoutes()); |
109
|
|
|
|
110
|
|
|
self::$cachedRoutes[$controller] = $routes |
111
|
|
|
->filter(function (Route $route) use ($controller) { |
112
|
|
|
return $controller === Str::before($route->getActionName(), '@'); |
113
|
|
|
}); |
114
|
|
|
|
115
|
|
|
return self::$cachedRoutes[$controller]; |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
private function resolveNameForRoute(Route $route): string |
119
|
|
|
{ |
120
|
|
|
$method = $route->getActionMethod(); |
121
|
|
|
|
122
|
|
|
if (array_key_exists($method, $this->names)) { |
123
|
|
|
return $this->names[$method]; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
return $method; |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
private function ensureUserDefinedMethodsExist() |
130
|
|
|
{ |
131
|
|
|
foreach ($this->methods as $method) { |
132
|
|
|
if (! method_exists($this->controller, $method)) { |
133
|
|
|
throw new Exception("Resource links tried to check non-existing method {$method} on controller: {$this->controller}"); |
134
|
|
|
} |
135
|
|
|
} |
136
|
|
|
} |
137
|
|
|
} |
138
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.