FormHandler   B
last analyzed

Complexity

Total Complexity 45

Size/Duplication

Total Lines 183
Duplicated Lines 0 %

Importance

Changes 2
Bugs 1 Features 1
Metric Value
wmc 45
eloc 99
c 2
b 1
f 1
dl 0
loc 183
rs 8.8

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A getParameters() 0 17 6
A getChecksum() 0 37 5
D setParameter() 0 96 33

How to fix   Complexity   

Complex Class

Complex classes like FormHandler 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 FormHandler, and based on these observations, apply Extract Interface, too.

1
<?php
2
declare(strict_types=1);
3
4
namespace Bpost\BpostApiClient;
5
6
use Bpost\BpostApiClient\Exception\BpostLogicException\BpostInvalidLengthException;
7
use Bpost\BpostApiClient\Exception\BpostLogicException\BpostInvalidValueException;
8
9
/**
10
 * bPost Form handler class
11
 *
12
 * @author Tijs Verkoyen <[email protected]>
13
 */
14
class FormHandler
15
{
16
    private Bpost $bpost;
17
18
    /** @var array<string,mixed> */
19
    private array $parameters = [];
20
21
    /**
22
     * Create bPostFormHandler instance
23
     */
24
    public function __construct(string $accountId, string $passPhrase, string $apiUrl = Bpost::API_URL)
25
    {
26
        $this->bpost = new Bpost($accountId, $passPhrase, $apiUrl);
27
    }
28
29
    /**
30
     * Calculate the hash
31
     */
32
    private function getChecksum(): string
33
    {
34
        $keysToHash = [
35
            'accountId',
36
            'action',
37
            'costCenter',
38
            'customerCountry',
39
            'deliveryMethodOverrides',
40
            'extraSecure',
41
            'orderReference',
42
            'orderWeight',
43
        ];
44
45
        $base = 'accountId=' . $this->bpost->getAccountId() . '&';
46
47
        foreach ($keysToHash as $key) {
48
            if (!array_key_exists($key, $this->parameters)) {
49
                continue;
50
            }
51
52
            $value = $this->parameters[$key];
53
54
            if (!is_array($value)) {
55
                $base .= $key . '=' . $value . '&';
56
                continue;
57
            }
58
59
            // Si c’est un tableau, concaténer chaque entrée (tri déjà fait dans setParameter)
60
            foreach ($value as $entry) {
61
                $base .= $key . '=' . $entry . '&';
62
            }
63
        }
64
65
        // add passphrase
66
        $base .= $this->bpost->getPassPhrase();
67
68
        return hash('sha256', $base);
69
    }
70
71
    /**
72
     * Get the parameters
73
     *
74
     * @return array<string,mixed>
75
     */
76
    public function getParameters(bool $form = false, bool $includeChecksum = true): array
77
    {
78
        $return = $this->parameters;
79
80
        if ($form && isset($return['orderLine']) && is_array($return['orderLine'])) {
81
            foreach ($return['orderLine'] as $key => $value) {
82
                $return['orderLine[' . $key . ']'] = $value;
83
            }
84
            unset($return['orderLine']);
85
        }
86
87
        if ($includeChecksum) {
88
            $return['accountId'] = $this->bpost->getAccountId();
89
            $return['checksum']  = $this->getChecksum();
90
        }
91
92
        return $return;
93
    }
94
95
    /**
96
     * Set a parameter
97
     *
98
     * @throws BpostInvalidValueException
99
     * @throws BpostInvalidLengthException
100
     */
101
    public function setParameter(string $key, mixed $value): void
102
    {
103
        switch ($key) {
104
            // limited values
105
            case 'action':
106
            case 'lang':
107
                $allowedValues = [
108
                    'action' => ['START', 'CONFIRM'],
109
                    'lang'   => ['NL', 'FR', 'EN', 'DE', 'Default'],
110
                ];
111
                if (!in_array($value, $allowedValues[$key], true)) {
112
                    throw new BpostInvalidValueException($key, (string) $value, $allowedValues[$key]);
113
                }
114
                $this->parameters[$key] = $value;
115
                break;
116
117
            // maximum 2 chars
118
            case 'customerCountry':
119
                if (mb_strlen((string) $value) > 2) {
120
                    throw new BpostInvalidLengthException($key, mb_strlen((string) $value), 2);
121
                }
122
                $this->parameters[$key] = (string) $value;
123
                break;
124
125
            // maximum 8 chars
126
            case 'customerStreetNumber':
127
            case 'customerBox':
128
                if (mb_strlen((string) $value) > 8) {
129
                    throw new BpostInvalidLengthException($key, mb_strlen((string) $value), 8);
130
                }
131
                $this->parameters[$key] = (string) $value;
132
                break;
133
134
            // maximum 20 chars
135
            case 'customerPhoneNumber':
136
                if (mb_strlen((string) $value) > 20) {
137
                    throw new BpostInvalidLengthException($key, mb_strlen((string) $value), 20);
138
                }
139
                $this->parameters[$key] = (string) $value;
140
                break;
141
142
            // maximum 32 chars
143
            case 'customerPostalCode':
144
                if (mb_strlen((string) $value) > 32) {
145
                    throw new BpostInvalidLengthException($key, mb_strlen((string) $value), 32);
146
                }
147
                $this->parameters[$key] = (string) $value;
148
                break;
149
150
            // maximum 40 chars
151
            case 'customerFirstName':
152
            case 'customerLastName':
153
            case 'customerCompany':
154
            case 'customerStreet':
155
            case 'customerCity':
156
                if (mb_strlen((string) $value) > 40) {
157
                    throw new BpostInvalidLengthException($key, mb_strlen((string) $value), 40);
158
                }
159
                $this->parameters[$key] = (string) $value;
160
                break;
161
162
            // maximum 50 chars
163
            case 'orderReference':
164
            case 'costCenter':
165
            case 'customerEmail':
166
                if (mb_strlen((string) $value) > 50) {
167
                    throw new BpostInvalidLengthException($key, mb_strlen((string) $value), 50);
168
                }
169
                $this->parameters[$key] = (string) $value;
170
                break;
171
172
            // integers
173
            case 'orderTotalPrice':
174
            case 'orderWeight':
175
                $this->parameters[$key] = (int) $value;
176
                break;
177
178
            // array (order lines)
179
            case 'orderLine':
180
                $this->parameters[$key] ??= [];
181
                $this->parameters[$key][] = $value;
182
                break;
183
184
            // unknown (free fields/URLs/flags/overrides...)
185
            case 'deliveryMethodOverrides':
186
            case 'extra':
187
            case 'extraSecure':
188
            case 'confirmUrl':
189
            case 'cancelUrl':
190
            case 'errorUrl':
191
            default:
192
                if (is_array($value)) {
193
                    // garantir un ordre stable pour le checksum
194
                    sort($value);
195
                }
196
                $this->parameters[$key] = $value;
197
        }
198
    }
199
}
200