Completed
Push — master ( 1ecbe4...61c842 )
by Michał
264:53 queued 250:28
created

applyStateMachineTransitionAction()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 31
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 31
rs 8.439
cc 5
eloc 17
nc 4
nop 1
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
namespace Sylius\Bundle\ResourceBundle\Controller;
13
14
use Doctrine\Common\Persistence\ObjectManager;
15
use FOS\RestBundle\View\View;
16
use Sylius\Component\Resource\Factory\FactoryInterface;
17
use Sylius\Component\Resource\Metadata\MetadataInterface;
18
use Sylius\Component\Resource\Repository\RepositoryInterface;
19
use Sylius\Component\Resource\ResourceActions;
20
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
21
use Symfony\Component\HttpFoundation\RedirectResponse;
22
use Symfony\Component\HttpFoundation\Request;
23
use Symfony\Component\HttpFoundation\Response;
24
use Symfony\Component\HttpKernel\Exception\HttpException;
25
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
26
use Symfony\Component\PropertyAccess\PropertyAccess;
27
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
28
29
/**
30
 * @author Paweł Jędrzejewski <[email protected]>
31
 * @author Saša Stamenković <[email protected]>
32
 */
33
class ResourceController extends Controller
34
{
35
    /**
36
     * @var MetadataInterface
37
     */
38
    protected $metadata;
39
40
    /**
41
     * @var RequestConfigurationFactoryInterface
42
     */
43
    protected $requestConfigurationFactory;
44
45
    /**
46
     * @var ViewHandlerInterface
47
     */
48
    protected $viewHandler;
49
50
    /**
51
     * @var RepositoryInterface
52
     */
53
    protected $repository;
54
55
    /**
56
     * @var FactoryInterface
57
     */
58
    protected $factory;
59
60
    /**
61
     * @var NewResourceFactoryInterface
62
     */
63
    protected $newResourceFactory;
64
65
    /**
66
     * @var ObjectManager
67
     */
68
    protected $manager;
69
70
    /**
71
     * @var SingleResourceProviderInterface
72
     */
73
    protected $singleResourceProvider;
74
75
    /**
76
     * @var ResourcesCollectionProviderInterface
77
     */
78
    protected $resourcesCollectionProvider;
79
80
    /**
81
     * @var ResourceFormFactoryInterface
82
     */
83
    protected $resourceFormFactory;
84
85
    /**
86
     * @var RedirectHandlerInterface
87
     */
88
    protected $redirectHandler;
89
90
    /**
91
     * @var FlashHelperInterface
92
     */
93
    protected $flashHelper;
94
95
    /**
96
     * @var AuthorizationCheckerInterface
97
     */
98
    protected $authorizationChecker;
99
100
    /**
101
     * @var EventDispatcherInterface
102
     */
103
    protected $eventDispatcher;
104
105
    /**
106
     * @var StateMachineInterface
107
     */
108
    protected $stateMachine;
109
110
    /**
111
     * @param MetadataInterface $metadata
112
     * @param RequestConfigurationFactoryInterface $requestConfigurationFactory
113
     * @param ViewHandlerInterface $viewHandler
114
     * @param RepositoryInterface $repository
115
     * @param FactoryInterface $factory
116
     * @param NewResourceFactoryInterface $newResourceFactory
117
     * @param ObjectManager $manager
118
     * @param SingleResourceProviderInterface $singleResourceProvider
119
     * @param ResourcesCollectionProviderInterface $resourcesFinder
120
     * @param ResourceFormFactoryInterface $resourceFormFactory
121
     * @param RedirectHandlerInterface $redirectHandler
122
     * @param FlashHelperInterface $flashHelper
123
     * @param AuthorizationCheckerInterface $authorizationChecker
124
     * @param EventDispatcherInterface $eventDispatcher
125
     * @param StateMachineInterface $stateMachine
126
     */
127
    public function __construct(
128
        MetadataInterface $metadata,
129
        RequestConfigurationFactoryInterface $requestConfigurationFactory,
130
        ViewHandlerInterface $viewHandler,
131
        RepositoryInterface $repository,
132
        FactoryInterface $factory,
133
        NewResourceFactoryInterface $newResourceFactory,
134
        ObjectManager $manager,
135
        SingleResourceProviderInterface $singleResourceProvider,
136
        ResourcesCollectionProviderInterface $resourcesFinder,
137
        ResourceFormFactoryInterface $resourceFormFactory,
138
        RedirectHandlerInterface $redirectHandler,
139
        FlashHelperInterface $flashHelper,
140
        AuthorizationCheckerInterface $authorizationChecker,
141
        EventDispatcherInterface $eventDispatcher,
142
        StateMachineInterface $stateMachine
143
    ) {
144
        $this->metadata = $metadata;
145
        $this->requestConfigurationFactory = $requestConfigurationFactory;
146
        $this->viewHandler = $viewHandler;
147
        $this->repository = $repository;
148
        $this->factory = $factory;
149
        $this->newResourceFactory = $newResourceFactory;
150
        $this->manager = $manager;
151
        $this->singleResourceProvider = $singleResourceProvider;
152
        $this->resourcesCollectionProvider = $resourcesFinder;
153
        $this->resourceFormFactory = $resourceFormFactory;
154
        $this->redirectHandler = $redirectHandler;
155
        $this->flashHelper = $flashHelper;
156
        $this->authorizationChecker = $authorizationChecker;
157
        $this->eventDispatcher = $eventDispatcher;
158
        $this->stateMachine = $stateMachine;
159
    }
160
161
    /**
162
     * @param Request $request
163
     *
164
     * @return Response
165
     */
166
    public function showAction(Request $request)
167
    {
168
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
169
170
        $this->isGrantedOr403($configuration, ResourceActions::SHOW);
171
        $resource = $this->findOr404($configuration);
172
173
        $this->eventDispatcher->dispatch(ResourceActions::SHOW, $configuration, $resource);
174
175
        $view = View::create($resource);
176
177
        if ($configuration->isHtmlRequest()) {
178
            $view
179
                ->setTemplate($configuration->getTemplate(ResourceActions::SHOW . '.html'))
180
                ->setTemplateVar($this->metadata->getName())
181
                ->setData([
182
                    'configuration' => $configuration,
183
                    'metadata' => $this->metadata,
184
                    'resource' => $resource,
185
                    $this->metadata->getName() => $resource,
186
                ])
187
            ;
188
        }
189
190
        return $this->viewHandler->handle($configuration, $view);
191
    }
192
193
    /**
194
     * @param Request $request
195
     *
196
     * @return \Symfony\Component\HttpFoundation\Response
197
     */
198
    public function indexAction(Request $request)
199
    {
200
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
201
202
        $this->isGrantedOr403($configuration, ResourceActions::INDEX);
203
        $resources = $this->resourcesCollectionProvider->get($configuration, $this->repository);
204
205
        $view = View::create($resources);
206
207
        if ($configuration->isHtmlRequest()) {
208
            $view
209
                ->setTemplate($configuration->getTemplate(ResourceActions::INDEX . '.html'))
210
                ->setTemplateVar($this->metadata->getPluralName())
211
                ->setData([
212
                    'configuration' => $configuration,
213
                    'metadata' => $this->metadata,
214
                    'resources' => $resources,
215
                    $this->metadata->getPluralName() => $resources,
216
                ])
217
            ;
218
        }
219
220
        return $this->viewHandler->handle($configuration, $view);
221
    }
222
223
    /**
224
     * @param Request $request
225
     *
226
     * @return Response
227
     */
228
    public function createAction(Request $request)
229
    {
230
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
231
232
        $this->isGrantedOr403($configuration, ResourceActions::CREATE);
233
        $newResource = $this->newResourceFactory->create($configuration, $this->factory);
234
235
        $form = $this->resourceFormFactory->create($configuration, $newResource);
236
237
        if ($request->isMethod('POST') && $form->submit($request)->isValid()) {
238
            $newResource = $form->getData();
239
240
            $event = $this->eventDispatcher->dispatchPreEvent(ResourceActions::CREATE, $configuration, $newResource);
241
242
            if ($event->isStopped() && !$configuration->isHtmlRequest()) {
243
                throw new HttpException($event->getErrorCode(), $event->getMessage());
244
            }
245
            if ($event->isStopped()) {
246
                $this->flashHelper->addFlashFromEvent($configuration, $event);
247
248
                return $this->redirectHandler->redirectToIndex($configuration, $newResource);
249
            }
250
251
            $this->repository->add($newResource);
252
            $this->eventDispatcher->dispatchPostEvent(ResourceActions::CREATE, $configuration, $newResource);
253
254
            if (!$configuration->isHtmlRequest()) {
255
                return $this->viewHandler->handle($configuration, View::create($newResource, 201));
256
            }
257
258
            $this->flashHelper->addSuccessFlash($configuration, ResourceActions::CREATE, $newResource);
259
260
            return $this->redirectHandler->redirectToResource($configuration, $newResource);
261
        }
262
263
        if (!$configuration->isHtmlRequest()) {
264
            return $this->viewHandler->handle($configuration, View::create($form, 400));
265
        }
266
267
        $view = View::create()
268
            ->setData([
269
                'configuration' => $configuration,
270
                'metadata' => $this->metadata,
271
                'resource' => $newResource,
272
                $this->metadata->getName() => $newResource,
273
                'form' => $form->createView(),
274
            ])
275
            ->setTemplate($configuration->getTemplate(ResourceActions::CREATE . '.html'))
276
        ;
277
278
        return $this->viewHandler->handle($configuration, $view);
279
    }
280
281
    /**
282
     * @param Request $request
283
     *
284
     * @return Response
285
     */
286
    public function updateAction(Request $request)
287
    {
288
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
289
290
        $this->isGrantedOr403($configuration, ResourceActions::UPDATE);
291
        $resource = $this->findOr404($configuration);
292
293
        $form = $this->resourceFormFactory->create($configuration, $resource);
294
295
        if (in_array($request->getMethod(), ['POST', 'PUT', 'PATCH']) && $form->submit($request, !$request->isMethod('PATCH'))->isValid()) {
296
            $resource = $form->getData();
297
298
            $event = $this->eventDispatcher->dispatchPreEvent(ResourceActions::UPDATE, $configuration, $resource);
299
300
            if ($event->isStopped() && !$configuration->isHtmlRequest()) {
301
                throw new HttpException($event->getErrorCode(), $event->getMessage());
302
            }
303
            if ($event->isStopped()) {
304
                $this->flashHelper->addFlashFromEvent($configuration, $event);
305
306
                return $this->redirectHandler->redirectToResource($configuration, $resource);
307
            }
308
309
            if ($configuration->hasStateMachine()) {
310
                $this->stateMachine->apply($configuration, $resource);
311
            }
312
313
            $this->manager->flush();
314
            $this->eventDispatcher->dispatchPostEvent(ResourceActions::UPDATE, $configuration, $resource);
315
316
            if (!$configuration->isHtmlRequest()) {
317
                return $this->viewHandler->handle($configuration, View::create($resource, 204));
318
            }
319
320
            $this->flashHelper->addSuccessFlash($configuration, ResourceActions::UPDATE, $resource);
321
322
            return $this->redirectHandler->redirectToResource($configuration, $resource);
323
        }
324
325
        if (!$configuration->isHtmlRequest()) {
326
            return $this->viewHandler->handle($configuration, View::create($form, 400));
327
        }
328
329
        $view = View::create()
330
            ->setData([
331
                'configuration' => $configuration,
332
                'metadata' => $this->metadata,
333
                'resource' => $resource,
334
                $this->metadata->getName() => $resource,
335
                'form' => $form->createView(),
336
            ])
337
            ->setTemplate($configuration->getTemplate(ResourceActions::UPDATE . '.html'))
338
        ;
339
340
        return $this->viewHandler->handle($configuration, $view);
341
    }
342
343
    /**
344
     * @param Request $request
345
     *
346
     * @return Response
347
     */
348
    public function deleteAction(Request $request)
349
    {
350
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
351
352
        $this->isGrantedOr403($configuration, ResourceActions::DELETE);
353
        $resource = $this->findOr404($configuration);
354
355
        $event = $this->eventDispatcher->dispatchPreEvent(ResourceActions::DELETE, $configuration, $resource);
356
357
        if ($event->isStopped() && !$configuration->isHtmlRequest()) {
358
            throw new HttpException($event->getErrorCode(), $event->getMessage());
359
        }
360
        if ($event->isStopped()) {
361
            $this->flashHelper->addFlashFromEvent($configuration, $event);
362
363
            return $this->redirectHandler->redirectToIndex($configuration, $resource);
364
        }
365
366
        $this->repository->remove($resource);
367
        $this->eventDispatcher->dispatchPostEvent(ResourceActions::DELETE, $configuration, $resource);
368
369
        if (!$configuration->isHtmlRequest()) {
370
            return $this->viewHandler->handle($configuration, View::create(null, 204));
371
        }
372
373
        $this->flashHelper->addSuccessFlash($configuration, ResourceActions::DELETE, $resource);
374
375
        return $this->redirectHandler->redirectToIndex($configuration, $resource);
376
    }
377
378
    /**
379
     * @param Request $request
380
     *
381
     * @return RedirectResponse
382
     */
383
    public function applyStateMachineTransitionAction(Request $request)
384
    {
385
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
386
387
        $this->isGrantedOr403($configuration, ResourceActions::UPDATE);
388
        $resource = $this->findOr404($configuration);
389
390
        $event = $this->eventDispatcher->dispatchPreEvent(ResourceActions::UPDATE, $configuration, $resource);
391
392
        if ($event->isStopped() && !$configuration->isHtmlRequest()) {
393
            throw new HttpException($event->getErrorCode(), $event->getMessage());
394
        }
395
        if ($event->isStopped()) {
396
            $this->flashHelper->addFlashFromEvent($configuration, $event);
397
398
            return $this->redirectHandler->redirectToResource($configuration, $resource);
399
        }
400
401
        $this->stateMachine->apply($configuration, $resource);
402
        $this->manager->flush();
403
404
        $this->eventDispatcher->dispatchPostEvent(ResourceActions::UPDATE, $configuration, $resource);
405
406
        if (!$configuration->isHtmlRequest()) {
407
            return $this->viewHandler->handle($configuration, View::create($resource, 200));
408
        }
409
410
        $this->flashHelper->addSuccessFlash($configuration, ResourceActions::UPDATE, $resource);
411
412
        return $this->redirectHandler->redirectToResource($configuration, $resource);
413
    }
414
415
    /**
416
     * @param Request $request
417
     *
418
     * @return RedirectResponse
419
     */
420
    public function enableAction(Request $request)
421
    {
422
        return $this->toggle($request, true);
423
    }
424
    /**
425
     * @param Request $request
426
     *
427
     * @return RedirectResponse
428
     */
429
    public function disableAction(Request $request)
430
    {
431
        return $this->toggle($request, false);
432
    }
433
434
    /**
435
     * @param Request $request
436
     * @param $enabled
437
     *
438
     * @return RedirectResponse
439
     */
440
    protected function toggle(Request $request, $enabled)
441
    {
442
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
443
444
        $this->isGrantedOr403($configuration, ResourceActions::UPDATE);
445
446
        $resource = $this->findOr404($configuration);
447
        $resource->setEnabled($enabled);
448
449
        $this->eventDispatcher->dispatchPreEvent(ResourceActions::UPDATE, $configuration, $resource);
450
        $this->manager->flush();
451
        $this->eventDispatcher->dispatchPostEvent(ResourceActions::UPDATE, $configuration, $resource);
452
453
        if (!$configuration->isHtmlRequest()) {
454
            return $this->viewHandler->handle($configuration, View::create($resource, 204));
455
        }
456
457
        $this->flashHelper->addSuccessFlash($configuration, $enabled ? 'enable' : 'disable', $resource);
458
459
        return $this->redirectHandler->redirectToIndex($configuration, $resource);
460
    }
461
462
    /**
463
     * @param Request $request
464
     *
465
     * @return Response
466
     */
467
    public function moveUpAction(Request $request)
468
    {
469
        return $this->move($request, 1);
470
    }
471
472
    /**
473
     * @param Request $request
474
     *
475
     * @return Response
476
     */
477
    public function moveDownAction(Request $request)
478
    {
479
        return $this->move($request, -1);
480
    }
481
482
    /**
483
     * @param Request $request
484
     * @param int $movement
485
     *
486
     * @return RedirectResponse
487
     */
488
    protected function move(Request $request, $movement)
489
    {
490
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
491
        $resource = $this->findOr404($configuration);
492
493
        $position = $configuration->getSortablePosition();
494
        $accessor = PropertyAccess::createPropertyAccessor();
495
        $accessor->setValue(
496
            $resource,
497
            $position,
498
            $accessor->getValue($resource, $position) + $movement
499
        );
500
501
        $this->eventDispatcher->dispatchPreEvent(ResourceActions::UPDATE, $configuration, $resource);
0 ignored issues
show
Documentation introduced by
$resource is of type object|array, but the function expects a object<Sylius\Component\...odel\ResourceInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
502
        $this->manager->flush();
503
        $this->eventDispatcher->dispatchPostEvent(ResourceActions::UPDATE, $configuration, $resource);
0 ignored issues
show
Documentation introduced by
$resource is of type object|array, but the function expects a object<Sylius\Component\...odel\ResourceInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
504
505
        if (!$configuration->isHtmlRequest()) {
506
            return $this->viewHandler->handle($configuration, View::create($resource, 204));
507
        }
508
509
        $this->flashHelper->addSuccessFlash($configuration, 'move', $resource);
0 ignored issues
show
Documentation introduced by
$resource is of type object|array, but the function expects a null|object<Sylius\Compo...odel\ResourceInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
510
511
        return $this->redirectHandler->redirectToIndex($configuration, $resource);
0 ignored issues
show
Documentation introduced by
$resource is of type object|array, but the function expects a null|object<Sylius\Compo...odel\ResourceInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
512
    }
513
514
    /**
515
     * @param RequestConfiguration $configuration
516
     * @param string $permission
517
     *
518
     * @throws AccessDeniedException
519
     */
520
    protected function isGrantedOr403(RequestConfiguration $configuration, $permission)
521
    {
522
        if (!$configuration->hasPermission()) {
523
            return;
524
        }
525
526
        $permission = $configuration->getPermission($permission);
527
528
        if (!$this->authorizationChecker->isGranted($configuration, $permission)) {
529
            throw new AccessDeniedException();
530
        }
531
    }
532
533
    /**
534
     * @param RequestConfiguration $configuration
535
     *
536
     * @return \Sylius\Component\Resource\Model\ResourceInterface
537
     *
538
     * @throws NotFoundHttpException
539
     */
540
    protected function findOr404(RequestConfiguration $configuration)
541
    {
542
        if (null === $resource = $this->singleResourceProvider->get($configuration, $this->repository)) {
543
            throw new NotFoundHttpException();
544
        }
545
546
        return $resource;
547
    }
548
}
549