Completed
Push — master ( 4daa28...c9e675 )
by Paweł
10s
created

CartController::summaryAction()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 8
nc 2
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 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 addAction(Request $request)
68
    {
69
        /** @var OrderRepositoryInterface $cartRepository */
70
        $cartRepository = $this->get('sylius.repository.order');
71
        /** @var ObjectManager $cartManager */
72
        $cartManager = $this->get('sylius.manager.order');
73
        /** @var ViewHandlerInterface $viewHandler */
74
        $viewHandler = $this->get('fos_rest.view_handler');
75
        /** @var CartItemFactoryInterface $cartItemFactory */
76
        $cartItemFactory = $this->get('sylius.factory.order_item');
77
        /** @var OrderItemQuantityModifierInterface $orderItemModifier */
78
        $orderItemModifier = $this->get('sylius.order_item_quantity_modifier');
79
        /** @var OrderProcessorInterface $orderProcessor */
80
        $orderProcessor = $this->get('sylius.order_processing.order_processor');
81
82
        /** @var OrderInterface $cart */
83
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
84
85
        if (null === $cart) {
86
            throw new NotFoundHttpException('Cart with given id does not exists');
87
        }
88
89
        $productVariant = $this->resolveVariant($request);
90
91
        if (null === $productVariant) {
92
            throw new NotFoundHttpException('Variant not found for given configuration');
93
        }
94
95
        /** @var OrderItemInterface $cartItem */
96
        $cartItem = $cartItemFactory->createForCart($cart);
97
        $cartItem->setVariant($productVariant);
98
        $orderItemModifier->modify($cartItem, $request->request->getInt('quantity'));
99
100
        $cart->addItem($cartItem);
101
102
        $orderProcessor->process($cart);
103
104
        $cartManager->flush();
105
106
        return $viewHandler->handle(View::create(null, Response::HTTP_CREATED));
107
    }
108
109
    /**
110
     * @param Request $request
111
     *
112
     * @return Response
113
     */
114
    public function dropAction(Request $request)
115
    {
116
        /** @var OrderRepositoryInterface $cartRepository */
117
        $cartRepository = $this->get('sylius.repository.order');
118
        /** @var ViewHandlerInterface $viewHandler */
119
        $viewHandler = $this->get('fos_rest.view_handler');
120
121
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
122
123
        if (null === $cart) {
124
            throw new NotFoundHttpException('Cart with given id does not exists');
125
        }
126
127
        $cartRepository->remove($cart);
128
129
        return $viewHandler->handle(View::create(null, Response::HTTP_NO_CONTENT));
130
    }
131
132
    /**
133
     * @param Request $request
134
     *
135
     * @return Response
136
     */
137
    public function changeItemQuantityAction(Request $request)
138
    {
139
        /** @var ObjectManager $cartManager */
140
        $cartManager = $this->get('sylius.manager.order');
141
        /** @var ViewHandlerInterface $viewHandler */
142
        $viewHandler = $this->get('fos_rest.view_handler');
143
        /** @var OrderItemRepositoryInterface $orderItemRepository */
144
        $cartItemRepository = $this->get('sylius.repository.order_item');
145
        /** @var OrderItemQuantityModifierInterface $orderItemModifier */
146
        $orderItemModifier = $this->get('sylius.order_item_quantity_modifier');
147
        /** @var OrderProcessorInterface $orderProcessor */
148
        $orderProcessor = $this->get('sylius.order_processing.order_processor');
149
        /** @var OrderRepositoryInterface $cartRepository */
150
        $cartRepository = $this->get('sylius.repository.order');
151
152
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
153
154
        if (null === $cart) {
155
            throw new NotFoundHttpException('Cart with given id does not exists');
156
        }
157
158
        /** @var OrderInterface $cart */
159
        $cartItem = $cartItemRepository->find($request->attributes->get('id'));
160
161
        if (null === $cartItem || !$cart->hasItem($cartItem)) {
162
            throw new NotFoundHttpException('Cart item with given id does not exists');
163
        }
164
165
        $orderItemModifier->modify($cartItem, $request->request->getInt('quantity'));
166
167
        $orderProcessor->process($cart);
168
169
        $cartManager->flush();
170
171
        return $viewHandler->handle(View::create(null, Response::HTTP_NO_CONTENT));
172
    }
173
174
    /**
175
     * @param Request $request
176
     *
177
     * @return Response
178
     */
179
    public function removeItemAction(Request $request)
