Passed
Push — trunk ( 95cc21...bc3fdd )
by Christian
12:22 queued 15s
created

SalesChannelContext   C

Complexity

Total Complexity 57

Size/Duplication

Total Lines 451
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 104
c 0
b 0
f 0
dl 0
loc 451
rs 5.04
wmc 57

45 Methods

Rating   Name   Duplication   Size   Complexity  
A setItemRounding() 0 3 1
A ensureLoggedIn() 0 8 4
A getTaxCalculationType() 0 3 1
A buildTaxRules() 0 19 4
A getLanguageId() 0 3 1
A getPaymentMethod() 0 3 1
A getItemRounding() 0 3 1
A getCustomer() 0 3 1
A setPermissions() 0 7 2
A getTaxState() 0 3 1
A getCurrencyId() 0 3 1
A getCurrentCustomerGroup() 0 3 1
A lockRules() 0 3 1
A getPermissions() 0 3 1
A getToken() 0 3 1
A addState() 0 3 1
A getSalesChannelId() 0 3 1
A getLanguageIdChain() 0 3 1
A getFallbackCustomerGroup() 0 8 1
A getAreaRuleIds() 0 3 1
A setTaxState() 0 3 1
A getShippingMethod() 0 3 1
A getContext() 0 3 1
A getStates() 0 3 1
A getShippingLocation() 0 3 1
A getSalesChannel() 0 3 1
A hasPermission() 0 3 2
A setTotalRounding() 0 3 1
A removeState() 0 3 1
A getTotalRounding() 0 3 1
A setRuleIds() 0 8 2
A getRuleIds() 0 3 1
A getCustomerId() 0 3 2
A getDomainId() 0 3 1
A getVersionId() 0 3 1
A __construct() 0 34 1
A setAreaRuleIds() 0 3 1
A lockPermissions() 0 3 1
A hasState() 0 3 1
A getRuleIdsByAreas() 0 13 3
A getApiAlias() 0 3 1
A setDomainId() 0 3 1
A getTaxRules() 0 3 1
A considerInheritance() 0 3 1
A getCurrency() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like SalesChannelContext often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SalesChannelContext, and based on these observations, apply Extract Interface, too.

