Completed
Push — master ( b65281...0374b2 )
by Łukasz
02:44
created

CartController::changeItemQuantityAction()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 36
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 36
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 17
nc 3
nop 1
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 Sylius\Component\Channel\Repository\ChannelRepositoryInterface;
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\ChannelInterface;
13
use Sylius\Component\Core\Model\OrderInterface;
14
use Sylius\Component\Core\Model\OrderItemInterface;
15
use Sylius\Component\Core\Model\ProductInterface;
16
use Sylius\Component\Core\Model\ProductVariantInterface;
17
use Sylius\Component\Core\Model\ShipmentInterface;
18
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
19
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
20
use Sylius\Component\Core\Repository\ProductVariantRepositoryInterface;
21
use Sylius\Component\Order\Modifier\OrderItemQuantityModifierInterface;
22
use Sylius\Component\Order\Processor\OrderProcessorInterface;
23
use Sylius\Component\Order\Repository\OrderItemRepositoryInterface;
24
use Sylius\Component\Registry\ServiceRegistryInterface;
25
use Sylius\Component\Resource\Factory\FactoryInterface;
26
use Sylius\ShopApiPlugin\Factory\ImageViewFactoryInterface;
27
use Sylius\Component\Shipping\Exception\UnresolvedDefaultShippingMethodException;
28
use Sylius\Component\Shipping\Resolver\ShippingMethodsResolverInterface;
29
use Sylius\ShopApiPlugin\Factory\PriceViewFactoryInterface;
30
use Sylius\ShopApiPlugin\Factory\ProductVariantViewFactoryInterface;
31
use Sylius\ShopApiPlugin\Factory\ProductViewFactoryInterface;
32
use Sylius\ShopApiPlugin\View\CartSummaryView;
33
use Sylius\ShopApiPlugin\View\EstimatedShippingCostView;
34
use Sylius\ShopApiPlugin\View\ItemView;
35
use Sylius\ShopApiPlugin\View\TotalsView;
36
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
37
use Symfony\Component\HttpFoundation\Request;
38
use Symfony\Component\HttpFoundation\Response;
39
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
40
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
41
42
final class CartController extends Controller
43
{
44
    /**
45
     * @param Request $request
46
     *
47
     * @return Response
48
     */
49
    public function pickupAction(Request $request)
50
    {
51
        /** @var FactoryInterface $cartFactory */
52
        $cartFactory = $this->get('sylius.factory.order');
53
        /** @var OrderRepositoryInterface $cartRepository */
54
        $cartRepository = $this->get('sylius.repository.order');
55
        /** @var ChannelRepositoryInterface $channelRepository */
56
        $channelRepository = $this->get('sylius.repository.channel');
57
        /** @var ViewHandlerInterface $viewHandler */
58
        $viewHandler = $this->get('fos_rest.view_handler');
59
60
        if (null !== $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')])) {
61
            throw new BadRequestHttpException('Cart with given token already exists');
62
        }
63
64
        /** @var ChannelInterface $channel */
65
        $channel = $channelRepository->findOneByCode($request->request->get('channel'));
66
67
        /** @var OrderInterface $cart */
68
        $cart = $cartFactory->createNew();
69
        $cart->setChannel($channel);
70
        $cart->setCurrencyCode($channel->getBaseCurrency()->getCode());
71
        $cart->setLocaleCode($channel->getDefaultLocale()->getCode());
72
        $cart->setTokenValue($request->attributes->get('token'));
73
74
        $cartRepository->add($cart);
75
76
        return $viewHandler->handle(View::create(null, Response::HTTP_CREATED));
77
    }
78
79
    /**
80
     * @param Request $request
81
     *
82
     * @return Response
83
     */
84
    public function summaryAction(Request $request)
85
    {
86
        /** @var OrderRepositoryInterface $cartRepository */
87
        $cartRepository = $this->get('sylius.repository.order');
88
        /** @var ViewHandlerInterface $viewHandler */
89
        $viewHandler = $this->get('fos_rest.view_handler');
90
        /** @var ProductViewFactoryInterface $productViewFactory */
91
        $productViewFactory = $this->get('sylius.shop_api_plugin.factory.product_view_factory');
92
        /** @var ProductVariantViewFactoryInterface $productViewViewFactory */
93
        $productViewViewFactory = $this->get('sylius.shop_api_plugin.factory.product_variant_view_factory');
94
95
        /** @var OrderInterface $cart */
96
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
97
98
        if (null === $cart) {
99
            throw new NotFoundHttpException('Cart with given id does not exists');
100
        }
101
102
        $locale = $cart->getLocaleCode();
103
104
        $cartView = new CartSummaryView();
105
        $cartView->channel = $cart->getChannel()->getCode();
106
        $cartView->currency = $cart->getCurrencyCode();
107
        $cartView->locale = $locale;
108
        $cartView->checkoutState = $cart->getCheckoutState();
109
        $cartView->tokenValue = $cart->getTokenValue();
110
        $cartView->totals = new TotalsView();
111
        $cartView->totals->promotion = 0;
112
        $cartView->totals->items = $cart->getItemsTotal();
113
        $cartView->totals->shipping = $cart->getShippingTotal();
114
        $cartView->totals->taxes = $cart->getTaxTotal();
115
116
        /** @var OrderItemInterface $item */
117
        foreach ($cart->getItems() as $item) {
118
            $itemView = new ItemView();
119
            $product = $item->getProduct();
120
121
            $itemView->id = $item->getId();
122
            $itemView->quantity = $item->getQuantity();
123
            $itemView->total = $item->getTotal();
124
            $itemView->product = $productViewFactory->create($product, $locale);
125
            $itemView->product->variants = [$productViewViewFactory->create($item->getVariant(), $cart->getChannel(), $locale)];
0 ignored issues
show
Compatibility introduced by
$cart->getChannel() of type object<Sylius\Component\...Model\ChannelInterface> is not a sub-type of object<Sylius\Component\...Model\ChannelInterface>. It seems like you assume a child interface of the interface Sylius\Component\Channel\Model\ChannelInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
126
127
            $cartView->items[] = $itemView;
128
        }
129
130
        return $viewHandler->handle(View::create($cartView, Response::HTTP_OK));
131
    }
132
133
    /**
134
     * @param Request $request
135
     *
136
     * @return Response
137
     */
138
    public function addAction(Request $request)
139
    {
140
        /** @var OrderRepositoryInterface $cartRepository */
141
        $cartRepository = $this->get('sylius.repository.order');
142
        /** @var ObjectManager $cartManager */
143
        $cartManager = $this->get('sylius.manager.order');
144
        /** @var ViewHandlerInterface $viewHandler */
145
        $viewHandler = $this->get('fos_rest.view_handler');
146
        /** @var CartItemFactoryInterface $cartItemFactory */
147
        $cartItemFactory = $this->get('sylius.factory.order_item');
148
        /** @var OrderItemQuantityModifierInterface $orderItemModifier */
149
        $orderItemModifier = $this->get('sylius.order_item_quantity_modifier');
150
        /** @var OrderProcessorInterface $orderProcessor */
151
        $orderProcessor = $this->get('sylius.order_processing.order_processor');
152
153
        /** @var OrderInterface $cart */
154
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
155
156
        if (null === $cart) {
157
            throw new NotFoundHttpException('Cart with given id does not exists');
158
        }
159
160
        $productVariant = $this->resolveVariant($request);
161
162
        if (null === $productVariant) {
163
            throw new NotFoundHttpException('Variant not found for given configuration');
164
        }
165
166
        /** @var OrderItemInterface $cartItem */
167
        $cartItem = $cartItemFactory->createForCart($cart);
168
        $cartItem->setVariant($productVariant);
169
        $orderItemModifier->modify($cartItem, $request->request->getInt('quantity'));
170
171
        $cart->addItem($cartItem);
172
173
        $orderProcessor->process($cart);
174
175
        $cartManager->flush();
176
177
        return $viewHandler->handle(View::create(null, Response::HTTP_CREATED));
178
    }
179
180
    /**
181
     * @param Request $request
182
     *
183
     * @return Response
184
     */
185
    public function dropAction(Request $request)
186
    {
187
        /** @var OrderRepositoryInterface $cartRepository */
188
        $cartRepository = $this->get('sylius.repository.order');
189
        /** @var ViewHandlerInterface $viewHandler */
190
        $viewHandler = $this->get('fos_rest.view_handler');
191
192
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
193
194
        if (null === $cart) {
195
            throw new NotFoundHttpException('Cart with given id does not exists');
196
        }
197
198
        $cartRepository->remove($cart);
199
200
        return $viewHandler->handle(View::create(null, Response::HTTP_NO_CONTENT));
201
    }
202
203
    /**
204
     * @param Request $request
205
     *
206
     * @return Response
207
     */
208
    public function changeItemQuantityAction(Request $request)
209
    {
210
        /** @var ObjectManager $cartManager */
211
        $cartManager = $this->get('sylius.manager.order');
212
        /** @var ViewHandlerInterface $viewHandler */
213
        $viewHandler = $this->get('fos_rest.view_handler');
214
        /** @var OrderItemRepositoryInterface $orderItemRepository */
215
        $cartItemRepository = $this->get('sylius.repository.order_item');
216
        /** @var OrderItemQuantityModifierInterface $orderItemModifier */
217
        $orderItemModifier = $this->get('sylius.order_item_quantity_modifier');
218
        /** @var OrderProcessorInterface $orderProcessor */
219
        $orderProcessor = $this->get('sylius.order_processing.order_processor');
220
        /** @var OrderRepositoryInterface $cartRepository */
221
        $cartRepository = $this->get('sylius.repository.order');
222
223
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
224
225
        if (null === $cart) {
226
            throw new NotFoundHttpException('Cart with given id does not exists');
227
        }
228
229
        /** @var OrderInterface $cart */
230
        $cartItem = $cartItemRepository->find($request->attributes->get('id'));
231
232
        if (null === $cartItem || !$cart->hasItem($cartItem)) {
233
            throw new NotFoundHttpException('Cart item with given id does not exists');
234
        }
235
236
        $orderItemModifier->modify($cartItem, $request->request->getInt('quantity'));
237
238
        $orderProcessor->process($cart);
239
240
        $cartManager->flush();
241
242
        return $viewHandler->handle(View::create(null, Response::HTTP_NO_CONTENT));
243
    }
244
245
    /**
246
     * @param Request $request
247
     *
248
     * @return Response
249
     */
250
    public function removeItemAction(Request $request)
251
    {
252
        /** @var OrderRepositoryInterface $cartRepository */
253
        $cartRepository = $this->get('sylius.repository.order');
254
        /** @var ViewHandlerInterface $viewHandler */
255
        $viewHandler = $this->get('fos_rest.view_handler');
256
        /** @var OrderItemRepositoryInterface $orderItemRepository */
257
        $cartItemRepository = $this->get('sylius.repository.order_item');
258
259
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
260
261
        if (null === $cart) {
262
            throw new NotFoundHttpException('Cart with given id does not exists');
263
        }
264
265
        /** @var OrderInterface $cart */
266
        $cartItem = $cartItemRepository->find($request->attributes->get('id'));
267
268
        if (null === $cartItem || !$cart->hasItem($cartItem)) {
269
            throw new NotFoundHttpException('Cart item with given id does not exists');
270
        }
271
272
        $cart->removeItem($cartItem);
273
        $cartItemRepository->remove($cartItem);
274
275
        return $viewHandler->handle(View::create(null, Response::HTTP_NO_CONTENT));
276
    }
277
278
    /**
279
     * @param Request $request
280
     *
281
     * @return Response
282
     */
283
    public function estimateShippingCostAction(Request $request)
284
    {
285
        /** @var OrderRepositoryInterface $cartRepository */
286
        $cartRepository = $this->get('sylius.repository.order');
287
        /** @var ViewHandlerInterface $viewHandler */
288
        $viewHandler = $this->get('fos_rest.view_handler');
289
        /** @var ShippingMethodsResolverInterface $shippingMethodResolver */
290
        $shippingMethodResolver = $this->get('sylius.shipping_methods_resolver');
291
        /** @var AddressFactoryInterface $addressFactory */
292
        $addressFactory = $this->get('sylius.factory.address');
293
        /** @var FactoryInterface $shipmentFactory */
294
        $shipmentFactory = $this->get('sylius.factory.shipment');
295
        /** @var ServiceRegistryInterface $calculators */
296
        $calculators = $this->get('sylius.registry.shipping_calculator');
297
        /** @var PriceViewFactoryInterface $priceViewFactory */
298
        $priceViewFactory = $this->get('sylius.shop_api_plugin.factory.price_view_factory');
299
300
        /** @var OrderInterface $cart */
301
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
302
303
        if (null === $cart) {
304
            throw new NotFoundHttpException('Cart with given id does not exists');
305
        }
306
307
        /** @var AddressInterface $address */
308
        $address = $addressFactory->createNew();
309
        $address->setCountryCode($request->query->get('countryCode'));
310
        $address->setProvinceCode($request->query->get('provinceCode'));
311
        $cart->setShippingAddress($address);
312
313
        /** @var ShipmentInterface $shipment */
314
        $shipment = $shipmentFactory->createNew();
315
        $shipment->setOrder($cart);
316
317
        $shippingMethods = $shippingMethodResolver->getSupportedMethods($shipment);
318
319
        if (empty($shippingMethods)) {
320
            throw new UnresolvedDefaultShippingMethodException();
321
        }
322
323
        $shippingMethod = $shippingMethods[0];
324
325
        $estimatedShippingCostView = new EstimatedShippingCostView();
326
        $calculator = $calculators->get($shippingMethod->getCalculator());
327
328
        $estimatedShippingCostView->price = $priceViewFactory->create($calculator->calculate($shipment, $shippingMethod->getConfiguration()));
329
330
        return $viewHandler->handle(View::create($estimatedShippingCostView, Response::HTTP_OK));
331
    }
332
333
    /**
334
     * @param Request $request
335
     *
336
     * @return null|ProductVariantInterface
337
     */
338
    private function resolveVariant(Request $request)
339
    {
340
        /** @var ProductRepositoryInterface $productRepository */
341
        $productRepository = $this->get('sylius.repository.product');
342
343
        /** @var ProductInterface $product */
344
        $product = $productRepository->findOneBy(['code' => $request->request->get('productCode')]);
345
346
        if ($product->isSimple()) {
347
            return $product->getVariants()[0];
348
        }
349
350
        if ($product->hasOptions()){
351
            return $this->getVariant($request->request->get('options'), $product);
352
        }
353
354
        /** @var ProductVariantRepositoryInterface $productVariantRepository */
355
        $productVariantRepository = $this->get('sylius.repository.product_variant');
356
357
        return $productVariantRepository->findOneByCodeAndProductCode($request->request->get('variantCode'), $request->request->get('productCode'));
358
    }
359
360
    /**
361
     * @param array $options
362
     * @param ProductInterface $product
363
     *
364
     * @return null|ProductVariantInterface
365
     */
366
    private function getVariant(array $options, ProductInterface $product)
367
    {
368
        foreach ($product->getVariants() as $variant) {
369
            foreach ($variant->getOptionValues() as $optionValue) {
370
                if (!isset($options[$optionValue->getOptionCode()]) || $optionValue->getCode() !== $options[$optionValue->getOptionCode()]) {
371
                    continue 2;
372
                }
373
            }
374
375
            return $variant;
376
        }
377
378
        return null;
379
    }
380
}
381