Completed
Push — master ( 41948a...5bb6bb )
by Łukasz
17:08 queued 13:33
created

CartController   C

Complexity

Total Complexity 28

Size/Duplication

Total Lines 297
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 30

Importance

Changes 0
Metric Value
wmc 28
lcom 1
cbo 30
dl 0
loc 297
rs 5
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A pickupAction() 0 17 2
A summaryAction() 0 18 2
B addAction() 0 41 3
A dropAction() 0 17 2
B changeItemQuantityAction() 0 36 4
B removeItemAction() 0 27 4
A estimateShippingCostAction() 0 49 3
A resolveVariant() 0 21 3
B getVariant() 0 14 5
1
<?php
2
3
namespace Sylius\ShopApiPlugin\Controller;
4
5
use Doctrine\Common\Persistence\ObjectManager;
6
use FOS\RestBundle\View\View;
7
use FOS\RestBundle\View\ViewHandlerInterface;
8
use League\Tactician\CommandBus;
9
use Sylius\Component\Core\Factory\AddressFactoryInterface;
10
use Sylius\Component\Core\Factory\CartItemFactoryInterface;
11
use Sylius\Component\Core\Model\AddressInterface;
12
use Sylius\Component\Core\Model\OrderInterface;
13
use Sylius\Component\Core\Model\OrderItemInterface;
14
use Sylius\Component\Core\Model\ProductInterface;
15
use Sylius\Component\Core\Model\ProductVariantInterface;
16
use Sylius\Component\Core\Model\ShipmentInterface;
17
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
18
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
19
use Sylius\Component\Core\Repository\ProductVariantRepositoryInterface;
20
use Sylius\Component\Order\Modifier\OrderItemQuantityModifierInterface;
21
use Sylius\Component\Order\Processor\OrderProcessorInterface;
22
use Sylius\Component\Order\Repository\OrderItemRepositoryInterface;
23
use Sylius\Component\Registry\ServiceRegistryInterface;
24
use Sylius\Component\Resource\Factory\FactoryInterface;
25
use Sylius\ShopApiPlugin\Factory\CartViewFactoryInterface;
26
use Sylius\Component\Shipping\Exception\UnresolvedDefaultShippingMethodException;
27
use Sylius\Component\Shipping\Resolver\ShippingMethodsResolverInterface;
28
use Sylius\ShopApiPlugin\Factory\PriceViewFactoryInterface;
29
use Sylius\ShopApiPlugin\Command\PickupCart;
30
use Sylius\ShopApiPlugin\View\EstimatedShippingCostView;
31
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
32
use Symfony\Component\HttpFoundation\Request;
33
use Symfony\Component\HttpFoundation\Response;
34
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
35
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
36
37
final class CartController extends Controller
38
{
39
    /**
40
     * @param Request $request
41
     *
42
     * @return Response
43
     */
44
    public function pickupAction(Request $request)
45
    {
46
        /** @var OrderRepositoryInterface $cartRepository */
47
        $cartRepository = $this->get('sylius.repository.order');
48
        /** @var CommandBus $bus */
49
        $bus = $this->get('tactician.commandbus');
50
        /** @var ViewHandlerInterface $viewHandler */
51
        $viewHandler = $this->get('fos_rest.view_handler');
52
53
        if (null !== $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')])) {
54
            throw new BadRequestHttpException('Cart with given token already exists');
55
        }
56
57
        $bus->handle(new PickupCart($request->attributes->get('token'), $request->request->get('channel')));
58
59
        return $viewHandler->handle(View::create(null, Response::HTTP_CREATED));
60
    }
61
62
    /**
63
     * @param Request $request
64
     *
65
     * @return Response
66
     */
67
    public function summaryAction(Request $request)
68
    {
69
        /** @var OrderRepositoryInterface $cartRepository */
70
        $cartRepository = $this->get('sylius.repository.order');
71
        /** @var ViewHandlerInterface $viewHandler */
72
        $viewHandler = $this->get('fos_rest.view_handler');
73
        /** @var CartViewFactoryInterface $cartViewFactory */
74
        $cartViewFactory = $this->get('sylius.shop_api_plugin.factory.cart_view_factory');
75
76
        /** @var OrderInterface $cart */
77
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
78
79
        if (null === $cart) {
80
            throw new NotFoundHttpException('Cart with given id does not exists');
81
        }
82
83
        return $viewHandler->handle(View::create($cartViewFactory->create($cart, $cart->getLocaleCode()), Response::HTTP_OK));
84
    }
85
86
    /**
87
     * @param Request $request
88
     *
89
     * @return Response
90
     */
91
    public function addAction(Request $request)
92
    {
93
        /** @var OrderRepositoryInterface $cartRepository */
94
        $cartRepository = $this->get('sylius.repository.order');
95
        /** @var ObjectManager $cartManager */
96
        $cartManager = $this->get('sylius.manager.order');
97
        /** @var ViewHandlerInterface $viewHandler */
98
        $viewHandler = $this->get('fos_rest.view_handler');
99
        /** @var CartItemFactoryInterface $cartItemFactory */
100
        $cartItemFactory = $this->get('sylius.factory.order_item');
101
        /** @var OrderItemQuantityModifierInterface $orderItemModifier */
102
        $orderItemModifier = $this->get('sylius.order_item_quantity_modifier');
103
        /** @var OrderProcessorInterface $orderProcessor */
104
        $orderProcessor = $this->get('sylius.order_processing.order_processor');
105
106
        /** @var OrderInterface $cart */
107
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
108
109
        if (null === $cart) {
110
            throw new NotFoundHttpException('Cart with given id does not exists');
111
        }
112
113
        $productVariant = $this->resolveVariant($request);
114
115
        if (null === $productVariant) {
116
            throw new NotFoundHttpException('Variant not found for given configuration');
117
        }
118
119
        /** @var OrderItemInterface $cartItem */
120
        $cartItem = $cartItemFactory->createForCart($cart);
121
        $cartItem->setVariant($productVariant);
122
        $orderItemModifier->modify($cartItem, $request->request->getInt('quantity'));
123
124
        $cart->addItem($cartItem);
125
126
        $orderProcessor->process($cart);
127
128
        $cartManager->flush();
129
130
        return $viewHandler->handle(View::create(null, Response::HTTP_CREATED));
131
    }
132
133
    /**
134
     * @param Request $request
135
     *
136
     * @return Response
137
     */
138
    public function dropAction(Request $request)
139
    {
140
        /** @var OrderRepositoryInterface $cartRepository */
141
        $cartRepository = $this->get('sylius.repository.order');
142
        /** @var ViewHandlerInterface $viewHandler */
143
        $viewHandler = $this->get('fos_rest.view_handler');
144
145
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
146
147
        if (null === $cart) {
148
            throw new NotFoundHttpException('Cart with given id does not exists');
149
        }
150
151
        $cartRepository->remove($cart);
152
153
        return $viewHandler->handle(View::create(null, Response::HTTP_NO_CONTENT));
154
    }
155
156
    /**
157
     * @param Request $request
158
     *
159
     * @return Response
160
     */
161
    public function changeItemQuantityAction(Request $request)
162
    {
163
        /** @var ObjectManager $cartManager */
164
        $cartManager = $this->get('sylius.manager.order');
165
        /** @var ViewHandlerInterface $viewHandler */
166
        $viewHandler = $this->get('fos_rest.view_handler');
167
        /** @var OrderItemRepositoryInterface $orderItemRepository */
168
        $cartItemRepository = $this->get('sylius.repository.order_item');
169
        /** @var OrderItemQuantityModifierInterface $orderItemModifier */
170
        $orderItemModifier = $this->get('sylius.order_item_quantity_modifier');
171
        /** @var OrderProcessorInterface $orderProcessor */
172
        $orderProcessor = $this->get('sylius.order_processing.order_processor');
173
        /** @var OrderRepositoryInterface $cartRepository */
174
        $cartRepository = $this->get('sylius.repository.order');
175
176
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
177
178
        if (null === $cart) {
179
            throw new NotFoundHttpException('Cart with given id does not exists');
180
        }
181
182
        /** @var OrderInterface $cart */
183
        $cartItem = $cartItemRepository->find($request->attributes->get('id'));
184
185
        if (null === $cartItem || !$cart->hasItem($cartItem)) {
186
            throw new NotFoundHttpException('Cart item with given id does not exists');
187
        }
188
189
        $orderItemModifier->modify($cartItem, $request->request->getInt('quantity'));
190
191
        $orderProcessor->process($cart);
192
193
        $cartManager->flush();
194
195
        return $viewHandler->handle(View::create(null, Response::HTTP_NO_CONTENT));
196
    }
197
198
    /**
199
     * @param Request $request
200
     *
201
     * @return Response
202
     */
203
    public function removeItemAction(Request $request)
204
    {
205
        /** @var OrderRepositoryInterface $cartRepository */
206
        $cartRepository = $this->get('sylius.repository.order');
207
        /** @var ViewHandlerInterface $viewHandler */
208
        $viewHandler = $this->get('fos_rest.view_handler');
209
        /** @var OrderItemRepositoryInterface $orderItemRepository */
210
        $cartItemRepository = $this->get('sylius.repository.order_item');
211
212
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
213
214
        if (null === $cart) {
215
            throw new NotFoundHttpException('Cart with given id does not exists');
216
        }
217
218
        /** @var OrderInterface $cart */
219
        $cartItem = $cartItemRepository->find($request->attributes->get('id'));
220
221
        if (null === $cartItem || !$cart->hasItem($cartItem)) {
222
            throw new NotFoundHttpException('Cart item with given id does not exists');
223
        }
224
225
        $cart->removeItem($cartItem);
226
        $cartItemRepository->remove($cartItem);
227
228
        return $viewHandler->handle(View::create(null, Response::HTTP_NO_CONTENT));
229
    }
230
231
    /**
232
     * @param Request $request
233
     *
234
     * @return Response
235
     */
236
    public function estimateShippingCostAction(Request $request)
237
    {
238
        /** @var OrderRepositoryInterface $cartRepository */
239
        $cartRepository = $this->get('sylius.repository.order');
240
        /** @var ViewHandlerInterface $viewHandler */
241
        $viewHandler = $this->get('fos_rest.view_handler');
242
        /** @var ShippingMethodsResolverInterface $shippingMethodResolver */
243
        $shippingMethodResolver = $this->get('sylius.shipping_methods_resolver');
244
        /** @var AddressFactoryInterface $addressFactory */
245
        $addressFactory = $this->get('sylius.factory.address');
246
        /** @var FactoryInterface $shipmentFactory */
247
        $shipmentFactory = $this->get('sylius.factory.shipment');
248
        /** @var ServiceRegistryInterface $calculators */
249
        $calculators = $this->get('sylius.registry.shipping_calculator');
250
        /** @var PriceViewFactoryInterface $priceViewFactory */
251
        $priceViewFactory = $this->get('sylius.shop_api_plugin.factory.price_view_factory');
252
253
        /** @var OrderInterface $cart */
254
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
255
256
        if (null === $cart) {
257
            throw new NotFoundHttpException('Cart with given id does not exists');
258
        }
259
260
        /** @var AddressInterface $address */
261
        $address = $addressFactory->createNew();
262
        $address->setCountryCode($request->query->get('countryCode'));
263
        $address->setProvinceCode($request->query->get('provinceCode'));
264
        $cart->setShippingAddress($address);
265
266
        /** @var ShipmentInterface $shipment */
267
        $shipment = $shipmentFactory->createNew();
268
        $shipment->setOrder($cart);
269
270
        $shippingMethods = $shippingMethodResolver->getSupportedMethods($shipment);
271
272
        if (empty($shippingMethods)) {
273
            throw new UnresolvedDefaultShippingMethodException();
274
        }
275
276
        $shippingMethod = $shippingMethods[0];
277
278
        $estimatedShippingCostView = new EstimatedShippingCostView();
279
        $calculator = $calculators->get($shippingMethod->getCalculator());
280
281
        $estimatedShippingCostView->price = $priceViewFactory->create($calculator->calculate($shipment, $shippingMethod->getConfiguration()));
282
283
        return $viewHandler->handle(View::create($estimatedShippingCostView, Response::HTTP_OK));
284
    }
285
286
    /**
287
     * @param Request $request
288
     *
289
     * @return null|ProductVariantInterface
290
     */
291
    private function resolveVariant(Request $request)
292
    {
293
        /** @var ProductRepositoryInterface $productRepository */
294
        $productRepository = $this->get('sylius.repository.product');
295
296
        /** @var ProductInterface $product */
297
        $product = $productRepository->findOneBy(['code' => $request->request->get('productCode')]);
298
299
        if ($product->isSimple()) {
300
            return $product->getVariants()[0];
301
        }
302
303
        if ($product->hasOptions()){
304
            return $this->getVariant($request->request->get('options'), $product);
305
        }
306
307
        /** @var ProductVariantRepositoryInterface $productVariantRepository */
308
        $productVariantRepository = $this->get('sylius.repository.product_variant');
309
310
        return $productVariantRepository->findOneByCodeAndProductCode($request->request->get('variantCode'), $request->request->get('productCode'));
311
    }
312
313
    /**
314
     * @param array $options
315
     * @param ProductInterface $product
316
     *
317
     * @return null|ProductVariantInterface
318
     */
319
    private function getVariant(array $options, ProductInterface $product)
320
    {
321
        foreach ($product->getVariants() as $variant) {
322
            foreach ($variant->getOptionValues() as $optionValue) {
323
                if (!isset($options[$optionValue->getOptionCode()]) || $optionValue->getCode() !== $options[$optionValue->getOptionCode()]) {
324
                    continue 2;
325
                }
326
            }
327
328
            return $variant;
329
        }
330
331
        return null;
332
    }
333
}
334