Completed
Pull Request — master (#133)
by Łukasz
07:03 queued 04:08
created

CartController::dropAction()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 17
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
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 Sylius\Component\Core\Factory\AddressFactoryInterface;
9
use Sylius\Component\Core\Factory\CartItemFactoryInterface;
10
use Sylius\Component\Core\Model\AddressInterface;
11
use Sylius\Component\Core\Model\OrderInterface;
12
use Sylius\Component\Core\Model\OrderItemInterface;
13
use Sylius\Component\Core\Model\ProductInterface;
14
use Sylius\Component\Core\Model\ProductVariantInterface;
15
use Sylius\Component\Core\Model\ShipmentInterface;
16
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
17
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
18
use Sylius\Component\Core\Repository\ProductVariantRepositoryInterface;
19
use Sylius\Component\Order\Modifier\OrderItemQuantityModifierInterface;
20
use Sylius\Component\Order\Processor\OrderProcessorInterface;
21
use Sylius\Component\Order\Repository\OrderItemRepositoryInterface;
22
use Sylius\Component\Registry\ServiceRegistryInterface;
23
use Sylius\Component\Resource\Factory\FactoryInterface;
24
use Sylius\Component\Shipping\Exception\UnresolvedDefaultShippingMethodException;
25
use Sylius\Component\Shipping\Resolver\ShippingMethodsResolverInterface;
26
use Sylius\ShopApiPlugin\Factory\PriceViewFactoryInterface;
27
use Sylius\ShopApiPlugin\View\EstimatedShippingCostView;
28
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
29
use Symfony\Component\HttpFoundation\Request;
30
use Symfony\Component\HttpFoundation\Response;
31
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
32
33
final class CartController extends Controller
34
{
35
    /**
36
     * @param Request $request
37
     *
38
     * @return Response
39
     */
40
    public function addAction(Request $request)
41
    {
42
        /** @var OrderRepositoryInterface $cartRepository */
43
        $cartRepository = $this->get('sylius.repository.order');
44
        /** @var ObjectManager $cartManager */
45
        $cartManager = $this->get('sylius.manager.order');
46
        /** @var ViewHandlerInterface $viewHandler */
47
        $viewHandler = $this->get('fos_rest.view_handler');
48
        /** @var CartItemFactoryInterface $cartItemFactory */
49
        $cartItemFactory = $this->get('sylius.factory.order_item');
50
        /** @var OrderItemQuantityModifierInterface $orderItemModifier */
51
        $orderItemModifier = $this->get('sylius.order_item_quantity_modifier');
52
        /** @var OrderProcessorInterface $orderProcessor */
53
        $orderProcessor = $this->get('sylius.order_processing.order_processor');
54
55
        /** @var OrderInterface $cart */
56
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
57
58
        if (null === $cart) {
59
            throw new NotFoundHttpException('Cart with given id does not exists');
60
        }
61
62
        $productVariant = $this->resolveVariant($request);
63
64
        if (null === $productVariant) {
65
            throw new NotFoundHttpException('Variant not found for given configuration');
66
        }
67
68
        /** @var OrderItemInterface $cartItem */
69
        $cartItem = $cartItemFactory->createForCart($cart);
70
        $cartItem->setVariant($productVariant);
71
        $orderItemModifier->modify($cartItem, $request->request->getInt('quantity'));
72
73
        $cart->addItem($cartItem);
74
75
        $orderProcessor->process($cart);
76
77
        $cartManager->flush();
78
79
        return $viewHandler->handle(View::create(null, Response::HTTP_CREATED));
80
    }
81
82
    /**
83
     * @param Request $request
84
     *
85
     * @return Response
86
     */
87
    public function changeItemQuantityAction(Request $request)
88
    {
89
        /** @var ObjectManager $cartManager */
90
        $cartManager = $this->get('sylius.manager.order');
91
        /** @var ViewHandlerInterface $viewHandler */
92
        $viewHandler = $this->get('fos_rest.view_handler');
93
        /** @var OrderItemRepositoryInterface $orderItemRepository */
94
        $cartItemRepository = $this->get('sylius.repository.order_item');
95
        /** @var OrderItemQuantityModifierInterface $orderItemModifier */
96
        $orderItemModifier = $this->get('sylius.order_item_quantity_modifier');
97
        /** @var OrderProcessorInterface $orderProcessor */
98
        $orderProcessor = $this->get('sylius.order_processing.order_processor');
99
        /** @var OrderRepositoryInterface $cartRepository */
100
        $cartRepository = $this->get('sylius.repository.order');
101
102
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
103
104
        if (null === $cart) {
105
            throw new NotFoundHttpException('Cart with given id does not exists');
106
        }
107
108
        /** @var OrderInterface $cart */
109
        $cartItem = $cartItemRepository->find($request->attributes->get('id'));
110
111
        if (null === $cartItem || !$cart->hasItem($cartItem)) {
112
            throw new NotFoundHttpException('Cart item with given id does not exists');
113
        }
114
115
        $orderItemModifier->modify($cartItem, $request->request->getInt('quantity'));
116
117
        $orderProcessor->process($cart);
118
119
        $cartManager->flush();
120
121
        return $viewHandler->handle(View::create(null, Response::HTTP_NO_CONTENT));
122
    }
123
124
    /**
125
     * @param Request $request
126
     *
127
     * @return Response
128
     */
129
    public function removeItemAction(Request $request)
130
    {
131
        /** @var OrderRepositoryInterface $cartRepository */
132
        $cartRepository = $this->get('sylius.repository.order');
133
        /** @var ViewHandlerInterface $viewHandler */
134
        $viewHandler = $this->get('fos_rest.view_handler');
135
        /** @var OrderItemRepositoryInterface $orderItemRepository */
136
        $cartItemRepository = $this->get('sylius.repository.order_item');
137
138
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
139
140
        if (null === $cart) {
141
            throw new NotFoundHttpException('Cart with given id does not exists');
142
        }
143
144
        /** @var OrderInterface $cart */
145
        $cartItem = $cartItemRepository->find($request->attributes->get('id'));
146
147
        if (null === $cartItem || !$cart->hasItem($cartItem)) {
148
            throw new NotFoundHttpException('Cart item with given id does not exists');
149
        }
150
151
        $cart->removeItem($cartItem);
152
        $cartItemRepository->remove($cartItem);
153
154
        return $viewHandler->handle(View::create(null, Response::HTTP_NO_CONTENT));
155
    }
156
157
    /**
158
     * @param Request $request
159
     *
160
     * @return Response
161
     */
162
    public function estimateShippingCostAction(Request $request)
163
    {
164
        /** @var OrderRepositoryInterface $cartRepository */
165
        $cartRepository = $this->get('sylius.repository.order');
166
        /** @var ViewHandlerInterface $viewHandler */
167
        $viewHandler = $this->get('fos_rest.view_handler');
168
        /** @var ShippingMethodsResolverInterface $shippingMethodResolver */
169
        $shippingMethodResolver = $this->get('sylius.shipping_methods_resolver');
170
        /** @var AddressFactoryInterface $addressFactory */
171
        $addressFactory = $this->get('sylius.factory.address');
172
        /** @var FactoryInterface $shipmentFactory */
173
        $shipmentFactory = $this->get('sylius.factory.shipment');
174
        /** @var ServiceRegistryInterface $calculators */
175
        $calculators = $this->get('sylius.registry.shipping_calculator');
176
        /** @var PriceViewFactoryInterface $priceViewFactory */
177
        $priceViewFactory = $this->get('sylius.shop_api_plugin.factory.price_view_factory');
178
179
        /** @var OrderInterface $cart */
180
        $cart = $cartRepository->findOneBy(['tokenValue' => $request->attributes->get('token')]);
181
182
        if (null === $cart) {
183
            throw new NotFoundHttpException('Cart with given id does not exists');
184
        }
185
186
        /** @var AddressInterface $address */
187
        $address = $addressFactory->createNew();
188
        $address->setCountryCode($request->query->get('countryCode'));
189
        $address->setProvinceCode($request->query->get('provinceCode'));
190
        $cart->setShippingAddress($address);
191
192
        /** @var ShipmentInterface $shipment */
193
        $shipment = $shipmentFactory->createNew();
194
        $shipment->setOrder($cart);
195
196
        $shippingMethods = $shippingMethodResolver->getSupportedMethods($shipment);
197
198
        if (empty($shippingMethods)) {
199
            throw new UnresolvedDefaultShippingMethodException();
200
        }
201
202
        $shippingMethod = $shippingMethods[0];
203
204
        $estimatedShippingCostView = new EstimatedShippingCostView();
205
        $calculator = $calculators->get($shippingMethod->getCalculator());
206
207
        $estimatedShippingCostView->price = $priceViewFactory->create($calculator->calculate($shipment, $shippingMethod->getConfiguration()));
208
209
        return $viewHandler->handle(View::create($estimatedShippingCostView, Response::HTTP_OK));
210
    }
211
212
    /**
213
     * @param Request $request
214
     *
215
     * @return null|ProductVariantInterface
216
     */
217
    private function resolveVariant(Request $request)
218
    {
219
        /** @var ProductRepositoryInterface $productRepository */
220
        $productRepository = $this->get('sylius.repository.product');
221
222
        /** @var ProductInterface $product */
223
        $product = $productRepository->findOneBy(['code' => $request->request->get('productCode')]);
224
225
        if ($product->isSimple()) {
226
            return $product->getVariants()[0];
227
        }
228
229
        if ($product->hasOptions()){
230
            return $this->getVariant($request->request->get('options'), $product);
231
        }
232
233
        /** @var ProductVariantRepositoryInterface $productVariantRepository */
234
        $productVariantRepository = $this->get('sylius.repository.product_variant');
235
236
        return $productVariantRepository->findOneByCodeAndProductCode($request->request->get('variantCode'), $request->request->get('productCode'));
237
    }
238
239
    /**
240
     * @param array $options
241
     * @param ProductInterface $product
242
     *
243
     * @return null|ProductVariantInterface
244
     */
245
    private function getVariant(array $options, ProductInterface $product)
246
    {
247
        foreach ($product->getVariants() as $variant) {
248
            foreach ($variant->getOptionValues() as $optionValue) {
249
                if (!isset($options[$optionValue->getOptionCode()]) || $optionValue->getCode() !== $options[$optionValue->getOptionCode()]) {
250
                    continue 2;
251
                }
252
            }
253
254
            return $variant;
255
        }
256
257
        return null;
258
    }
259
}
260