Completed
Push — master ( ec71aa...2c64ed )
by Ruben
01:09
created

ControllerEndpointType::resolveEndpoints()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 9.6
c 0
b 0
f 0
cc 2
nc 2
nop 2
1
<?php
2
3
namespace Spatie\LaravelEndpointResources\EndpointTypes;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Routing\Route;
7
use Illuminate\Routing\Router;
8
use Illuminate\Support\Arr;
9
use Illuminate\Support\Collection;
10
use Illuminate\Support\Str;
11
12
class ControllerEndpointType extends EndpointType
13
{
14
    /** @var string */
15
    private $controller;
16
17
    /** @var array */
18
    private $methods = [];
19
20
    /** @var array */
21
    private static $cachedRoutes = [];
22
23
    /** @var array */
24
    private $names = [];
25
26
    public static function make(string $controller): ControllerEndpointType
27
    {
28
        return new self($controller);
29
    }
30
31
    public function __construct(string $controller)
32
    {
33
        $this->controller = $controller;
34
    }
35
36
    public function methods($methods): ControllerEndpointType
37
    {
38
        $this->methods = Arr::wrap($methods);
39
40
        return $this;
41
    }
42
43
    public function names(array $names): ControllerEndpointType
44
    {
45
        $this->names = $names;
46
47
        return $this;
48
    }
49
50
    public function getEndpoints(Model $model = null): array
51
    {
52
        $methodsToInclude = empty($this->methods)
53
            ? ['show', 'edit', 'update', 'destroy']
54
            : $this->methods;
55
56
        return $this->resolveEndpoints($methodsToInclude, $model);
57
    }
58
59
    public function getCollectionEndpoints(): array
60
    {
61
        $methodsToInclude = empty($this->methods)
62
            ? ['index', 'store', 'create']
63
            : $this->methods;
64
65
        return $this->resolveEndpoints($methodsToInclude);
66
    }
67
68
    private function resolveEndpoints(array $methodsToInclude, Model $model = null): array
69
    {
70
        $endpoints = self::getRoutesForController($this->controller)
71
            ->filter(function (Route $route) use ($methodsToInclude) {
72
                return in_array($route->getActionMethod(), $methodsToInclude);
73
            })->map(function (Route $route) use ($model) {
74
                $route = RouteEndpointType::make($route)
75
                    ->parameters($this->parameters)
76
                    ->name($this->resolveNameForRoute($route))
77
                    ->prefix($this->prefix)
78
                    ->formatter($this->formatter)
79
                    ->getEndpoints($model);
80
81
                return $route;
82
            })->toArray();
83
84
        return ! empty($endpoints)
85
            ? array_merge_recursive(...$endpoints)
86
            : [];
87
    }
88
89
    private static function getRoutesForController(string $controller): Collection
90
    {
91
        if (in_array($controller, self::$cachedRoutes)) {
92
            return self::$cachedRoutes[$controller];
93
        }
94
95
        $routes = collect(resolve(Router::class)->getRoutes()->getRoutes());
96
97
        self::$cachedRoutes[$controller] = $routes
98
            ->filter(function (Route $route) use ($controller) {
99
                return $controller === Str::before($route->getActionName(), '@');
100
            });
101
102
        return self::$cachedRoutes[$controller];
103
    }
104
105
    private function resolveNameForRoute(Route $route): string
106
    {
107
        $method = $route->getActionMethod();
108
109
        if (array_key_exists($method, $this->names)) {
110
            return $this->names[$method];
111
        }
112
113
        return $method;
114
    }
115
}
116