Issues (88)

src/Rules/Postalcode.php (1 issue)

Labels
Severity
1
<?php
2
3
/**
4
 * This file is part of Dimtrovich/Validation.
5
 *
6
 * (c) 2023 Dimitri Sitchet Tomkeu <[email protected]>
7
 *
8
 * For the full copyright and license information, please view
9
 * the LICENSE file that was distributed with this source code.
10
 */
11
12
namespace Dimtrovich\Validation\Rules;
13
14
use BlitzPHP\Utilities\Support\Invader;
15
use Rakit\Validation\Rule;
16
17
class Postalcode extends AbstractRule
18
{
19
    /**
20
     * Reference key to get locale from data
21
     */
22
    protected ?string $reference = null;
23
24
    protected array $countrycodes = [];
25
26
    /**
27
     * {@inheritDoc}
28
     */
29
    public function fillParameters(array $params): Rule
30
    {
31
        $this->countrycodes = $params;
32
33
        return $this;
34
    }
35
36
    /**
37
     * Static constructor method to create data aware validation rule which
38
     * reads the allowed country code by reference.
39
     */
40
    public static function reference(string $reference): static
41
    {
42
        $rule            = new static();
43
        $rule->reference = $reference;
44
45
        return $rule;
46
    }
47
48
    /**
49
     * Static constructor method
50
     */
51
    public static function countrycode(array $countrycodes): static
52
    {
53
        $rule               = new static();
54
        $rule->countrycodes = $countrycodes;
55
56
        return $rule;
57
    }
58
59
    /**
60
     * Check if the current value is a valid Postal Code
61
     *
62
     * @see https://en.wikipedia.org/wiki/Postal_code
63
     *
64
     * @credit <a href="https://github.com/Intervention/validation">Intervention/validation - \Intervention\Validation\Rules\PostalCode</a>
65
     *
66
     * @param mixed $value
67
     */
68
    public function check($value): bool
69
    {
70
        foreach ($this->getPatterns() as $pattern) {
71
            if (preg_match($pattern, $value)) {
72
                return true;
73
            }
74
        }
75
76
        return false;
77
    }
78
79
    /**
80
     * Return regex patterns for allowed country codes
81
     */
82
    protected function getPatterns(): array
83
    {
84
        $patterns = array_map(fn ($countrycode) => $this->getPattern($countrycode), $this->getCountryCodes());
85
86
        return array_filter($patterns, fn ($pattern) => null !== $pattern);
87
    }
88
89
    protected function getCountryCodes(): array
90
    {
91
        if (count($this->countrycodes) === 0) {
92
            $data = Invader::make($this->validation)->inputs;
0 ignored issues
show
It seems like $this->validation can also be of type null; however, parameter $obj of BlitzPHP\Utilities\Support\Invader::make() does only seem to accept object, 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

92
            $data = Invader::make(/** @scrutinizer ignore-type */ $this->validation)->inputs;
Loading history...
93
94
            // return country code by reference
95
            if (is_array($data) && array_key_exists($this->reference, $data)) {
96
                return [$data[$this->reference]];
97
            }
98
        }
99
100
        return $this->countrycodes;
101
    }
102
103
    /**
104
     * Return regex pattern for postal code of current country code
105
     */
106
    protected function getPattern(string $countrycode): ?string
107
    {
108
        switch (strtolower($countrycode)) {
109
            case 'dz':
110
            case 'as':
111
            case 'ad':
112
            case 'de':
113
            case 'ba':
114
            case 'ic':
115
            case 'mp':
116
            case 'hr':
117
            case 'cu':
118
            case 'ee':
119
            case 'fi':
120
            case 'fr':
121
            case 'gf':
122
            case 'gp':
123
            case 'gu':
124
            case 'id':
125
            case 'it':
126
            case 'kr':
127
            case 'kv':
128
            case 'lt':
129
            case 'my':
130
            case 'mh':
131
            case 'mq':
132
            case 'yt':
133
            case 'fm':
134
            case 'mc':
135
            case 'me':
136
            case 'ma':
137
            case 'nc':
138
            case 'pk':
139
            case 'pw':
140
            case 'pr':
141
            case 're':
142
            case 'sm':
143
            case 'rs':
144
            case 'es':
145
            case 'xy':
146
            case 'th':
147
            case 'tr':
148
            case 'ua':
149
            case 'us':
150
            case 'vi':
151
                return '/^[0-9]{5}$/';
152
153
            case 'fo':
154
            case 'is':
155
            case 'mg':
156
            case 'pg':
157
                return '/^[0-9]{3}$/';
158
159
            case 'cz':
160
            case 'gr':
161
            case 'sk':
162
            case 'se':
163
                return '/^[0-9]{3} [0-9]{2}$/';
164
165
            case 'il':
166
                return '/^[0-9]{5}([0-9]{2})?$/';
167
168
            case 'br':
169
                return '/^[0-9]{5}(-?[0-9]{3})?$/';
170
171
            case 'gg':
172
            case 'je':
173
                return '/^[a-z]{2}[0-9][0-9]? [0-9][a-z]{2}$/i';
174
175
            case 'bn':
176
                return '/^[a-z]{2}[0-9]{4}$/i';
177
178
            case 'jp':
179
                return '/^[0-9]{3}-[0-9]{4}$/';
180
181
            case 'nl':
182
                return '/^[0-9]{4}\\s?[a-z]{2}$/i';
183
184
            case 'ar':
185
            case 'am':
186
            case 'au':
187
            case 'at':
188
            case 'bd':
189
            case 'be':
190
            case 'bg':
191
            case 'cy':
192
            case 'dk':
193
            case 'ge':
194
            case 'gl':
195
            case 'hu':
196
            case 'lv':
197
            case 'li':
198
            case 'lu':
199
            case 'mk':
200
            case 'md':
201
            case 'nz':
202
            case 'no':
203
            case 'ph':
204
            case 'si':
205
            case 'za':
206
            case 'ch':
207
            case 'tn':
208
                return '/^[0-9]{4}$/';
209
210
            case 'mv':
211
            case 'mx':
212
                return '/^[0-9]{4}[0-9]?$/';
213
214
            case 'mn':
215
                return '/^[0-9]{5}[0-9]?$/';
216
217
            case 'pl':
218
                return '/^[0-9]{2}-[0-9]{3}$/';
219
220
            case 'pt':
221
                return '/^[0-9]{4}(-[0-9]{3})?$/';
222
223
            case 'by':
224
            case 'cn':
225
            case 'ec':
226
            case 'in':
227
            case 'kz':
228
            case 'kg':
229
            case 'ro':
230
            case 'ru':
231
            case 'sg':
232
            case 'tj':
233
            case 'zu':
234
                return '/^[0-9]{6}$/';
235
236
            case 'ca':
237
                return '/^[a-z][0-9][a-z] [0-9][a-z]([0-9])?$/i';
238
239
            case 'az':
240
                return '/^[0-9]{4}([0-9]{2})?$/';
241
242
            case 'sz':
243
                return '/^[a-z]{1}[0-9]{3}$/i';
244
245
            case 'tw':
246
                return '/^[0-9]{3}([0-9]{2})?$/';
247
248
            case 'gb':
249
                return '/^(([a-z][0-9])|([a-z][0-9]{2})|([a-z][0-9][a-z])|([a-z]{2}[0-9])|([a-z]{2}[0-9]{2})|([a-z]{2}[0-9][a-z])) [0-9][a-z]{2}$/i';
250
        }
251
252
        return null;
253
    }
254
}
255