Complex classes like EntityController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use EntityController, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
21 | class EntityController extends Controller |
||
22 | { |
||
23 | 2 | public function listAction(Request $request) |
|
42 | |||
43 | 2 | public function postAction(Request $request) |
|
63 | |||
64 | 2 | public function getAction(Request $request, $id) |
|
74 | |||
75 | 2 | public function putAction(Request $request, $id) |
|
96 | |||
97 | 2 | public function deleteAction(Request $request, $id) |
|
105 | |||
106 | public function listSubresourceAction(Request $request, $id) |
||
107 | { |
||
108 | $page = $request->query->get('page', 1); |
||
109 | $perPage = $request->query->get('perPage', 50); |
||
110 | |||
111 | $subresource = $this->getSubresource(); |
||
112 | $entity = $this->fetchEntity($id); |
||
113 | $this->assertSubresourceListGranted($entity, $subresource); |
||
114 | |||
115 | $paginator = $this->listSubresource( |
||
116 | $entity, |
||
117 | $subresource, |
||
118 | $page, |
||
119 | $perPage |
||
120 | ); |
||
121 | $total = $paginator->count(); |
||
122 | $entities = $paginator->getIterator()->getArrayCopy(); |
||
123 | |||
124 | $normalizer = $this->get('ddr_rest.normalizer'); |
||
125 | $content = $normalizer->normalize($entities, $this->parseIncludes($request)); |
||
126 | |||
127 | $response = new JsonResponse($content, Response::HTTP_OK); |
||
128 | $this->addPaginationHeaders($response, $page, $perPage, $total); |
||
129 | |||
130 | return $response; |
||
131 | } |
||
132 | |||
133 | public function postSubresourceAction(Request $request, $id) |
||
148 | |||
149 | public function putSubresourceAction(Request $request, $id, $subId) |
||
150 | { |
||
151 | $subresource = $this->getSubresource(); |
||
152 | $parent = $this->fetchEntity($id); |
||
153 | $this->assertSubresourcePutGranted($parent, $subresource); |
||
154 | $this->getService()->addToCollection($parent, $subresource, $subId); |
||
155 | |||
156 | return new JsonResponse(null, Response::HTTP_NO_CONTENT); |
||
157 | } |
||
158 | |||
159 | public function deleteSubresourceAction(Request $request, $id, $subId) |
||
160 | { |
||
161 | $subresource = $this->getSubresource(); |
||
162 | $parent = $this->fetchEntity($id); |
||
163 | $this->assertSubresourceDeleteGranted($parent, $subresource); |
||
164 | $this->getService()->removeFromCollection($parent, $subresource, $subId); |
||
165 | |||
166 | return new JsonResponse(null, Response::HTTP_NO_CONTENT); |
||
167 | } |
||
168 | |||
169 | /** |
||
170 | * @return CrudServiceInterface |
||
171 | */ |
||
172 | 8 | protected function getService() |
|
193 | |||
194 | protected function parseRequest(Request $request, $entity = null, $entityClass = null) |
||
195 | { |
||
196 | return $this->get('ddr.rest.parser.request')->parseEntity($request, $entityClass, $entity); |
||
197 | } |
||
198 | |||
199 | /** |
||
200 | * @param object $entity |
||
201 | * |
||
202 | * @return object |
||
203 | */ |
||
204 | protected function postProcessPostedEntity($entity) |
||
208 | |||
209 | /** |
||
210 | * @param object $entity |
||
211 | * |
||
212 | * @return object |
||
213 | */ |
||
214 | protected function postProcessPuttedEntity($entity) |
||
215 | { |
||
216 | return $entity; |
||
217 | } |
||
218 | |||
219 | /** |
||
220 | * @param string $subresource |
||
221 | * @param object $parent |
||
222 | * @param object $entity |
||
223 | * |
||
224 | * @return object |
||
225 | */ |
||
226 | protected function postProcessSubResourcePostedEntity($subresource, $entity, $parent) |
||
230 | |||
231 | 6 | protected function fetchEntity($id) |
|
240 | |||
241 | 2 | protected function listEntities(int $page = 1, int $perPage = 50): Paginator |
|
247 | |||
248 | protected function createEntity($entity) |
||
252 | |||
253 | protected function updateEntity($entity) |
||
254 | { |
||
255 | return $this->getService()->update($entity); |
||
256 | } |
||
257 | |||
258 | protected function listSubresource($entity, $property, $page = 1, $perPage = 50): Paginator |
||
259 | { |
||
260 | $service = $this->getService(); |
||
261 | |||
262 | return $service->listAssociationPaginated($entity, $property, $page, $perPage); |
||
263 | } |
||
264 | |||
265 | 10 | protected function getEntityClass() |
|
269 | |||
270 | protected function getShortName() |
||
274 | |||
275 | 8 | protected function getServiceId() |
|
279 | |||
280 | 10 | protected function getCurrentRequest() |
|
284 | |||
285 | 2 | protected function assertListGranted() |
|
286 | { |
||
287 | 2 | $classMetadata = $this->getClassMetadata(); |
|
288 | 2 | $right = $classMetadata->getListRight(); |
|
289 | 2 | if (null === $right) { |
|
290 | 2 | return; |
|
291 | } |
||
292 | |||
293 | $this->denyAccessUnlessGranted($right->attributes); |
||
294 | } |
||
295 | |||
296 | 2 | protected function assertPostGranted() |
|
306 | |||
307 | 2 | protected function assertGetGranted($entity) |
|
308 | { |
||
309 | 2 | $classMetadata = $this->getClassMetadata(); |
|
310 | 2 | $right = $classMetadata->getGetRight(); |
|
311 | 2 | if (null === $right) { |
|
312 | 2 | return; |
|
313 | } |
||
314 | |||
315 | $this->assertRightGranted($entity, $right); |
||
316 | } |
||
317 | |||
318 | 2 | protected function assertPutGranted($entity) |
|
319 | { |
||
320 | 2 | $classMetadata = $this->getClassMetadata(); |
|
321 | 2 | $right = $classMetadata->getPutRight(); |
|
322 | 2 | if (null === $right) { |
|
323 | 2 | throw $this->createAccessDeniedException(); |
|
324 | } |
||
325 | |||
326 | $this->assertRightGranted($entity, $right); |
||
327 | } |
||
328 | |||
329 | 2 | protected function assertDeleteGranted($entity) |
|
339 | |||
340 | protected function assertSubresourceListGranted($entity, $subresource) |
||
341 | { |
||
342 | $classMetadata = $this->getClassMetadata(); |
||
343 | /** @var PropertyMetadata $propertyMetadata */ |
||
344 | $propertyMetadata = $classMetadata->propertyMetadata[$subresource]; |
||
345 | $right = $propertyMetadata->getSubResourceListRight(); |
||
346 | if (null === $right) { |
||
347 | return; |
||
348 | } |
||
349 | |||
350 | $this->assertRightGranted($entity, $right); |
||
351 | } |
||
352 | |||
353 | protected function assertSubresourcePostGranted($entity, $subresource) |
||
365 | |||
366 | protected function assertSubresourcePutGranted($entity, $subresource) |
||
367 | { |
||
368 | $classMetadata = $this->getClassMetadata(); |
||
369 | /** @var PropertyMetadata $propertyMetadata */ |
||
370 | $propertyMetadata = $classMetadata->propertyMetadata[$subresource]; |
||
371 | $right = $propertyMetadata->getSubResourcePutRight(); |
||
372 | if (null === $right) { |
||
373 | throw $this->createAccessDeniedException(); |
||
374 | } |
||
375 | |||
376 | $this->assertRightGranted($entity, $right); |
||
377 | } |
||
378 | |||
379 | protected function assertSubresourceDeleteGranted($entity, $subresource) |
||
380 | { |
||
381 | $classMetadata = $this->getClassMetadata(); |
||
382 | /** @var PropertyMetadata $propertyMetadata */ |
||
383 | $propertyMetadata = $classMetadata->propertyMetadata[$subresource]; |
||
384 | $right = $propertyMetadata->getSubResourceDeleteRight(); |
||
385 | if (null === $right) { |
||
386 | throw $this->createAccessDeniedException(); |
||
387 | } |
||
388 | |||
389 | $this->assertRightGranted($entity, $right); |
||
390 | } |
||
391 | |||
392 | /** |
||
393 | * @return ClassMetadata |
||
394 | */ |
||
395 | 10 | protected function getClassMetadata() |
|
403 | |||
404 | protected function getSubResourceEntityClass($subresource) |
||
411 | |||
412 | protected function resolveSubject($entity, $propertyPath) |
||
421 | |||
422 | /** |
||
423 | * @param object $entity |
||
424 | * @param Right $right |
||
425 | */ |
||
426 | protected function assertRightGranted($entity, Right $right) |
||
427 | { |
||
428 | $propertyPath = $right->propertyPath; |
||
429 | if (null === $propertyPath) { |
||
430 | $this->denyAccessUnlessGranted($right->attributes); |
||
431 | } else { |
||
432 | $subject = $this->resolveSubject($entity, $propertyPath); |
||
433 | $this->denyAccessUnlessGranted($right->attributes, $subject); |
||
434 | } |
||
435 | } |
||
436 | |||
437 | /** |
||
438 | * @return string[] |
||
439 | */ |
||
440 | protected function getSubresourceSerializationGroups($subresource) |
||
444 | |||
445 | /** |
||
446 | * @param string $subresource |
||
447 | * @param object $entity |
||
448 | * |
||
449 | * @return |
||
450 | */ |
||
451 | protected function saveSubResource($subresource, $entity) |
||
455 | |||
456 | /** |
||
457 | * @return string|null |
||
458 | */ |
||
459 | protected function getSubresource() |
||
460 | { |
||
461 | return $this->getCurrentRequest()->attributes->get('_subresource'); |
||
462 | } |
||
463 | |||
464 | 4 | protected function parseIncludes(Request $request) |
|
465 | { |
||
466 | 4 | $includeString = $request->query->get('include'); |
|
467 | 4 | if (empty($includeString)) { |
|
468 | 4 | return []; |
|
469 | } |
||
470 | |||
471 | return explode(',', $includeString); |
||
472 | } |
||
473 | |||
474 | private function parseConstraintViolations(ConstraintViolationListInterface $errors) |
||
488 | |||
489 | 2 | private function addPaginationHeaders(Response $response, int $page, int $perPage, int $total) |
|
500 | } |
||
501 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.