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

resolveEndpointsFromControllerEndpointType()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.6333
c 0
b 0
f 0
cc 4
nc 4
nop 1
1
<?php
2
3
namespace Spatie\LaravelEndpointResources;
4
5
use Closure;
6
use Illuminate\Support\Arr;
7
use Spatie\LaravelEndpointResources\EndpointTypes\ControllerEndpointType;
8
use Spatie\LaravelEndpointResources\EndpointTypes\EndpointType;
9
use Illuminate\Database\Eloquent\Model;
10
use Illuminate\Http\Resources\Json\JsonResource;
11
12
class EndpointResource extends JsonResource
13
{
14
    /** @var string */
15
    private $endpointResourceType;
16
17
    /** @var \Spatie\LaravelEndpointResources\EndpointsGroup */
18
    private $endpointsGroup;
19
20
    public static function initialize(Model $model = null, string $endpointResourceType = null): EndpointResource
21
    {
22
        return new self($model, $endpointResourceType);
23
    }
24
25
    public function __construct(Model $model = null, string $endpointResourceType = null)
26
    {
27
        parent::__construct($model);
28
29
        $this->endpointResourceType = $endpointResourceType ?? EndpointResourceType::ITEM;
30
        $this->endpointsGroup = new EndpointsGroup();
31
    }
32
33
    public function endpoint($controller, $parameters = null, $httpVerb = null): EndpointResource
34
    {
35
        if ($controller instanceof Closure) {
36
            $endpointsGroup = new EndpointsGroup();
37
38
            $controller($endpointsGroup);
39
40
            return $this->addEndpointsGroup($endpointsGroup);
41
        }
42
43
        if (is_array($controller)) {
44
            return $this->addAction($controller, Arr::wrap($parameters), $httpVerb);
45
        }
46
47
        if (is_string($controller)) {
48
            return method_exists($controller, '__invoke')
49
                ? $this->addInvokableController($controller, Arr::wrap($parameters))
50
                : $this->addController($controller, Arr::wrap($parameters));
51
        }
52
53
        return $this;
54
    }
55
56
    public function mergeCollectionEndpoints(): EndpointResource
57
    {
58
        $this->endpointResourceType = EndpointResourceType::MULTI;
59
60
        return $this;
61
    }
62
63
    public function toArray($request)
64
    {
65
        $this->ensureCollectionEndpointsAreAutomaticallyMerged();
66
67
        return $this->endpointsGroup
68
            ->getEndpointTypes()
69
            ->map(function (EndpointType $endpointType) use ($request) {
70
                return $endpointType->hasParameters() === false
71
                    ? $endpointType->parameters($request->route()->parameters())
72
                    : $endpointType;
73
            })
74
            ->mapWithKeys(function (EndPointType $endpointType) {
75
                if ($endpointType instanceof ControllerEndpointType) {
76
                    return $this->resolveEndpointsFromControllerEndpointType($endpointType);
77
                }
78
79
                return $endpointType->getEndpoints($this->resource);
80
            });
81
    }
82
83
84
    private function addController(string $controller, $parameters = null): EndpointResource
85
    {
86
        $this->endpointsGroup->controller($controller)
87
            ->parameters(Arr::wrap($parameters));
88
89
        return $this;
90
    }
91
92
    private function addAction(array $action, $parameters = null, string $httpVerb = null): EndpointResource
93
    {
94
        $this->endpointsGroup->action($action)
95
            ->httpVerb($httpVerb)
96
            ->parameters(Arr::wrap($parameters));
97
98
        return $this;
99
    }
100
101
    private function addInvokableController(string $controller, $parameters = null): EndpointResource
102
    {
103
        $this->endpointsGroup->invokableController($controller)
104
            ->parameters(Arr::wrap($parameters));
105
106
        return $this;
107
    }
108
109
    private function addEndpointsGroup(EndpointsGroup $endpointsGroup): EndpointResource
110
    {
111
        $this->endpointsGroup->endpointsGroup($endpointsGroup);
112
113
        return $this;
114
    }
115
116
117
    private function resolveEndpointsFromControllerEndpointType(ControllerEndpointType $endpointType): array
118
    {
119
        if ($this->endpointResourceType === EndpointResourceType::ITEM) {
120
            return $endpointType->getEndpoints($this->resource);
121
        }
122
123
        if ($this->endpointResourceType === EndpointResourceType::COLLECTION) {
124
            return $endpointType->getCollectionEndpoints();
125
        }
126
127
        if ($this->endpointResourceType === EndpointResourceType::MULTI) {
128
            return array_merge(
129
                $endpointType->getEndpoints($this->resource),
130
                $endpointType->getCollectionEndpoints()
131
            );
132
        }
133
134
        return [];
135
    }
136
137
    private function ensureCollectionEndpointsAreAutomaticallyMerged()
138
    {
139
        if ($this->endpointResourceType !== EndpointResourceType::ITEM) {
140
            return;
141
        }
142
143
        if (config('laravel-endpoint-resources.automatically-merge-endpoints') === false) {
144
            return;
145
        }
146
147
        if (is_null($this->resource) || $this->resource->exists === false) {
148
            $this->mergeCollectionEndpoints();
149
        }
150
    }
151
}
152