Completed
Push — master ( 603bb4...808830 )
by Kamil
13:03
created

ResourceController::updateAction()   D

Complexity

Conditions 14
Paths 12

Size

Total Lines 82
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 82
rs 4.955
c 0
b 0
f 0
cc 14
eloc 46
nc 12
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Sylius\Bundle\ResourceBundle\Controller;
15
16
use Doctrine\Common\Persistence\ObjectManager;
17
use FOS\RestBundle\View\View;
18
use Sylius\Bundle\ResourceBundle\Event\ResourceControllerEvent;
19
use Sylius\Component\Resource\Exception\DeleteHandlingException;
20
use Sylius\Component\Resource\Exception\UpdateHandlingException;
21
use Sylius\Component\Resource\Factory\FactoryInterface;
22
use Sylius\Component\Resource\Metadata\MetadataInterface;
23
use Sylius\Component\Resource\Model\ResourceInterface;
24
use Sylius\Component\Resource\Repository\RepositoryInterface;
25
use Sylius\Component\Resource\ResourceActions;
26
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
27
use Symfony\Component\HttpFoundation\Request;
28
use Symfony\Component\HttpFoundation\Response;
29
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
30
use Symfony\Component\HttpKernel\Exception\HttpException;
31
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
32
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
33
34
class ResourceController extends Controller
35
{
36
    /**
37
     * @var MetadataInterface
38
     */
39
    protected $metadata;
40
41
    /**
42
     * @var RequestConfigurationFactoryInterface
43
     */
44
    protected $requestConfigurationFactory;
45
46
    /**
47
     * @var ViewHandlerInterface
48
     */
49
    protected $viewHandler;
50
51
    /**
52
     * @var RepositoryInterface
53
     */
54
    protected $repository;
55
56
    /**
57
     * @var FactoryInterface
58
     */
59
    protected $factory;
60
61
    /**
62
     * @var NewResourceFactoryInterface
63
     */
64
    protected $newResourceFactory;
65
66
    /**
67
     * @var ObjectManager
68
     */
69
    protected $manager;
70
71
    /**
72
     * @var SingleResourceProviderInterface
73
     */
74
    protected $singleResourceProvider;
75
76
    /**
77
     * @var ResourcesCollectionProviderInterface
78
     */
79
    protected $resourcesCollectionProvider;
80
81
    /**
82
     * @var ResourceFormFactoryInterface
83
     */
84
    protected $resourceFormFactory;
85
86
    /**
87
     * @var RedirectHandlerInterface
88
     */
89
    protected $redirectHandler;
90
91
    /**
92
     * @var FlashHelperInterface
93
     */
94
    protected $flashHelper;
95
96
    /**
97
     * @var AuthorizationCheckerInterface
98
     */
99
    protected $authorizationChecker;
100
101
    /**
102
     * @var EventDispatcherInterface
103
     */
104
    protected $eventDispatcher;
105
106
    /**
107
     * @var StateMachineInterface
108
     */
109
    protected $stateMachine;
110
111
    /**
112
     * @var ResourceUpdateHandlerInterface
113
     */
114
    protected $resourceUpdateHandler;
115
116
    /**
117
     * @var ResourceDeleteHandlerInterface
118
     */
119
    protected $resourceDeleteHandler;
120
121
    /**
122
     * @param MetadataInterface $metadata
123
     * @param RequestConfigurationFactoryInterface $requestConfigurationFactory
124
     * @param ViewHandlerInterface $viewHandler
125
     * @param RepositoryInterface $repository
126
     * @param FactoryInterface $factory
127
     * @param NewResourceFactoryInterface $newResourceFactory
128
     * @param ObjectManager $manager
129
     * @param SingleResourceProviderInterface $singleResourceProvider
130
     * @param ResourcesCollectionProviderInterface $resourcesFinder
131
     * @param ResourceFormFactoryInterface $resourceFormFactory
132
     * @param RedirectHandlerInterface $redirectHandler
133
     * @param FlashHelperInterface $flashHelper
134
     * @param AuthorizationCheckerInterface $authorizationChecker
135
     * @param EventDispatcherInterface $eventDispatcher
136
     * @param StateMachineInterface $stateMachine
137
     * @param ResourceUpdateHandlerInterface $resourceUpdateHandler
138
     * @param ResourceDeleteHandlerInterface $resourceDeleteHandler
139
     */
140
    public function __construct(
141
        MetadataInterface $metadata,
142
        RequestConfigurationFactoryInterface $requestConfigurationFactory,
143
        ViewHandlerInterface $viewHandler,
144
        RepositoryInterface $repository,
145
        FactoryInterface $factory,
146
        NewResourceFactoryInterface $newResourceFactory,
147
        ObjectManager $manager,
148
        SingleResourceProviderInterface $singleResourceProvider,
149
        ResourcesCollectionProviderInterface $resourcesFinder,
150
        ResourceFormFactoryInterface $resourceFormFactory,
151
        RedirectHandlerInterface $redirectHandler,
152
        FlashHelperInterface $flashHelper,
153
        AuthorizationCheckerInterface $authorizationChecker,
154
        EventDispatcherInterface $eventDispatcher,
155
        StateMachineInterface $stateMachine,
156
        ResourceUpdateHandlerInterface $resourceUpdateHandler,
157
        ResourceDeleteHandlerInterface $resourceDeleteHandler
158
    ) {
159
        $this->metadata = $metadata;
160
        $this->requestConfigurationFactory = $requestConfigurationFactory;
161
        $this->viewHandler = $viewHandler;
162
        $this->repository = $repository;
163
        $this->factory = $factory;
164
        $this->newResourceFactory = $newResourceFactory;
165
        $this->manager = $manager;
166
        $this->singleResourceProvider = $singleResourceProvider;
167
        $this->resourcesCollectionProvider = $resourcesFinder;
168
        $this->resourceFormFactory = $resourceFormFactory;
169
        $this->redirectHandler = $redirectHandler;
170
        $this->flashHelper = $flashHelper;
171
        $this->authorizationChecker = $authorizationChecker;
172
        $this->eventDispatcher = $eventDispatcher;
173
        $this->stateMachine = $stateMachine;
174
        $this->resourceUpdateHandler = $resourceUpdateHandler;
175
        $this->resourceDeleteHandler = $resourceDeleteHandler;
176
    }
177
178
    /**
179
     * @param Request $request
180
     *
181
     * @return Response
182
     */
183
    public function showAction(Request $request): Response
184
    {
185
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
186
187
        $this->isGrantedOr403($configuration, ResourceActions::SHOW);
188
        $resource = $this->findOr404($configuration);
189
190
        $this->eventDispatcher->dispatch(ResourceActions::SHOW, $configuration, $resource);
191
192
        $view = View::create($resource);
193
194
        if ($configuration->isHtmlRequest()) {
195
            $view
196
                ->setTemplate($configuration->getTemplate(ResourceActions::SHOW . '.html'))
197
                ->setTemplateVar($this->metadata->getName())
198
                ->setData([
199
                    'configuration' => $configuration,
200
                    'metadata' => $this->metadata,
201
                    'resource' => $resource,
202
                    $this->metadata->getName() => $resource,
203
                ])
204
            ;
205
        }
206
207
        return $this->viewHandler->handle($configuration, $view);
208
    }
209
210
    /**
211
     * @param Request $request
212
     *
213
     * @return Response
214
     */
215
    public function indexAction(Request $request): Response
216
    {
217
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
218
219
        $this->isGrantedOr403($configuration, ResourceActions::INDEX);
220
        $resources = $this->resourcesCollectionProvider->get($configuration, $this->repository);
221
222
        $this->eventDispatcher->dispatchMultiple(ResourceActions::INDEX, $configuration, $resources);
223
224
        $view = View::create($resources);
225
226
        if ($configuration->isHtmlRequest()) {
227
            $view
228
                ->setTemplate($configuration->getTemplate(ResourceActions::INDEX . '.html'))
229
                ->setTemplateVar($this->metadata->getPluralName())
230
                ->setData([
231
                    'configuration' => $configuration,
232
                    'metadata' => $this->metadata,
233
                    'resources' => $resources,
234
                    $this->metadata->getPluralName() => $resources,
235
                ])
236
            ;
237
        }
238
239
        return $this->viewHandler->handle($configuration, $view);
240
    }
241
242
    /**
243
     * @param Request $request
244
     *
245
     * @return Response
246
     */
247
    public function createAction(Request $request): Response
248
    {
249
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
250
251
        $this->isGrantedOr403($configuration, ResourceActions::CREATE);
252
        $newResource = $this->newResourceFactory->create($configuration, $this->factory);
253
254
        $form = $this->resourceFormFactory->create($configuration, $newResource);
255
256
        if ($request->isMethod('POST') && $form->handleRequest($request)->isValid()) {
257
            $newResource = $form->getData();
258
259
            $event = $this->eventDispatcher->dispatchPreEvent(ResourceActions::CREATE, $configuration, $newResource);
260
261
            if ($event->isStopped() && !$configuration->isHtmlRequest()) {
262
                throw new HttpException($event->getErrorCode(), $event->getMessage());
263
            }
264
            if ($event->isStopped()) {
265
                $this->flashHelper->addFlashFromEvent($configuration, $event);
266
267
                if ($event->hasResponse()) {
268
                    return $event->getResponse();
269
                }
270
271
                return $this->redirectHandler->redirectToIndex($configuration, $newResource);
272
            }
273
274
            if ($configuration->hasStateMachine()) {
275
                $this->stateMachine->apply($configuration, $newResource);
276
            }
277
278
            $this->repository->add($newResource);
279
            $postEvent = $this->eventDispatcher->dispatchPostEvent(ResourceActions::CREATE, $configuration, $newResource);
280
281
            if (!$configuration->isHtmlRequest()) {
282
                return $this->viewHandler->handle($configuration, View::create($newResource, Response::HTTP_CREATED));
283
            }
284
285
            $this->flashHelper->addSuccessFlash($configuration, ResourceActions::CREATE, $newResource);
286
287
            if ($postEvent->hasResponse()) {
288
                return $postEvent->getResponse();
289
            }
290
291
            return $this->redirectHandler->redirectToResource($configuration, $newResource);
292
        }
293
294
        if (!$configuration->isHtmlRequest()) {
295
            return $this->viewHandler->handle($configuration, View::create($form, Response::HTTP_BAD_REQUEST));
296
        }
297
298
        $initializeEvent = $this->eventDispatcher->dispatchInitializeEvent(ResourceActions::CREATE, $configuration, $newResource);
299
        if ($initializeEvent->hasResponse()) {
300
            return $initializeEvent->getResponse();
301
        }
302
303
        $view = View::create()
304
            ->setData([
305
                'configuration' => $configuration,
306
                'metadata' => $this->metadata,
307
                'resource' => $newResource,
308
                $this->metadata->getName() => $newResource,
309
                'form' => $form->createView(),
310
            ])
311
            ->setTemplate($configuration->getTemplate(ResourceActions::CREATE . '.html'))
312
        ;
313
314
        return $this->viewHandler->handle($configuration, $view);
315
    }
316
317
    /**
318
     * @param Request $request
319
     *
320
     * @return Response
321
     */
322
    public function updateAction(Request $request): Response
323
    {
324
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
325
326
        $this->isGrantedOr403($configuration, ResourceActions::UPDATE);
327
        $resource = $this->findOr404($configuration);
328
329
        $form = $this->resourceFormFactory->create($configuration, $resource);
330
331
        if (in_array($request->getMethod(), ['POST', 'PUT', 'PATCH'], true) && $form->handleRequest($request)->isValid()) {
332
            $resource = $form->getData();
333
334
            /** @var ResourceControllerEvent $event */
335
            $event = $this->eventDispatcher->dispatchPreEvent(ResourceActions::UPDATE, $configuration, $resource);
336
337
            if ($event->isStopped() && !$configuration->isHtmlRequest()) {
338
                throw new HttpException($event->getErrorCode(), $event->getMessage());
339
            }
340
            if ($event->isStopped()) {
341
                $this->flashHelper->addFlashFromEvent($configuration, $event);
342
343
                if ($event->hasResponse()) {
344
                    return $event->getResponse();
345
                }
346
347
                return $this->redirectHandler->redirectToResource($configuration, $resource);
348
            }
349
350
            try {
351
                $this->resourceUpdateHandler->handle($resource, $configuration, $this->manager);
352
            } catch (UpdateHandlingException $exception) {
353
                if (!$configuration->isHtmlRequest()) {
354
                    return $this->viewHandler->handle(
355
                        $configuration,
356
                        View::create($form, $exception->getApiResponseCode())
357
                    );
358
                }
359
360
                $this->flashHelper->addErrorFlash($configuration, $exception->getFlash());
361
362
                return $this->redirectHandler->redirectToReferer($configuration);
363
            }
364
365
            $postEvent = $this->eventDispatcher->dispatchPostEvent(ResourceActions::UPDATE, $configuration, $resource);
366
367
            if (!$configuration->isHtmlRequest()) {
368
                $view = $configuration->getParameters()->get('return_content', false) ? View::create($resource, Response::HTTP_OK) : View::create(null, Response::HTTP_NO_CONTENT);
369
370
                return $this->viewHandler->handle($configuration, $view);
371
            }
372
373
            $this->flashHelper->addSuccessFlash($configuration, ResourceActions::UPDATE, $resource);
374
375
            if ($postEvent->hasResponse()) {
376
                return $postEvent->getResponse();
377
            }
378
379
            return $this->redirectHandler->redirectToResource($configuration, $resource);
380
        }
381
382
        if (!$configuration->isHtmlRequest()) {
383
            return $this->viewHandler->handle($configuration, View::create($form, Response::HTTP_BAD_REQUEST));
384
        }
385
386
        $initializeEvent = $this->eventDispatcher->dispatchInitializeEvent(ResourceActions::UPDATE, $configuration, $resource);
387
        if ($initializeEvent->hasResponse()) {
388
            return $initializeEvent->getResponse();
389
        }
390
391
        $view = View::create()
392
            ->setData([
393
                'configuration' => $configuration,
394
                'metadata' => $this->metadata,
395
                'resource' => $resource,
396
                $this->metadata->getName() => $resource,
397
                'form' => $form->createView(),
398
            ])
399
            ->setTemplate($configuration->getTemplate(ResourceActions::UPDATE . '.html'))
400
        ;
401
402
        return $this->viewHandler->handle($configuration, $view);
403
    }
404
405
    /**
406
     * @param Request $request
407
     *
408
     * @return Response
409
     */
410
    public function deleteAction(Request $request): Response
411
    {
412
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
413
414
        $this->isGrantedOr403($configuration, ResourceActions::DELETE);
415
        $resource = $this->findOr404($configuration);
416
417
        if ($configuration->isCsrfProtectionEnabled() && !$this->isCsrfTokenValid($resource->getId(), $request->request->get('_csrf_token'))) {
418
            throw new HttpException(Response::HTTP_FORBIDDEN, 'Invalid csrf token.');
419
        }
420
421
        $event = $this->eventDispatcher->dispatchPreEvent(ResourceActions::DELETE, $configuration, $resource);
422
423
        if ($event->isStopped() && !$configuration->isHtmlRequest()) {
424
            throw new HttpException($event->getErrorCode(), $event->getMessage());
425
        }
426
        if ($event->isStopped()) {
427
            $this->flashHelper->addFlashFromEvent($configuration, $event);
428
429
            if ($event->hasResponse()) {
430
                return $event->getResponse();
431
            }
432
433
            return $this->redirectHandler->redirectToIndex($configuration, $resource);
434
        }
435
436
        try {
437
            $this->resourceDeleteHandler->handle($resource, $this->repository);
438
        } catch (DeleteHandlingException $exception) {
439
            if (!$configuration->isHtmlRequest()) {
440
                return $this->viewHandler->handle(
441
                    $configuration,
442
                    View::create(null, $exception->getApiResponseCode())
443
                );
444
            }
445
446
            $this->flashHelper->addErrorFlash($configuration, $exception->getFlash());
447
448
            return $this->redirectHandler->redirectToReferer($configuration);
449
        }
450
451
        $postEvent = $this->eventDispatcher->dispatchPostEvent(ResourceActions::DELETE, $configuration, $resource);
452
453
        if (!$configuration->isHtmlRequest()) {
454
            return $this->viewHandler->handle($configuration, View::create(null, Response::HTTP_NO_CONTENT));
455
        }
456
457
        $this->flashHelper->addSuccessFlash($configuration, ResourceActions::DELETE, $resource);
458
459
        if ($postEvent->hasResponse()) {
460
            return $postEvent->getResponse();
461
        }
462
463
        return $this->redirectHandler->redirectToIndex($configuration, $resource);
464
    }
465
466
    /**
467
     * @param Request $request
468
     *
469
     * @return Response
470
     */
471
    public function bulkDeleteAction(Request $request): Response
472
    {
473
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
474
475
        $this->isGrantedOr403($configuration, ResourceActions::BULK_DELETE);
476
        $resources = $this->resourcesCollectionProvider->get($configuration, $this->repository);
477
478
        if (
479
            $configuration->isCsrfProtectionEnabled() &&
480
            !$this->isCsrfTokenValid(ResourceActions::BULK_DELETE, $request->request->get('_csrf_token'))
481
        ) {
482
            throw new HttpException(Response::HTTP_FORBIDDEN, 'Invalid csrf token.');
483
        }
484
485
        $this->eventDispatcher->dispatchMultiple(ResourceActions::BULK_DELETE, $configuration, $resources);
486
487
        foreach ($resources as $resource) {
488
            $event = $this->eventDispatcher->dispatchPreEvent(ResourceActions::DELETE, $configuration, $resource);
489
490
            if ($event->isStopped() && !$configuration->isHtmlRequest()) {
491
                throw new HttpException($event->getErrorCode(), $event->getMessage());
492
            }
493
            if ($event->isStopped()) {
494
                $this->flashHelper->addFlashFromEvent($configuration, $event);
495
496
                if ($event->hasResponse()) {
497
                    return $event->getResponse();
498
                }
499
500
                return $this->redirectHandler->redirectToIndex($configuration, $resource);
501
            }
502
503
            try {
504
                $this->resourceDeleteHandler->handle($resource, $this->repository);
505
            } catch (DeleteHandlingException $exception) {
506
                if (!$configuration->isHtmlRequest()) {
507
                    return $this->viewHandler->handle(
508
                        $configuration,
509
                        View::create(null, $exception->getApiResponseCode())
510
                    );
511
                }
512
513
                $this->flashHelper->addErrorFlash($configuration, $exception->getFlash());
514
515
                return $this->redirectHandler->redirectToReferer($configuration);
516
            }
517
518
            $postEvent = $this->eventDispatcher->dispatchPostEvent(ResourceActions::DELETE, $configuration, $resource);
519
        }
520
521
        if (!$configuration->isHtmlRequest()) {
522
            return $this->viewHandler->handle($configuration, View::create(null, Response::HTTP_NO_CONTENT));
523
        }
524
525
        $this->flashHelper->addSuccessFlash($configuration, ResourceActions::BULK_DELETE);
526
527
        if (isset($postEvent) && $postEvent->hasResponse()) {
528
            return $postEvent->getResponse();
529
        }
530
531
        return $this->redirectHandler->redirectToIndex($configuration);
532
    }
533
534
    /**
535
     * @param Request $request
536
     *
537
     * @return Response
538
     */
539
    public function applyStateMachineTransitionAction(Request $request): Response
540
    {
541
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
542
543
        $this->isGrantedOr403($configuration, ResourceActions::UPDATE);
544
        $resource = $this->findOr404($configuration);
545
546
        $event = $this->eventDispatcher->dispatchPreEvent(ResourceActions::UPDATE, $configuration, $resource);
547
548
        if ($event->isStopped() && !$configuration->isHtmlRequest()) {
549
            throw new HttpException($event->getErrorCode(), $event->getMessage());
550
        }
551
        if ($event->isStopped()) {
552
            $this->flashHelper->addFlashFromEvent($configuration, $event);
553
554
            if ($event->hasResponse()) {
555
                return $event->getResponse();
556
            }
557
558
            return $this->redirectHandler->redirectToResource($configuration, $resource);
559
        }
560
561
        if (!$this->stateMachine->can($configuration, $resource)) {
562
            throw new BadRequestHttpException();
563
        }
564
565
        try {
566
            $this->resourceUpdateHandler->handle($resource, $configuration, $this->manager);
567
        } catch (UpdateHandlingException $exception) {
568
            if (!$configuration->isHtmlRequest()) {
569
                return $this->viewHandler->handle(
570
                    $configuration,
571
                    View::create($resource, $exception->getApiResponseCode())
572
                );
573
            }
574
575
            $this->flashHelper->addErrorFlash($configuration, $exception->getFlash());
576
577
            return $this->redirectHandler->redirectToReferer($configuration);
578
        }
579
580
        $postEvent = $this->eventDispatcher->dispatchPostEvent(ResourceActions::UPDATE, $configuration, $resource);
581
582
        if (!$configuration->isHtmlRequest()) {
583
            $view = $configuration->getParameters()->get('return_content', true) ? View::create($resource, Response::HTTP_OK) : View::create(null, Response::HTTP_NO_CONTENT);
584
585
            return $this->viewHandler->handle($configuration, $view);
586
        }
587
588
        $this->flashHelper->addSuccessFlash($configuration, ResourceActions::UPDATE, $resource);
589
590
        if ($postEvent->hasResponse()) {
591
            return $postEvent->getResponse();
592
        }
593
594
        return $this->redirectHandler->redirectToResource($configuration, $resource);
595
    }
596
597
    /**
598
     * @param RequestConfiguration $configuration
599
     * @param string $permission
600
     *
601
     * @throws AccessDeniedException
602
     */
603
    protected function isGrantedOr403(RequestConfiguration $configuration, string $permission): void
604
    {
605
        if (!$configuration->hasPermission()) {
606
            return;
607
        }
608
609
        $permission = $configuration->getPermission($permission);
610
611
        if (!$this->authorizationChecker->isGranted($configuration, $permission)) {
612
            throw new AccessDeniedException();
613
        }
614
    }
615
616
    /**
617
     * @param RequestConfiguration $configuration
618
     *
619
     * @return ResourceInterface
620
     *
621
     * @throws NotFoundHttpException
622
     */
623
    protected function findOr404(RequestConfiguration $configuration): ResourceInterface
624
    {
625
        if (null === $resource = $this->singleResourceProvider->get($configuration, $this->repository)) {
626
            throw new NotFoundHttpException(sprintf('The "%s" has not been found', $this->metadata->getHumanizedName()));
627
        }
628
629
        return $resource;
630
    }
631
}
632