Passed
Push — master ( 2d5c28...1adfda )
by
unknown
03:35
created

onPreDecodeRequestBody()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
4
namespace W2w\Laravel\Apie\Plugins\IlluminateDispatcher;
5
6
use Illuminate\Auth\AuthManager;
7
use Illuminate\Contracts\Auth\Access\Gate;
8
use Illuminate\Contracts\Events\Dispatcher;
9
use Illuminate\Validation\Factory;
10
use ReflectionClass;
11
use W2w\Laravel\Apie\Contracts\HasApieRulesContract;
12
use W2w\Lib\Apie\Events\DecodeEvent;
13
use W2w\Lib\Apie\Events\DeleteResourceEvent;
14
use W2w\Lib\Apie\Events\ModifySingleResourceEvent;
15
use W2w\Lib\Apie\Events\NormalizeEvent;
16
use W2w\Lib\Apie\Events\ResponseEvent;
17
use W2w\Lib\Apie\Events\RetrievePaginatedResourcesEvent;
18
use W2w\Lib\Apie\Events\RetrieveSingleResourceEvent;
19
use W2w\Lib\Apie\Events\StoreExistingResourceEvent;
20
use W2w\Lib\Apie\Events\StoreNewResourceEvent;
21
use W2w\Lib\Apie\PluginInterfaces\ResourceLifeCycleInterface;
22
23
/**
24
 * Link the Apie resource life cycle methods Laravel:
25
 * - event dispatcher
26
 * - validation rules with adding 'rules' in context.
27
 * - if the api resource is linked to a policy, check the policy.
28
 */
