Passed
Push — master ( dd6e64...a763da )
by Christian
12:12 queued 11s
created

OrderService::addAffiliateTracking()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 2
nop 2
dl 0
loc 7
rs 10
c 0
b 0
f 0
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
87
        $this->validateCart($cart, $context->getContext());
88
89
        return $this->cartService->order($cart, $context, $data->toRequestDataBag());
90
    }
91
92
    /**
93
     * @deprecated tag:v6.4.0 Parameter $customerId will be removed
94
     *
95
     * @internal Should not be called from outside the core
96
     */
97
    public function orderStateTransition(
98
        string $orderId,
99
        string $transition,
100
        ParameterBag $data,
101
        Context $context,
102
        ?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

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

227
        $this->eventDispatcher->/** @scrutinizer ignore-call */ 
228
                                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...
228
229
        return $validation;
230
    }
231
}
232