PutItemsToCartAction::provideCommandRequest()   B
last analyzed

Complexity

Conditions 7
Paths 4

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
rs 8.8333
c 0
b 0
f 0
cc 7
nc 4
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Sylius\ShopApiPlugin\Controller\Cart;
6
7
use FOS\RestBundle\View\View;
8
use FOS\RestBundle\View\ViewHandlerInterface;
9
use League\Tactician\CommandBus;
10
use Sylius\ShopApiPlugin\Request\PutOptionBasedConfigurableItemToCartRequest;
11
use Sylius\ShopApiPlugin\Request\PutSimpleItemToCartRequest;
12
use Sylius\ShopApiPlugin\Request\PutVariantBasedConfigurableItemToCartRequest;
13
use Sylius\ShopApiPlugin\View\ValidationErrorView;
14
use Sylius\ShopApiPlugin\ViewRepository\CartViewRepositoryInterface;
15
use Symfony\Component\HttpFoundation\Request;
16
use Symfony\Component\HttpFoundation\Response;
17
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
18
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
19
use Symfony\Component\Validator\ConstraintViolationInterface;
20
use Symfony\Component\Validator\ConstraintViolationListInterface;
21
use Symfony\Component\Validator\Validator\ValidatorInterface;
22
23
final class PutItemsToCartAction
24
{
25
    /** @var ViewHandlerInterface */
26
    private $viewHandler;
27
28
    /** @var CommandBus */
29
    private $bus;
30
31
    /** @var ValidatorInterface */
32
    private $validator;
33
34
    /** @var CartViewRepositoryInterface */
35
    private $cartQuery;
36
37
    /** @var string */
38
    private $validationErrorViewClass;
39
40
    public function __construct(
41
        ViewHandlerInterface $viewHandler,
42
        CommandBus $bus,
43
        ValidatorInterface $validator,
44
        CartViewRepositoryInterface $cartQuery,
45
        string $validationErrorViewClass
46
    ) {
47
        $this->viewHandler = $viewHandler;
48
        $this->bus = $bus;
49
        $this->validator = $validator;
50
        $this->cartQuery = $cartQuery;
51
        $this->validationErrorViewClass = $validationErrorViewClass;
52
    }
53
54
    public function __invoke(Request $request): Response
55
    {
56
        /** @var ConstraintViolationListInterface[] $validationResults */
57
        $validationResults = [];
58
        $commandRequests = [];
59
        $commandsToExecute = [];
60
        $token = $request->attributes->get('token');
61
62
        foreach ($request->request->all() as $item) {
63
            $item['token'] = $token;
64
            $commandRequests[] = $this->provideCommandRequest($item);
65
        }
66
67
        foreach ($commandRequests as $commandRequest) {
68
            $validationResult = $this->validator->validate($commandRequest);
69
70
            if (0 === count($validationResult)) {
71
                $commandsToExecute[] = $commandRequest->getCommand();
72
            }
73
74
            $validationResults[] = $validationResult;
75
        }
76
77
        if (!$this->isValid($validationResults)) {
78
            /** @var ValidationErrorView $errorMessage */
79
            $errorMessage = new $this->validationErrorViewClass();
80
81
            $errorMessage->code = Response::HTTP_BAD_REQUEST;
82
            $errorMessage->message = 'Validation failed';
83
84
            foreach ($validationResults as $validationResult) {
85
                $errors = [];
86
87
                /** @var ConstraintViolationInterface $result */
88
                foreach ($validationResult as $result) {
89
                    $errors[$result->getPropertyPath()][] = $result->getMessage();
90
                }
91
92
                $errorMessage->errors[] = $errors;
93
            }
94
95
            return $this->viewHandler->handle(View::create($errorMessage, Response::HTTP_BAD_REQUEST));
96
        }
97
98
        foreach ($commandsToExecute as $commandToExecute) {
99
            $this->bus->handle($commandToExecute);
100
        }
101
102
        try {
103
            return $this->viewHandler->handle(
104
                View::create($this->cartQuery->getOneByToken($token), Response::HTTP_CREATED)
105
            );
106
        } catch (\InvalidArgumentException $exception) {
107
            throw new BadRequestHttpException($exception->getMessage());
108
        }
109
    }
110
111
    /**
112
     * @param array $item
113
     *
114
     * @return PutOptionBasedConfigurableItemToCartRequest|PutSimpleItemToCartRequest|PutVariantBasedConfigurableItemToCartRequest
115
     */
116
    private function provideCommandRequest(array $item)
117
    {
118
        if (!isset($item['variantCode']) && !isset($item['options'])) {
119
            return PutSimpleItemToCartRequest::fromArray($item);
120
        }
121
122
        if (isset($item['variantCode']) && !isset($item['options'])) {
123
            return PutVariantBasedConfigurableItemToCartRequest::fromArray($item);
124
        }
125
126
        if (!isset($item['variantCode']) && isset($item['options'])) {
127
            return PutOptionBasedConfigurableItemToCartRequest::fromArray($item);
128
        }
129
130
        throw new NotFoundHttpException('Variant not found for given configuration');
131
    }
132
133
    private function isValid(array $validationResults): bool
134
    {
135
        foreach ($validationResults as $validationResult) {
136
            if (0 !== count($validationResult)) {
137
                return false;
138
            }
139
        }
140
141
        return true;
142
    }
143
}
144