29
class IlluminateDispatcherPlugin implements ResourceLifeCycleInterface
30
{
31
    /**
32
     * @var Dispatcher
33
     */
34
    private $dispatcher;
35
36
    /**
37
     * @var Factory
38
     */
39
    private $validator;
40
41
    /**
42
     * @var AuthManager
43
     */
44
    private $gate;
45
46
    /**
47
     * @param Dispatcher $dispatcher
48
     * @param Factory $validator
49
     * @param Gate $gate
50
     */
51
    public function __construct(Dispatcher $dispatcher, Factory $validator, Gate $gate)
52
    {
53
        $this->dispatcher = $dispatcher;
54
        $this->validator = $validator;
55
        $this->gate = $gate;
0 ignored issues
show
Documentation Bug introduced by
It seems like $gate of type Illuminate\Contracts\Auth\Access\Gate is incompatible with the declared type Illuminate\Auth\AuthManager of property $gate.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
56
    }
57
58
    /**
59
     * {@inheritDoc}
60
     */
61
    public function onPreDeleteResource(DeleteResourceEvent $event)
62
    {
63
        $this->dispatcher->dispatch($event);
64
    }
65
66
    /**
67
     * {@inheritDoc}
68
     */
69
    public function onPostDeleteResource(DeleteResourceEvent $event)
70
    {
71
        $this->dispatcher->dispatch($event);
72
    }
73
74
    /**
75
     * {@inheritDoc}
76
     */
77
    public function onPreRetrieveResource(RetrieveSingleResourceEvent $event)
78
    {
79
        $this->dispatcher->dispatch($event);
80
    }
81
82
    /**
83
     * {@inheritDoc}
84
     */
85
    public function onPostRetrieveResource(RetrieveSingleResourceEvent $event)
86
    {
87
        if ($this->gate->getPolicyFor($event->getResource())) {
88
            $this->gate->authorize('view', $event->getResource());
89
        }
90
91
        $this->dispatcher->dispatch($event);
92
    }
93
94
    /**
95
     * {@inheritDoc}
96
     */
97
    public function onPreRetrieveAllResources(RetrievePaginatedResourcesEvent $event)
98
    {
99
        $this->dispatcher->dispatch($event);
100
    }
101
102
    /**
103
     * {@inheritDoc}
104
     */
105
    public function onPostRetrieveAllResources(RetrievePaginatedResourcesEvent $event)
106
    {
107
        $resources = $event->getResources();
108
109
        $event->setResources($this->iterateList($resources));
0 ignored issues
show
Bug introduced by
It seems like $resources can also be of type null; however, parameter $resourceList of W2w\Laravel\Apie\Plugins...erPlugin::iterateList() does only seem to accept iterable, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

109
        $event->setResources($this->iterateList(/** @scrutinizer ignore-type */ $resources));
Loading history...
110
        $this->dispatcher->dispatch($event);
111
    }
112
113
    private function iterateList(iterable $resourceList)
114
    {
115
        foreach ($resourceList as $resource) {
116
            // do policy check for every individual item because of polymorphic item list.
117
            if (!$this->gate->getPolicyFor($resource) || $this->gate->allows('view', $resource)) {
118
                yield $resource;
119
            }
120
        }
121
    }
122
123
    /**
124
     * {@inheritDoc}
125
     */
126
    public function onPrePersistExistingResource(StoreExistingResourceEvent $event)
127
    {
128
        if ($this->gate->getPolicyFor($event->getResource())) {
129
            $this->gate->authorize('update', $event->getResource());
130
        }
131
        $this->dispatcher->dispatch($event);
132
    }
133
134
    /**
135
     * {@inheritDoc}
136
     */
137
    public function onPostPersistExistingResource(StoreExistingResourceEvent $event)
138
    {
139
        $this->dispatcher->dispatch($event);
140
    }
141
142
    /**
143
     * {@inheritDoc}
144
     */
145
    public function onPreModifyResource(ModifySingleResourceEvent $event)
146
    {
147
        $this->dispatcher->dispatch($event);
148
    }
149
150
    /**
151
     * {@inheritDoc}
152
     */
153
    public function onPostModifyResource(ModifySingleResourceEvent $event)
154
    {
155
        $this->dispatcher->dispatch($event);
156
    }
157
158
    /**
159
     * {@inheritDoc}
160
     */
161
    public function onPreCreateResource(StoreNewResourceEvent $event)
162
    {
163
        $this->dispatcher->dispatch($event);
164
    }
165
166
    /**
167
     * {@inheritDoc}
168
     */
169
    public function onPostCreateResource(StoreNewResourceEvent $event)
170
    {
171
        $this->dispatcher->dispatch($event);
172
    }
173
174
    /**
175
     * {@inheritDoc}
176
     */
177
    public function onPrePersistNewResource(StoreExistingResourceEvent $event)
178
    {
179
        if ($this->gate->getPolicyFor($event->getResource())) {
180
            $this->gate->authorize('create', $event->getResource());
181
        }
182
        $this->dispatcher->dispatch($event);
183
    }
184
185
    /**
186
     * {@inheritDoc}
187
     */
188
    public function onPostPersistNewResource(StoreExistingResourceEvent $event)
189
    {
190
        $this->dispatcher->dispatch($event);
191
    }
192
193
    /**
194
     * {@inheritDoc}
195
     */
196
    public function onPreCreateResponse(ResponseEvent $event)
197
    {
198
        $this->dispatcher->dispatch($event);
199
    }
200
201
    /**
202
     * {@inheritDoc}
203
     */
204
    public function onPostCreateResponse(ResponseEvent $event)
205
    {
206
        $this->dispatcher->dispatch($event);
207
    }
208
209
    /**
210
     * {@inheritDoc}
211
     */
212
    public function onPreCreateNormalizedData(NormalizeEvent $event)
213
    {
214
        $this->dispatcher->dispatch($event);
215
    }
216
217
    /**
218
     * {@inheritDoc}
219
     */
220
    public function onPostCreateNormalizedData(NormalizeEvent $event)
221
    {
222
        $this->dispatcher->dispatch($event);
223
    }
224
225
    /**
226
     * {@inheritDoc}
227
     */
228
    public function onPreDecodeRequestBody(DecodeEvent $event)
229
    {
230
        $this->dispatcher->dispatch($event);
231
    }
232
233
    /**
234
     * {@inheritDoc}
235
     */
236
    public function onPostDecodeRequestBody(DecodeEvent $event)
237
    {
238
        $refl = new ReflectionClass($event->getResourceClass());
239
        if ($refl->implementsInterface(HasApieRulesContract::class)) {
240
            // maybe move this to a listener?
241
            $rules = $refl->getMethod('getApieRules')->invoke(null);
242
            $decodedData = json_decode(json_encode($event->getDecodedData()), true);
243
            $validation = $this->validator->make($decodedData, $rules);
244
            $event->setDecodedData($validation->validate());
245
        }
246
        $this->dispatcher->dispatch($event);
247
    }
248
}
249