180
    {
181
        /** @var OrderRepositoryInterface $cartRepository */
182
        $cartRepository = $this->get('sylius.repository.order');
183
        /** @var ViewHandlerInterface $viewHandler */
184
        $viewHandler = $this->get('fos_rest.view_handler');
185
        /** @var OrderItemRepositoryInterface $orderItemRepository */
186
        $cartItemRepository = $this->get('sylius.repository.order_item');
187
188
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
189
190
        if (null === $cart) {
191
            throw new NotFoundHttpException('Cart with given id does not exists');
192
        }
193
194
        /** @var OrderInterface $cart */
195
        $cartItem = $cartItemRepository->find($request->attributes->get('id'));
196
197
        if (null === $cartItem || !$cart->hasItem($cartItem)) {
198
            throw new NotFoundHttpException('Cart item with given id does not exists');
199
        }
200
201
        $cart->removeItem($cartItem);
202
        $cartItemRepository->remove($cartItem);
203
204
        return $viewHandler->handle(View::create(null, Response::HTTP_NO_CONTENT));
205
    }
206
207
    /**
208
     * @param Request $request
209
     *
210
     * @return Response
211
     */
212
    public function estimateShippingCostAction(Request $request)
213
    {
214
        /** @var OrderRepositoryInterface $cartRepository */
215
        $cartRepository = $this->get('sylius.repository.order');
216
        /** @var ViewHandlerInterface $viewHandler */
217
        $viewHandler = $this->get('fos_rest.view_handler');
218
        /** @var ShippingMethodsResolverInterface $shippingMethodResolver */
219
        $shippingMethodResolver = $this->get('sylius.shipping_methods_resolver');
220
        /** @var AddressFactoryInterface $addressFactory */
221
        $addressFactory = $this->get('sylius.factory.address');
222
        /** @var FactoryInterface $shipmentFactory */
223
        $shipmentFactory = $this->get('sylius.factory.shipment');
224
        /** @var ServiceRegistryInterface $calculators */
225
        $calculators = $this->get('sylius.registry.shipping_calculator');
226
        /** @var PriceViewFactoryInterface $priceViewFactory */
227
        $priceViewFactory = $this->get('sylius.shop_api_plugin.factory.price_view_factory');
228
229
        /** @var OrderInterface $cart */
230
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
231
232
        if (null === $cart) {
233
            throw new NotFoundHttpException('Cart with given id does not exists');
234
        }
235
236
        /** @var AddressInterface $address */
237
        $address = $addressFactory->createNew();
238
        $address->setCountryCode($request->query->get('countryCode'));
239
        $address->setProvinceCode($request->query->get('provinceCode'));
240
        $cart->setShippingAddress($address);
241
242
        /** @var ShipmentInterface $shipment */
243
        $shipment = $shipmentFactory->createNew();
244
        $shipment->setOrder($cart);
245
246
        $shippingMethods = $shippingMethodResolver->getSupportedMethods($shipment);
247
248
        if (empty($shippingMethods)) {
249
            throw new UnresolvedDefaultShippingMethodException();
250
        }
251
252
        $shippingMethod = $shippingMethods[0];
253
254
        $estimatedShippingCostView = new EstimatedShippingCostView();
255
        $calculator = $calculators->get($shippingMethod->getCalculator());
256
257
        $estimatedShippingCostView->price = $priceViewFactory->create($calculator->calculate($shipment, $shippingMethod->getConfiguration()));
258
259
        return $viewHandler->handle(View::create($estimatedShippingCostView, Response::HTTP_OK));
260
    }
261
262
    /**
263
     * @param Request $request
264
     *
265
     * @return null|ProductVariantInterface
266
     */
267
    private function resolveVariant(Request $request)
268
    {
269
        /** @var ProductRepositoryInterface $productRepository */
270
        $productRepository = $this->get('sylius.repository.product');
271
272
        /** @var ProductInterface $product */
273
        $product = $productRepository->findOneBy(['code' => $request->request->get('productCode')]);
274
275
        if ($product->isSimple()) {
276
            return $product->getVariants()[0];
277
        }
278
279
        if ($product->hasOptions()){
280
            return $this->getVariant($request->request->get('options'), $product);
281
        }
282
283
        /** @var ProductVariantRepositoryInterface $productVariantRepository */
284
        $productVariantRepository = $this->get('sylius.repository.product_variant');
285
286
        return $productVariantRepository->findOneByCodeAndProductCode($request->request->get('variantCode'), $request->request->get('productCode'));
287
    }
288
289
    /**
290
     * @param array $options
291
     * @param ProductInterface $product
292
     *
293
     * @return null|ProductVariantInterface
294
     */
295
    private function getVariant(array $options, ProductInterface $product)
296
    {
297
        foreach ($product->getVariants() as $variant) {
298
            foreach ($variant->getOptionValues() as $optionValue) {
299
                if (!isset($options[$optionValue->getOptionCode()]) || $optionValue->getCode() !== $options[$optionValue->getOptionCode()]) {
300
                    continue 2;
301
                }
302
            }
303
304
            return $variant;
305
        }
306
307
        return null;
308
    }
309
}
310