Completed
Push — master ( 53ec55...6e8d59 )
by Mateusz
18s
created

OrderItemController   B

Complexity

Total Complexity 34

Size/Duplication

Total Lines 271
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 16

Importance

Changes 0
Metric Value
wmc 34
lcom 1
cbo 16
dl 0
loc 271
rs 7.7846
c 0
b 0
f 0

15 Methods

Rating   Name   Duplication   Size   Complexity  
C addAction() 0 74 10
C removeAction() 0 52 9
A getOrderRepository() 0 4 1
A redirectToCartSummary() 0 8 2
A getCartSummaryRoute() 0 4 1
A getCurrentCart() 0 4 1
A getContext() 0 4 1
A createAddToCartCommand() 0 4 1
A getFormFactory() 0 4 1
A getQuantityModifier() 0 4 1
A getOrderModifier() 0 4 1
A getCartManager() 0 4 1
A getCartItemErrors() 0 7 1
A getAddToCartFormWithErrors() 0 8 2
A handleBadAjaxRequestView() 0 7 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
declare(strict_types=1);
13
14
namespace Sylius\Bundle\OrderBundle\Controller;
15
16
use Doctrine\ORM\EntityManagerInterface;
17
use FOS\RestBundle\View\View;
18
use Sylius\Bundle\ResourceBundle\Controller\RequestConfiguration;
19
use Sylius\Bundle\ResourceBundle\Controller\ResourceController;
20
use Sylius\Component\Order\CartActions;
21
use Sylius\Component\Order\Context\CartContextInterface;
22
use Sylius\Component\Order\Model\OrderInterface;
23
use Sylius\Component\Order\Model\OrderItemInterface;
24
use Sylius\Component\Order\Modifier\OrderItemQuantityModifierInterface;
25
use Sylius\Component\Order\Modifier\OrderModifierInterface;
26
use Sylius\Component\Order\Repository\OrderRepositoryInterface;
27
use Symfony\Component\Form\FormError;
28
use Symfony\Component\Form\FormFactoryInterface;
29
use Symfony\Component\Form\FormInterface;
30
use Symfony\Component\HttpFoundation\Request;
31
use Symfony\Component\HttpFoundation\Response;
32
use Symfony\Component\HttpKernel\Exception\HttpException;
33
use Symfony\Component\Validator\ConstraintViolationListInterface;
34
35
class OrderItemController extends ResourceController
36
{
37
    /**
38
     * @param Request $request
39
     *
40
     * @return Response
41
     */
42
    public function addAction(Request $request): Response
43
    {
44
        $cart = $this->getCurrentCart();
45
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
46
47
        $this->isGrantedOr403($configuration, CartActions::ADD);
48
        /** @var OrderItemInterface $orderItem */
49
        $orderItem = $this->newResourceFactory->create($configuration, $this->factory);
50
51
        $this->getQuantityModifier()->modify($orderItem, 1);
52
53
        $form = $this->getFormFactory()->create(
54
            $configuration->getFormType(),
55
            $this->createAddToCartCommand($cart, $orderItem),
56
            $configuration->getFormOptions()
57
        );
58
59
        if ($request->isMethod('POST') && $form->handleRequest($request)->isValid()) {
60
            /** @var AddToCartCommandInterface $addCartItemCommand */
61
            $addToCartCommand = $form->getData();
62
63
            $errors = $this->getCartItemErrors($addToCartCommand->getCartItem());
64
            if (0 < count($errors)) {
65
                $form = $this->getAddToCartFormWithErrors($errors, $form);
66
67
                return $this->handleBadAjaxRequestView($configuration, $form);
68
            }
69
70
            $event = $this->eventDispatcher->dispatchPreEvent(CartActions::ADD, $configuration, $orderItem);
71
72
            if ($event->isStopped() && !$configuration->isHtmlRequest()) {
73
                throw new HttpException($event->getErrorCode(), $event->getMessage());
74
            }
75
            if ($event->isStopped()) {
76
                $this->flashHelper->addFlashFromEvent($configuration, $event);
77
78
                return $this->redirectHandler->redirectToIndex($configuration, $orderItem);
79
            }
80
81
            $this->getOrderModifier()->addToOrder($addToCartCommand->getCart(), $addToCartCommand->getCartItem());
82
83
            $cartManager = $this->getCartManager();
84
            $cartManager->persist($cart);
85
            $cartManager->flush();
86
87
            $resourceControllerEvent = $this->eventDispatcher->dispatchPostEvent(CartActions::ADD, $configuration, $orderItem);
88
            if ($resourceControllerEvent->hasResponse()) {
89
                return $resourceControllerEvent->getResponse();
90
            }
91
92
            $this->flashHelper->addSuccessFlash($configuration, CartActions::ADD, $orderItem);
93
94
            if ($request->isXmlHttpRequest()) {
95
                return $this->viewHandler->handle($configuration, View::create([], Response::HTTP_CREATED));
96
            }
97
98
            return $this->redirectHandler->redirectToResource($configuration, $orderItem);
99
        }
100
101
        if (!$configuration->isHtmlRequest()) {
102
            return $this->handleBadAjaxRequestView($configuration, $form);
103
        }
104
105
        $view = View::create()
106
            ->setData([
107
                'configuration' => $configuration,
108
                $this->metadata->getName() => $orderItem,
109
                'form' => $form->createView(),
110
            ])
111
            ->setTemplate($configuration->getTemplate(CartActions::ADD . '.html'))
112
        ;
113
114
        return $this->viewHandler->handle($configuration, $view);
115
    }
116
117
    /**
118
     * @param Request $request
119
     *
120
     * @return Response
121
     */
122
    public function removeAction(Request $request): Response
123
    {
124
        $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
125
126
        $this->isGrantedOr403($configuration, CartActions::REMOVE);
127
        /** @var OrderItemInterface $orderItem */
128
        $orderItem = $this->findOr404($configuration);
129
130
        $event = $this->eventDispatcher->dispatchPreEvent(CartActions::REMOVE, $configuration, $orderItem);
131
132
        if ($configuration->isCsrfProtectionEnabled() && !$this->isCsrfTokenValid($orderItem->getId(), $request->request->get('_csrf_token'))) {
133
            throw new HttpException(Response::HTTP_FORBIDDEN, 'Invalid csrf token.');
134
        }
135
136
        if ($event->isStopped() && !$configuration->isHtmlRequest()) {
137
            throw new HttpException($event->getErrorCode(), $event->getMessage());
138
        }
139
        if ($event->isStopped()) {
140
            $this->flashHelper->addFlashFromEvent($configuration, $event);
141
142
            return $this->redirectHandler->redirectToIndex($configuration, $orderItem);
143
        }
144
145
        $cart = $this->getCurrentCart();
146
        if ($cart !== $orderItem->getOrder()) {
147
            $this->addFlash('error', $this->get('translator')->trans('sylius.cart.cannot_modify', [], 'flashes'));
148
149
            if (!$configuration->isHtmlRequest()) {
150
                return $this->viewHandler->handle($configuration, View::create(null, Response::HTTP_NO_CONTENT));
151
            }
152
153
            return $this->redirectHandler->redirectToIndex($configuration, $orderItem);
154
        }
155
156
        $this->getOrderModifier()->removeFromOrder($cart, $orderItem);
157
158
        $this->repository->remove($orderItem);
159
160
        $cartManager = $this->getCartManager();
161
        $cartManager->persist($cart);
162
        $cartManager->flush();
163
164
        $this->eventDispatcher->dispatchPostEvent(CartActions::REMOVE, $configuration, $orderItem);
165
166
        if (!$configuration->isHtmlRequest()) {
167
            return $this->viewHandler->handle($configuration, View::create(null, Response::HTTP_NO_CONTENT));
168
        }
169
170
        $this->flashHelper->addSuccessFlash($configuration, CartActions::REMOVE, $orderItem);
171
172
        return $this->redirectHandler->redirectToIndex($configuration, $orderItem);
173
    }
174
175
    /**
176
     * @return OrderRepositoryInterface
177
     */
178
    protected function getOrderRepository(): OrderRepositoryInterface
179
    {
180
        return $this->get('sylius.repository.order');
181
    }
182
183
    /**
184
     * @param RequestConfiguration $configuration
185
     *
186
     * @return Response
187
     */
188
    protected function redirectToCartSummary(RequestConfiguration $configuration): Response
189
    {
190
        if (null === $configuration->getParameters()->get('redirect')) {
191
            return $this->redirectHandler->redirectToRoute($configuration, $this->getCartSummaryRoute());
192
        }
193
194
        return $this->redirectHandler->redirectToRoute($configuration, $configuration->getParameters()->get('redirect'));
195
    }
196
197
    /**
198
     * @return string
199
     */
200
    protected function getCartSummaryRoute(): string
201
    {
202
        return 'sylius_cart_summary';
203
    }
204
205
    /**
206
     * @return OrderInterface
207
     */
208
    protected function getCurrentCart(): OrderInterface
209
    {
210
        return $this->getContext()->getCart();
211
    }
212
213
    /**
214
     * @return CartContextInterface
215
     */
216
    protected function getContext(): CartContextInterface
217
    {
218
        return $this->get('sylius.context.cart');
219
    }
220
221
    /**
222
     * @param OrderInterface $cart
223
     * @param OrderItemInterface $cartItem
224
     *
225
     * @return AddToCartCommandInterface
226
     */
227
    protected function createAddToCartCommand(OrderInterface $cart, OrderItemInterface $cartItem): AddToCartCommandInterface
228
    {
229
        return $this->get('sylius.factory.add_to_cart_command')->createWithCartAndCartItem($cart, $cartItem);
230
    }
231
232
    /**
233
     * @return FormFactoryInterface
234
     */
235
    protected function getFormFactory(): FormFactoryInterface
236
    {
237
        return $this->get('form.factory');
238
    }
239
240
    /**
241
     * @return OrderItemQuantityModifierInterface
242
     */
243
    protected function getQuantityModifier(): OrderItemQuantityModifierInterface
244
    {
245
        return $this->get('sylius.order_item_quantity_modifier');
246
    }
247
248
    /**
249
     * @return OrderModifierInterface
250
     */
251
    protected function getOrderModifier(): OrderModifierInterface
252
    {
253
        return $this->get('sylius.order_modifier');
254
    }
255
256
    /**
257
     * @return EntityManagerInterface
258
     */
259
    protected function getCartManager(): EntityManagerInterface
260
    {
261
        return $this->get('sylius.manager.order');
262
    }
263
264
    /**
265
     * @param OrderItemInterface $orderItem
266
     *
267
     * @return ConstraintViolationListInterface
268
     */
269
    private function getCartItemErrors(OrderItemInterface $orderItem): ConstraintViolationListInterface
270
    {
271
        return $this
272
            ->get('validator')
273
            ->validate($orderItem, null, $this->getParameter('sylius.form.type.order_item.validation_groups'))
274
        ;
275
    }
276
277
    /**
278
     * @param ConstraintViolationListInterface $errors
279
     * @param FormInterface $form
280
     *
281
     * @return FormInterface
282
     */
283
    private function getAddToCartFormWithErrors(ConstraintViolationListInterface $errors, FormInterface $form): FormInterface
284
    {
285
        foreach ($errors as $error) {
286
            $form->get('cartItem')->get($error->getPropertyPath())->addError(new FormError($error->getMessage()));
287
        }
288
289
        return $form;
290
    }
291
292
    /**
293
     * @param RequestConfiguration $configuration
294
     * @param FormInterface $form
295
     *
296
     * @return Response
297
     */
298
    private function handleBadAjaxRequestView(RequestConfiguration $configuration, FormInterface $form): Response
299
    {
300
        return $this->viewHandler->handle(
301
            $configuration,
302
            View::create($form, Response::HTTP_BAD_REQUEST)->setData(['errors' => $form->getErrors(true, true)])
303
        );
304
    }
305
}
306