Passed
Push — master ( b21036...8d84d5 )
by Christian
11:52 queued 12s
created

OrderService::getMailTemplate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
c 0
b 0
f 0
nc 2
nop 3
dl 0
loc 18
rs 9.9666
1
<?php declare(strict_types=1);
2
3
namespace Shopware\Core\Checkout\Order\SalesChannel;
4
5
use Shopware\Core\Checkout\Cart\Cart;
6
use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
7
use Shopware\Core\Checkout\Order\Exception\PaymentMethodNotAvailableException;
8
use Shopware\Core\Framework\Context;
9
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
10
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
11
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
12
use Shopware\Core\Framework\Validation\BuildValidationEvent;
13
use Shopware\Core\Framework\Validation\DataBag\DataBag;
14
use Shopware\Core\Framework\Validation\DataValidationDefinition;
15
use Shopware\Core\Framework\Validation\DataValidationFactoryInterface;
16
use Shopware\Core\Framework\Validation\DataValidator;
17
use Shopware\Core\Framework\Validation\Exception\ConstraintViolationException;
18
use Shopware\Core\System\SalesChannel\SalesChannelContext;
19
use Shopware\Core\System\StateMachine\Aggregation\StateMachineState\StateMachineStateEntity;
20
use Shopware\Core\System\StateMachine\Exception\StateMachineStateNotFoundException;
21
use Shopware\Core\System\StateMachine\StateMachineRegistry;
22
use Shopware\Core\System\StateMachine\Transition;
23
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
24
use Symfony\Component\HttpFoundation\ParameterBag;
25
26
class OrderService
27
{
28
    public const CUSTOMER_COMMENT_KEY = 'customerComment';
29
    public const AFFILIATE_CODE_KEY = 'affiliateCode';
30
    public const CAMPAIGN_CODE_KEY = 'campaignCode';
31
32
    /**
33
     * @var DataValidator
34
     */
35
    private $dataValidator;
36
37
    /**
38
     * @var DataValidationFactoryInterface
39
     */
40
    private $orderValidationFactory;
41
42
    /**
43
     * @var EventDispatcherInterface
44
     */
45
    private $eventDispatcher;
46
47
    /**
48
     * @var CartService
49
     */
50
    private $cartService;
51
52
    /**
53
     * @var EntityRepositoryInterface
54
     */
55
    private $paymentMethodRepository;
56
57
    /**
58
     * @var StateMachineRegistry
59
     */
60
    private $stateMachineRegistry;
61
62
    public function __construct(
63
        DataValidator $dataValidator,
64
        DataValidationFactoryInterface $orderValidationFactory,
65
        EventDispatcherInterface $eventDispatcher,
66
        CartService $cartService,
67
        EntityRepositoryInterface $paymentMethodRepository,
68
        StateMachineRegistry $stateMachineRegistry
69
    ) {
70
        $this->dataValidator = $dataValidator;
71
        $this->orderValidationFactory = $orderValidationFactory;
72
        $this->eventDispatcher = $eventDispatcher;
73
        $this->cartService = $cartService;
74
        $this->paymentMethodRepository = $paymentMethodRepository;
75
        $this->stateMachineRegistry = $stateMachineRegistry;
76
    }
77
78
    /**
79
     * @throws ConstraintViolationException
80
     */
81
    public function createOrder(DataBag $data, SalesChannelContext $context): string
82
    {
83
        $this->validateOrderData($data, $context);
84
85
        $cart = $this->cartService->getCart($context->getToken(), $context);
86
        $this->addCustomerComment($cart, $data);
87
        $this->addAffiliateTracking($cart, $data);
88
89
        $this->validateCart($cart, $context->getContext());
90
91
        return $this->cartService->order($cart, $context);
92
    }
93
94
    /**
95
     * @deprecated tag:v6.4.0 Parameter $customerId will be removed
96
     *
97
     * @internal Should not be called from outside the core
98
     */
99
    public function orderStateTransition(
100
        string $orderId,
101
        string $transition,
102
        ParameterBag $data,
103
        Context $context,
104
        ?string $customerId = null
0 ignored issues
show
Unused Code introduced by
The parameter $customerId is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

104
        /** @scrutinizer ignore-unused */ ?string $customerId = null

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
105
    ): StateMachineStateEntity {
106
        $stateFieldName = $data->get('stateFieldName', 'stateId');
107
108
        $stateMachineStates = $this->stateMachineRegistry->transition(
109
            new Transition(
110
                'order',
111
                $orderId,
112
                $transition,
113
                $stateFieldName
114
            ),
115
            $context
116
        );
117
118
        $toPlace = $stateMachineStates->get('toPlace');
119
120
        if (!$toPlace) {
121
            throw new StateMachineStateNotFoundException('order_transaction', $transition);
122
        }
123
124
        return $toPlace;
125
    }
126
127
    /**
128
     * @internal Should not be called from outside the core
129
     */
130
    public function orderTransactionStateTransition(
131
        string $orderTransactionId,
132
        string $transition,
133
        ParameterBag $data,
134
        Context $context
135
    ): StateMachineStateEntity {
136
        $stateFieldName = $data->get('stateFieldName', 'stateId');
137
138
        $stateMachineStates = $this->stateMachineRegistry->transition(
139
            new Transition(
140
                'order_transaction',
141
                $orderTransactionId,
142
                $transition,
143
                $stateFieldName
144
            ),
145
            $context
146
        );
147
148
        $toPlace = $stateMachineStates->get('toPlace');
149
150
        if (!$toPlace) {
151
            throw new StateMachineStateNotFoundException('order_transaction', $transition);
152
        }
153
154
        return $toPlace;
155
    }
156
157
    /**
158
     * @internal Should not be called from outside the core
159
     */
160
    public function orderDeliveryStateTransition(
161
        string $orderDeliveryId,
162
        string $transition,
163
        ParameterBag $data,
164
        Context $context
165
    ): StateMachineStateEntity {
166
        $stateFieldName = $data->get('stateFieldName', 'stateId');
167
168
        $stateMachineStates = $this->stateMachineRegistry->transition(
169
            new Transition(
170
                'order_delivery',
171
                $orderDeliveryId,
172
                $transition,
173
                $stateFieldName
174
            ),
175
            $context
176
        );
177
178
        $toPlace = $stateMachineStates->get('toPlace');
179
180
        if (!$toPlace) {
181
            throw new StateMachineStateNotFoundException('order_transaction', $transition);
182
        }
183
184
        return $toPlace;
185
    }
186
187
    private function validateCart(Cart $cart, Context $context): void
188
    {
189
        $idsOfPaymentMethods = [];
190
191
        foreach ($cart->getTransactions() as $paymentMethod) {
192
            $idsOfPaymentMethods[] = $paymentMethod->getPaymentMethodId();
193
        }
194
195
        $criteria = new Criteria();
196
        $criteria->addFilter(
197
            new EqualsFilter('active', true)
198
        );
199
200
        $paymentMethods = $this->paymentMethodRepository->searchIds($criteria, $context);
201
202
        if ($paymentMethods->getTotal() !== count(array_unique($idsOfPaymentMethods))) {
203
            foreach ($cart->getTransactions() as $paymentMethod) {
204
                if (!in_array($paymentMethod->getPaymentMethodId(), $paymentMethods->getIds(), true)) {
205
                    throw new PaymentMethodNotAvailableException($paymentMethod->getPaymentMethodId());
206
                }
207
            }
208
        }
209
    }
210
211
    /**
212
     * @throws ConstraintViolationException
213
     */
214
    private function validateOrderData(ParameterBag $data, SalesChannelContext $context): void
215
    {
216
        $definition = $this->getOrderCreateValidationDefinition($context);
217
        $violations = $this->dataValidator->getViolations($data->all(), $definition);
218
219
        if ($violations->count() > 0) {
220
            throw new ConstraintViolationException($violations, $data->all());
221
        }
222
    }
223
224
    private function getOrderCreateValidationDefinition(SalesChannelContext $context): DataValidationDefinition
225
    {
226
        $validation = $this->orderValidationFactory->create($context);
227
228
        $validationEvent = new BuildValidationEvent($validation, $context->getContext());
229
        $this->eventDispatcher->dispatch($validationEvent, $validationEvent->getName());
0 ignored issues
show
Unused Code introduced by
The call to Symfony\Contracts\EventD...erInterface::dispatch() has too many arguments starting with $validationEvent->getName(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

229
        $this->eventDispatcher->/** @scrutinizer ignore-call */ 
230
                                dispatch($validationEvent, $validationEvent->getName());

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
230
231
        return $validation;
232
    }
233
234
    private function addCustomerComment(Cart $cart, DataBag $data): void
235
    {
236
        $customerComment = ltrim(rtrim((string) $data->get(self::CUSTOMER_COMMENT_KEY, '')));
237
238
        if ($customerComment === '') {
239
            return;
240
        }
241
242
        $cart->setCustomerComment($customerComment);
243
    }
244
245
    private function addAffiliateTracking(Cart $cart, DataBag $data): void
246
    {
247
        $affiliateCode = $data->get(self::AFFILIATE_CODE_KEY);
248
        $campaignCode = $data->get(self::CAMPAIGN_CODE_KEY);
249
        if ($affiliateCode !== null && $campaignCode !== null) {
250
            $cart->setAffiliateCode($affiliateCode);
251
            $cart->setCampaignCode($campaignCode);
252
        }
253
    }
254
}
255