1
<?php declare(strict_types=1);
2
3
namespace Shopware\Core\System\SalesChannel;
4
5
use Shopware\Core\Checkout\Cart\CartException;
6
use Shopware\Core\Checkout\Cart\Delivery\Struct\ShippingLocation;
7
use Shopware\Core\Checkout\Cart\Tax\Struct\TaxRule;
8
use Shopware\Core\Checkout\Cart\Tax\Struct\TaxRuleCollection;
9
use Shopware\Core\Checkout\Customer\Aggregate\CustomerGroup\CustomerGroupEntity;
10
use Shopware\Core\Checkout\Customer\CustomerEntity;
11
use Shopware\Core\Checkout\Payment\PaymentMethodEntity;
12
use Shopware\Core\Checkout\Shipping\ShippingMethodEntity;
13
use Shopware\Core\Framework\Context;
14
use Shopware\Core\Framework\DataAbstractionLayer\Pricing\CashRoundingConfig;
15
use Shopware\Core\Framework\Feature;
16
use Shopware\Core\Framework\Struct\StateAwareTrait;
17
use Shopware\Core\Framework\Struct\Struct;
18
use Shopware\Core\System\Currency\CurrencyEntity;
19
use Shopware\Core\System\SalesChannel\Exception\ContextPermissionsLockedException;
20
use Shopware\Core\System\SalesChannel\Exception\ContextRulesLockedException;
21
use Shopware\Core\System\Tax\Exception\TaxNotFoundException;
22
use Shopware\Core\System\Tax\TaxCollection;
23
24
class SalesChannelContext extends Struct
25
{
26
    use StateAwareTrait;
27
28
    /**
29
     * Unique token for context, e.g. stored in session or provided in request headers
30
     *
31
     * @var string
32
     */
33
    protected $token;
34
35
    /**
36
     * @var CustomerGroupEntity
37
     */
38
    protected $currentCustomerGroup;
39
40
    /**
41
     * @var CustomerGroupEntity
42
     */
43
    protected $fallbackCustomerGroup;
44
45
    /**
46
     * @var CurrencyEntity
47
     */
48
    protected $currency;
49
50
    /**
51
     * @var SalesChannelEntity
52
     */
53
    protected $salesChannel;
54
55
    /**
56
     * @var TaxCollection
57
     */
58
    protected $taxRules;
59
60
    /**
61
     * @var CustomerEntity|null
62
     */
63
    protected $customer;
64
65
    /**
66
     * @var PaymentMethodEntity
67
     */
68
    protected $paymentMethod;
69
70
    /**
71
     * @var ShippingMethodEntity
72
     */
73
    protected $shippingMethod;
74
75
    /**
76
     * @var ShippingLocation
77
     */
78
    protected $shippingLocation;
79
80
    /**
81
     * @var string[]
82
     */
83
    protected $rulesIds;
84
85
    /**
86
     * @var array<string, string[]>
87
     */
88
    protected array $areaRuleIds;
89
90
    /**
91
     * @var bool
92
     */
93
    protected $rulesLocked = false;
94
95
    /**
96
     * @var mixed[]
97
     */
98
    protected $permissions = [];
99
100
    /**
101
     * @var bool
102
     */
103
    protected $permisionsLocked = false;
104
105
    /**
106
     * @var Context
107
     */
108
    protected $context;
109
110
    /**
111
     * @var CashRoundingConfig
112
     */
113
    private $itemRounding;
114
115
    /**
116
     * @var CashRoundingConfig
117
     */
118
    private $totalRounding;
119
120
    /**
121
     * @var string|null
122
     */
123
    private $domainId;
124
125
    /**
126
     * @deprecated tag:v6.5.0 - __construct will be internal, use context factory to create a new context
127
     * @deprecated tag:v6.5.0 - Parameter $fallbackCustomerGroup is deprecated and will be removed
128
     *
129
     * @param array<string> $rulesIds
130
     * @param array<string, string[]> $areaRuleIds
131
     */
132
    public function __construct(
133
        Context $baseContext,
134
        string $token,
135
        ?string $domainId,
136
        SalesChannelEntity $salesChannel,
137
        CurrencyEntity $currency,
138
        CustomerGroupEntity $currentCustomerGroup,
139
        CustomerGroupEntity $fallbackCustomerGroup,
140
        TaxCollection $taxRules,
141
        PaymentMethodEntity $paymentMethod,
142
        ShippingMethodEntity $shippingMethod,
143
        ShippingLocation $shippingLocation,
144
        ?CustomerEntity $customer,
145
        CashRoundingConfig $itemRounding,
146
        CashRoundingConfig $totalRounding,
147
        array $rulesIds = [],
148
        array $areaRuleIds = []
149
    ) {
150
        $this->currentCustomerGroup = $currentCustomerGroup;
151
        $this->fallbackCustomerGroup = $fallbackCustomerGroup;
152
        $this->currency = $currency;
153
        $this->salesChannel = $salesChannel;
154
        $this->taxRules = $taxRules;
155
        $this->customer = $customer;
156
        $this->paymentMethod = $paymentMethod;
157
        $this->shippingMethod = $shippingMethod;
158
        $this->shippingLocation = $shippingLocation;
159
        $this->rulesIds = $rulesIds;
160
        $this->areaRuleIds = $areaRuleIds;
161
        $this->token = $token;
162
        $this->context = $baseContext;
163
        $this->itemRounding = $itemRounding;
164
        $this->totalRounding = $totalRounding;
165
        $this->domainId = $domainId;
166
    }
167
168
    public function getCurrentCustomerGroup(): CustomerGroupEntity
169
    {
170
        return $this->currentCustomerGroup;
171
    }
172
173
    /**
174
     * @deprecated tag:v6.5.0 - Fallback customer group is deprecated and will be removed, use getCurrentCustomerGroup instead
175
     */
176
    public function getFallbackCustomerGroup(): CustomerGroupEntity
177
    {
178
        Feature::triggerDeprecationOrThrow(
179
            'v6.5.0.0',
180
            Feature::deprecatedMethodMessage(__CLASS__, __METHOD__, 'v6.5.0.0', 'getCurrentCustomerGroup()')
181
        );
182
183
        return $this->fallbackCustomerGroup;
184
    }
185
186
    public function getCurrency(): CurrencyEntity
187
    {
188
        return $this->currency;
189
    }
190
191
    public function getSalesChannel(): SalesChannelEntity
192
    {
193
        return $this->salesChannel;
194
    }
195
196
    public function getTaxRules(): TaxCollection
197
    {
198
        return $this->taxRules;
199
    }
200
201
    /**
202
     * Get the tax rules depend on the customer billing address
203
     * respectively the shippingLocation if there is no customer
204
     */
205
    public function buildTaxRules(string $taxId): TaxRuleCollection
206
    {
207
        $tax = $this->taxRules->get($taxId);
208
209
        if ($tax === null || $tax->getRules() === null) {
210
            throw new TaxNotFoundException($taxId);
211
        }
212
213
        if ($tax->getRules()->first() !== null) {
214
            // NEXT-21735 - This is covered randomly
215
            // @codeCoverageIgnoreStart
216
            return new TaxRuleCollection([
217
                new TaxRule($tax->getRules()->first()->getTaxRate(), 100),
218
            ]);
219
            // @codeCoverageIgnoreEnd
220
        }
221
222
        return new TaxRuleCollection([
223
            new TaxRule($tax->getTaxRate(), 100),
224
        ]);
225
    }
226
227
    public function getCustomer(): ?CustomerEntity
228
    {
229
        return $this->customer;
230
    }
231
232
    public function getPaymentMethod(): PaymentMethodEntity
233
    {
234
        return $this->paymentMethod;
235
    }
236
237
    public function getShippingMethod(): ShippingMethodEntity
238
    {
239
        return $this->shippingMethod;
240
    }
241
242
    public function getShippingLocation(): ShippingLocation
243
    {
244
        return $this->shippingLocation;
245
    }
246
247
    public function getContext(): Context
248
    {
249
        return $this->context;
250
    }
251
252
    /**
253
     * @return string[]
254
     */
255
    public function getRuleIds(): array
256
    {
257
        return $this->rulesIds;
258
    }
259
260
    /**
261
     * @param array<string> $ruleIds
262
     */
263
    public function setRuleIds(array $ruleIds): void
264
    {
265
        if ($this->rulesLocked) {
266
            throw new ContextRulesLockedException();
267
        }
268
269
        $this->rulesIds = array_filter(array_values($ruleIds));
270
        $this->getContext()->setRuleIds($this->rulesIds);
271
    }
272
273
    /**
274
     * @internal
275
     *
276
     * @return array<string, string[]>
277
     */
278
    public function getAreaRuleIds(): array
279
    {
280
        return $this->areaRuleIds;
281
    }
282
283
    /**
284
     * @internal
285
     *
286
     * @param string[] $areas
287
     *
288
     * @return string[]
289
     */
290
    public function getRuleIdsByAreas(array $areas): array
291
    {
292
        $ruleIds = [];
293
294
        foreach ($areas as $area) {
295
            if (empty($this->areaRuleIds[$area])) {
296
                continue;
297
            }
298
299
            $ruleIds = array_unique(array_merge($ruleIds, $this->areaRuleIds[$area]));
300
        }
301
302
        return array_values($ruleIds);
303
    }
304
305
    /**
306
     * @internal
307
     *
308
     * @param array<string, string[]> $areaRuleIds
309
     */
310
    public function setAreaRuleIds(array $areaRuleIds): void
311
    {
312
        $this->areaRuleIds = $areaRuleIds;
313
    }
314
315
    public function lockRules(): void
316
    {
317
        $this->rulesLocked = true;
318
    }
319
320
    public function lockPermissions(): void
321
    {
322
        $this->permisionsLocked = true;
323
    }
324
325
    public function getToken(): string
326
    {
327
        return $this->token;
328
    }
329
330
    public function getTaxState(): string
331
    {
332
        return $this->context->getTaxState();
333
    }
334
335
    public function setTaxState(string $taxState): void
336
    {
337
        $this->context->setTaxState($taxState);
338
    }
339
340
    public function getTaxCalculationType(): string
341
    {
342
        return $this->getSalesChannel()->getTaxCalculationType();
343
    }
344
345
    /**
346
     * @return mixed[]
347
     */
348
    public function getPermissions(): array
349
    {
350
        return $this->permissions;
351
    }
352
353
    /**
354
     * @param mixed[] $permissions
355
     */
356
    public function setPermissions(array $permissions): void
357
    {
358
        if ($this->permisionsLocked) {
359
            throw new ContextPermissionsLockedException();
360
        }
361
362
        $this->permissions = array_filter($permissions);
363
    }
364
365
    public function getApiAlias(): string
366
    {
367
        return 'sales_channel_context';
368
    }
369
370
    public function hasPermission(string $permission): bool
371
    {
372
        return \array_key_exists($permission, $this->permissions) && (bool) $this->permissions[$permission];
373
    }
374
375
    public function getSalesChannelId(): string
376
    {
377
        return $this->getSalesChannel()->getId();
378
    }
379
380
    public function addState(string ...$states): void
381
    {
382
        $this->context->addState(...$states);
383
    }
384
385
    public function removeState(string $state): void
386
    {
387
        $this->context->removeState($state);
388
    }
389
390
    public function hasState(string ...$states): bool
391
    {
392
        return $this->context->hasState(...$states);
393
    }
394
395
    /**
396
     * @return string[]
397
     */
398
    public function getStates(): array
399
    {
400
        return $this->context->getStates();
401
    }
402
403
    public function getDomainId(): ?string
404
    {
405
        return $this->domainId;
406
    }
407
408
    public function setDomainId(?string $domainId): void
409
    {
410
        $this->domainId = $domainId;
411
    }
412
413
    /**
414
     * @return string[]
415
     */
416
    public function getLanguageIdChain(): array
417
    {
418
        return $this->context->getLanguageIdChain();
419
    }
420
421
    public function getLanguageId(): string
422
    {
423
        return $this->context->getLanguageId();
424
    }
425
426
    public function getVersionId(): string
427
    {
428
        return $this->context->getVersionId();
429
    }
430
431
    public function considerInheritance(): bool
432
    {
433
        return $this->context->considerInheritance();
434
    }
435
436
    public function getTotalRounding(): CashRoundingConfig
437
    {
438
        return $this->totalRounding;
439
    }
440
441
    public function setTotalRounding(CashRoundingConfig $totalRounding): void
442
    {
443
        $this->totalRounding = $totalRounding;
444
    }
445
446
    public function getItemRounding(): CashRoundingConfig
447
    {
448
        return $this->itemRounding;
449
    }
450
451
    public function setItemRounding(CashRoundingConfig $itemRounding): void
452
    {
453
        $this->itemRounding = $itemRounding;
454
    }
455
456
    public function getCurrencyId(): string
457
    {
458
        return $this->getCurrency()->getId();
459
    }
460
461
    public function ensureLoggedIn(bool $allowGuest = true): void
462
    {
463
        if ($this->customer === null) {
464
            throw CartException::customerNotLoggedIn();
465
        }
466
467
        if (!$allowGuest && $this->customer->getGuest()) {
468
            throw CartException::customerNotLoggedIn();
469
        }
470
    }
471
472
    public function getCustomerId(): ?string
473
    {
474
        return $this->customer ? $this->customer->getId() : null;
475
    }
476
}
477