Completed
Push — master ( 2cec0d...b328c5 )
by Ruben
02:14
created

EndpointResource::mergeCollectionEndpoints()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Spatie\LaravelEndpointResources;
4
5
use Illuminate\Support\Arr;
6
use Spatie\LaravelEndpointResources\EndpointTypes\ActionEndpointType;
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
use Illuminate\Support\Collection;
12
use Spatie\LaravelEndpointResources\EndpointTypes\InvokableControllerEndpointType;
13
14
class EndpointResource extends JsonResource
15
{
16
    /** @var \Illuminate\Database\Eloquent\Model */
17
    protected $model;
18
19
    /** @var string */
20
    protected $endpointResourceType;
21
22
    /** @var \Illuminate\Support\Collection */
23
    protected $endPointTypes;
24
25
    public function __construct(Model $model = null, string $endpointResourceType = null)
26
    {
27
        parent::__construct($model);
28
29
        $this->model = $model;
30
        $this->endpointResourceType = $endpointResourceType ?? EndpointResourceType::ITEM;
31
        $this->endPointTypes = new Collection();
32
    }
33
34
    public function addController(string $controller, $parameters = null): JsonResource
35
    {
36
        if (method_exists($controller, '__invoke')) {
37
            return $this->addInvokableController($controller, $parameters);
38
        }
39
40
        $this->endPointTypes->push(new ControllerEndpointType(
41
            $controller,
42
            $this->resolveProvidedParameters($parameters)
43
        ));
44
45
        return $this;
46
    }
47
48
    public function addAction(array $action, $parameters = null, string $httpVerb = null): JsonResource
49
    {
50
        $this->endPointTypes->push(new ActionEndpointType(
51
            $action,
52
            $this->resolveProvidedParameters($parameters),
53
            $httpVerb
54
        ));
55
56
        return $this;
57
    }
58
59
    public function addInvokableController(string $controller, $parameters = null) : JsonResource
60
    {
61
        $this->endPointTypes->push(new InvokableControllerEndpointType(
62
            $controller,
63
            $this->resolveProvidedParameters($parameters)
64
        ));
65
66
        return $this;
67
    }
68
69
    public function mergeCollectionEndpoints(): JsonResource
70
    {
71
        $this->endpointResourceType = EndpointResourceType::MULTI;
72
73
        return $this;
74
    }
75
76
    public function toArray($request)
77
    {
78
        $this->ensureCollectionEndpointsAreAutomaticallyMerged();
79
80
        return $this->endPointTypes->mapWithKeys(function (EndPointType $endpointType) {
81
            if ($endpointType instanceof MultiEndpointType) {
82
                return $this->resolveEndpointsFromMultiEndpointType($endpointType);
83
            }
84
85
            return $endpointType->getEndpoints($this->model);
86
        });
87
    }
88
89
    protected function resolveProvidedParameters($parameters = null): array
90
    {
91
        $parameters = Arr::wrap($parameters);
92
93
        return count($parameters) === 0
94
            ? request()->route()->parameters()
95
            : $parameters;
96
    }
97
98
    protected function resolveEndpointsFromMultiEndpointType(MultiEndpointType $multiEndpointType): array
99
    {
100
        if ($this->endpointResourceType === EndpointResourceType::ITEM) {
101
            return $multiEndpointType->getEndpoints($this->model);
102
        }
103
104
        if ($this->endpointResourceType === EndpointResourceType::COLLECTION) {
105
            return $multiEndpointType->getCollectionEndpoints();
106
        }
107
108
        if ($this->endpointResourceType === EndpointResourceType::MULTI) {
109
            return array_merge(
110
                $multiEndpointType->getEndpoints($this->model),
111
                $multiEndpointType->getCollectionEndpoints()
112
            );
113
        }
114
115
        return [];
116
    }
117
118
    private function ensureCollectionEndpointsAreAutomaticallyMerged()
119
    {
120
        if (is_null($this->resource) || $this->resource->exists === false) {
121
            $this->mergeCollectionEndpoints();
122
        }
123
    }
124
}
125