Passed
Push — master ( 8a23c2...e496ae )
by Christian
13:05 queued 10s
created

LineItemCustomFieldRule::isCustomFieldValid()   B

Complexity

Conditions 9
Paths 11

Size

Total Lines 31
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 23
nc 11
nop 1
dl 0
loc 31
rs 8.0555
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Shopware\Core\Checkout\Cart\Rule;
4
5
use Shopware\Core\Checkout\Cart\Exception\PayloadKeyNotFoundException;
6
use Shopware\Core\Checkout\Cart\LineItem\LineItem;
7
use Shopware\Core\Framework\Rule\Exception\UnsupportedOperatorException;
8
use Shopware\Core\Framework\Rule\Rule;
9
use Shopware\Core\Framework\Rule\RuleScope;
10
use Shopware\Core\System\CustomField\CustomFieldTypes;
11
use Symfony\Component\Validator\Constraint;
12
use Symfony\Component\Validator\Constraints\Choice;
13
use Symfony\Component\Validator\Constraints\NotBlank;
14
15
class LineItemCustomFieldRule extends Rule
16
{
17
    /** @var string */
18
    protected $operator;
19
20
    /** @var array */
21
    protected $renderedField;
22
23
    /** @var mixed */
24
    protected $renderedFieldValue;
25
26
    public function getName(): string
27
    {
28
        return 'cartLineItemCustomField';
29
    }
30
31
    /**
32
     * @throws UnsupportedOperatorException
33
     */
34
    public function match(RuleScope $scope): bool
35
    {
36
        if ($scope instanceof LineItemScope) {
37
            return $this->isCustomFieldValid($scope->getLineItem());
38
        }
39
40
        if (!$scope instanceof CartRuleScope) {
41
            return false;
42
        }
43
44
        foreach ($scope->getCart()->getLineItems() as $lineItem) {
45
            if ($this->isCustomFieldValid($lineItem)) {
46
                return true;
47
            }
48
        }
49
50
        return false;
51
    }
52
53
    public function getConstraints(): array
54
    {
55
        return [
56
            'renderedField' => [new NotBlank()],
57
            'selectedField' => [new NotBlank()],
58
            'selectedFieldSet' => [new NotBlank()],
59
            'renderedFieldValue' => $this->getRenderedFieldValueConstraints(),
60
            'operator' => [
61
                new NotBlank(),
62
                new Choice(
63
                    [
64
                        self::OPERATOR_NEQ,
65
                        self::OPERATOR_GTE,
66
                        self::OPERATOR_LTE,
67
                        self::OPERATOR_EQ,
68
                        self::OPERATOR_GT,
69
                        self::OPERATOR_LT,
70
                    ]
71
                ),
72
            ],
73
        ];
74
    }
75
76
    /**
77
     * @throws UnsupportedOperatorException
78
     */
79
    private function isCustomFieldValid(LineItem $lineItem): bool
80
    {
81
        try {
82
            $customFields = $lineItem->getPayloadValue('customFields');
83
84
            $actual = $this->getValue($customFields, $this->renderedField);
0 ignored issues
show
Bug introduced by
It seems like $customFields can also be of type null; however, parameter $customFields of Shopware\Core\Checkout\C...omFieldRule::getValue() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

84
            $actual = $this->getValue(/** @scrutinizer ignore-type */ $customFields, $this->renderedField);
Loading history...
85
86
            if ($actual === null) {
87
                return false;
88
            }
89
90
            $expected = $this->getExpectedValue($this->renderedFieldValue, $this->renderedField);
91
        } catch (PayloadKeyNotFoundException $e) {
92
            return false;
93
        }
94
95
        switch ($this->operator) {
96
            case self::OPERATOR_NEQ:
97
                return $actual !== $expected;
98
            case self::OPERATOR_GTE:
99
                return $actual >= $expected;
100
            case self::OPERATOR_LTE:
101
                return $actual <= $expected;
102
            case self::OPERATOR_EQ:
103
                return $actual === $expected;
104
            case self::OPERATOR_GT:
105
                return $actual > $expected;
106
            case self::OPERATOR_LT:
107
                return $actual < $expected;
108
            default:
109
                throw new UnsupportedOperatorException($this->operator, self::class);
110
        }
111
    }
112
113
    /**
114
     * @return Constraint[]
115
     */
116
    private function getRenderedFieldValueConstraints(): array
117
    {
118
        $constraints = [];
119
120
        if (!\is_array($this->renderedField) || !\array_key_exists('type', $this->renderedField)) {
0 ignored issues
show
introduced by
The condition is_array($this->renderedField) is always true.
Loading history...
121
            return [new NotBlank()];
122
        }
123
124
        if ($this->renderedField['type'] !== CustomFieldTypes::BOOL) {
125
            $constraints[] = new NotBlank();
126
        }
127
128
        return $constraints;
129
    }
130
131
    /**
132
     * @return string|int|float|bool|null
133
     */
134
    private function getValue(array $customFields, array $renderedField)
135
    {
136
        if (in_array($renderedField['type'], [CustomFieldTypes::BOOL, CustomFieldTypes::SWITCH], true)) {
137
            if (!empty($customFields) && \array_key_exists($this->renderedField['name'], $customFields)) {
138
                return $customFields[$renderedField['name']];
139
            }
140
141
            return false;
142
        }
143
144
        if (!empty($customFields) && \array_key_exists($this->renderedField['name'], $customFields)) {
145
            return $customFields[$renderedField['name']];
146
        }
147
148
        return null;
149
    }
150
151
    /**
152
     * @param string|int|float|bool|null $renderedFieldValue
153
     *
154
     * @return string|int|float|bool|null
155
     */
156
    private function getExpectedValue($renderedFieldValue, array $renderedField)
157
    {
158
        if (in_array($renderedField['type'], [CustomFieldTypes::BOOL, CustomFieldTypes::SWITCH], true)) {
159
            return $renderedFieldValue ?? false; // those fields are initialized with null in the rule builder
160
        }
161
162
        return $renderedFieldValue;
163
    }
164
}
165