1 | <?php |
||
9 | class ResourceChecker |
||
10 | { |
||
11 | use HandleExceptions; |
||
12 | |||
13 | /** |
||
14 | * Unknown error. |
||
15 | */ |
||
16 | const UNKNOWN_ERROR = 'Unknown error.'; |
||
17 | |||
18 | /** |
||
19 | * The current action. |
||
20 | * |
||
21 | * @var |
||
22 | */ |
||
23 | protected $currentAction = 'check'; |
||
24 | |||
25 | /** |
||
26 | * All resources. |
||
27 | * |
||
28 | * @var |
||
29 | */ |
||
30 | protected $resources; |
||
31 | |||
32 | /** |
||
33 | * Was checked? |
||
34 | * |
||
35 | * @var |
||
36 | */ |
||
37 | protected $checked; |
||
38 | |||
39 | /** |
||
40 | * Services already notified of error. |
||
41 | * |
||
42 | * @var |
||
43 | */ |
||
44 | protected $notified = []; |
||
45 | |||
46 | /** |
||
47 | * The cache service. |
||
48 | * |
||
49 | * @var Cache |
||
50 | */ |
||
51 | protected $cache; |
||
52 | |||
53 | /** |
||
54 | * Resource loader. |
||
55 | * |
||
56 | * @var ResourceLoader |
||
57 | */ |
||
58 | protected $resourceLoader; |
||
59 | |||
60 | /** |
||
61 | * ResourceChecker constructor. |
||
62 | * |
||
63 | * @param ResourceLoader $resourceLoader |
||
64 | * @param Cache $cache |
||
65 | */ |
||
66 | 10 | public function __construct(ResourceLoader $resourceLoader, Cache $cache) |
|
67 | { |
||
68 | 10 | $this->cache = $cache; |
|
69 | |||
70 | 10 | $this->resourceLoader = $resourceLoader; |
|
71 | 10 | } |
|
72 | |||
73 | /** |
||
74 | * Check all resources. |
||
75 | * |
||
76 | * @param bool $force |
||
77 | * @return \Illuminate\Support\Collection |
||
78 | * @throws Exception |
||
79 | */ |
||
80 | 8 | public function checkResources($force = false) |
|
81 | { |
||
82 | 8 | if (! ($resources = $this->getCachedResources($force))->isEmpty()) { |
|
83 | 5 | return $resources; |
|
84 | } |
||
85 | |||
86 | 3 | if (! $this->allResourcesAreGood()) { |
|
87 | return $this->resources = collect(); |
||
88 | } |
||
89 | |||
90 | 3 | $resources = $this->sortResources( |
|
91 | 3 | $this->getNonGlobalResources() |
|
92 | ->each(function ($resource) { |
||
93 | 3 | $this->checkResource($resource); |
|
94 | 3 | }) |
|
95 | 3 | ->merge( |
|
96 | $this->getGlobalResources()->each(function ($resource) { |
||
97 | return $resource->checkGlobal($this->getResources()); |
||
98 | 3 | }) |
|
99 | ) |
||
100 | ); |
||
101 | |||
102 | 3 | $this->checked = true; |
|
103 | |||
104 | 3 | return $this->resources = $this->cache->cacheResources($resources); |
|
105 | } |
||
106 | |||
107 | /** |
||
108 | * Check a resource. |
||
109 | * |
||
110 | * @param $resource |
||
111 | * @return array |
||
112 | * @throws Exception |
||
113 | */ |
||
114 | 4 | public function checkResource($resource) |
|
115 | { |
||
116 | $resource = |
||
117 | 4 | $resource instanceof Resource |
|
118 | 3 | ? $resource |
|
119 | 4 | : $this->getResourceBySlug($resource); |
|
120 | |||
121 | $checked = $this->cache->remember($resource->slug, function () use ( |
||
122 | 1 | $resource |
|
123 | ) { |
||
124 | 1 | return $resource->check($this->getCurrentAction()); |
|
125 | 4 | }); |
|
126 | |||
127 | 4 | $resource->targets = $checked->targets; |
|
128 | |||
129 | 4 | return $resource; |
|
130 | } |
||
131 | |||
132 | /** |
||
133 | * Get cached resources. |
||
134 | * |
||
135 | * @param bool $force |
||
136 | * @return \Illuminate\Support\Collection |
||
137 | * @throws Exception |
||
138 | */ |
||
139 | 8 | protected function getCachedResources($force = false) |
|
140 | { |
||
141 | 8 | if ($force) { |
|
142 | 2 | return collect(); |
|
143 | } |
||
144 | |||
145 | 6 | if ($this->checked) { |
|
146 | return $this->getResources(); |
||
147 | } |
||
148 | |||
149 | 6 | return $this->resources = $this->cache->getCachedResources(); |
|
150 | } |
||
151 | |||
152 | /** |
||
153 | * Get current action. |
||
154 | * |
||
155 | * @return mixed |
||
156 | */ |
||
157 | 1 | public function getCurrentAction() |
|
161 | |||
162 | /** |
||
163 | * Get all non global resources. |
||
164 | * |
||
165 | * @return bool |
||
166 | * @throws Exception |
||
167 | */ |
||
168 | 3 | protected function allResourcesAreGood() |
|
169 | { |
||
170 | 3 | return ! $this->getResources() |
|
171 | ->reject(function ($resource) { |
||
172 | 3 | return ! $resource instanceof Resource; |
|
173 | 3 | }) |
|
174 | 3 | ->isEmpty(); |
|
175 | } |
||
176 | |||
177 | /** |
||
178 | * Get all non global resources. |
||
179 | * |
||
180 | * @return Collection |
||
181 | * @throws Exception |
||
182 | */ |
||
183 | 3 | protected function getNonGlobalResources() |
|
184 | { |
||
185 | return $this->getResources()->filter(function (Resource $resource) { |
||
186 | 3 | return ! $resource->isGlobal; |
|
187 | 3 | }); |
|
188 | } |
||
189 | |||
190 | /** |
||
191 | * Get all global resources. |
||
192 | * |
||
193 | * @return Collection |
||
194 | * @throws Exception |
||
195 | */ |
||
196 | 3 | protected function getGlobalResources() |
|
197 | { |
||
198 | return $this->getResources()->filter(function (Resource $resource) { |
||
199 | 3 | return $resource->isGlobal; |
|
200 | 3 | }); |
|
201 | } |
||
202 | |||
203 | /** |
||
204 | * Get a resource by slug. |
||
205 | * |
||
206 | * @param $slug |
||
207 | * @return mixed |
||
208 | * @throws Exception |
||
209 | */ |
||
210 | 1 | public function getResourceBySlug($slug) |
|
211 | { |
||
212 | 1 | return $this->getResources() |
|
213 | 1 | ->where('slug', $slug) |
|
214 | 1 | ->first(); |
|
215 | } |
||
216 | |||
217 | /** |
||
218 | * Make the result array. |
||
219 | * |
||
220 | * @param $exception |
||
221 | * @param $resourceChecker |
||
222 | * @return array |
||
223 | */ |
||
224 | protected function makeResult($exception, $resourceChecker) |
||
244 | |||
245 | /** |
||
246 | * Get all resources. |
||
247 | * |
||
248 | * @return \Illuminate\Support\Collection |
||
249 | * @throws Exception |
||
250 | */ |
||
251 | 4 | public function getResources() |
|
252 | { |
||
253 | 4 | return $this->sortResources($this->loadResources()); |
|
254 | } |
||
255 | |||
256 | /** |
||
257 | * Set the current action. |
||
258 | * |
||
259 | * @param mixed $currentAction |
||
260 | */ |
||
261 | 1 | public function setCurrentAction($currentAction) |
|
262 | { |
||
263 | 1 | $this->currentAction = $currentAction; |
|
264 | 1 | } |
|
265 | |||
266 | /** |
||
267 | * Resources setter. |
||
268 | * |
||
269 | * @param mixed $resources |
||
270 | */ |
||
271 | public function setResources($resources) |
||
275 | |||
276 | /** |
||
277 | * Load all resources. |
||
278 | * |
||
279 | * @return \Illuminate\Support\Collection |
||
280 | * @throws Exception |
||
281 | */ |
||
282 | 4 | public function loadResources() |
|
283 | { |
||
296 | |||
297 | /** |
||
298 | * Get one resource. |
||
299 | * |
||
300 | * @param resource|Collection $resource |
||
301 | * @return resource |
||
302 | * @throws Exception |
||
303 | */ |
||
304 | 3 | public function makeResource($resource) |
|
312 | |||
313 | /** |
||
314 | * Sort resources. |
||
315 | * |
||
316 | * @param $resources |
||
317 | * @return \Illuminate\Support\Collection |
||
318 | */ |
||
319 | 4 | protected function sortResources($resources) |
|
335 | } |
||
336 |
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.