Completed
Push — master ( e43f1a...57db71 )
by Arman
26s queued 12s
created

General   B

Complexity

Total Complexity 51

Size/Duplication

Total Lines 274
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 51
eloc 81
c 1
b 0
f 0
dl 0
loc 274
rs 7.92

13 Methods

Rating   Name   Duplication   Size   Complexity  
A starts() 0 5 3
B date() 0 15 7
A streetAddress() 0 11 5
A unique() 0 9 3
A same() 0 5 3
A phoneNumber() 0 7 3
B creditCard() 0 35 8
A name() 0 5 3
A required() 0 4 3
A iban() 0 21 4
A regex() 0 5 3
A email() 0 5 3
A jsonString() 0 7 3

How to fix   Complexity   

Complex Class

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

1
<?php
2
3
/**
4
 * Quantum PHP Framework
5
 *
6
 * An open source software development framework for PHP
7
 *
8
 * @package Quantum
9
 * @author Arman Ag. <[email protected]>
10
 * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
11
 * @link http://quantum.softberg.org/
12
 * @since 2.4.0
13
 */
14
15
namespace Quantum\Libraries\Validation\Rules;
16
17
use Quantum\Factory\ModelFactory;
18
use Quantum\Di\Di;
19
20
/**
21
 * Trait General
22
 * @package Quantum\Libraries\Validation
23
 */
24
trait General
25
{
26
27
    /**
28
     * Adds validation Error
29
     * @param string $field
30
     * @param string $rule
31
     * @param mixed|null $param
32
     */
33
    abstract protected function addError(string $field, string $rule, $param = null);
34
35
    /**
36
     * Checks Field Required
37
     * @param string $field
38
     * @param string $value
39
     * @param null|mixed $param
40
     */
41
    protected function required(string $field, string $value, $param = null)
42
    {
43
        if ($value == false || empty($value)) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $value of type string to the boolean false. If you are specifically checking for an empty string, consider using the more explicit === '' instead.
Loading history...
44
            $this->addError($field, 'required', $param);
45
        }
46
    }
47
48
    /**
49
     * Checks Email
50
     * @param string $field
51
     * @param string $value
52
     * @param null|mixed $param
53
     */
54
    protected function email(string $field, string $value, $param = null)
55
    {
56
        if (!empty($value)) {
57
            if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
58
                $this->addError($field, 'email', $param);
59
            }
60
        }
61
    }
62
63
    /**
64
     * Checks for a valid credit card number
65
     * @param string $field
66
     * @param string $value
67
     * @param null|mixed $param
68
     */
69
    protected function creditCard(string $field, string $value, $param = null)
70
    {
71
        if (!empty($value)) {
72
            $number = preg_replace('/\D/', '', $value);
73
74
            if (function_exists('mb_strlen')) {
75
                $number_length = mb_strlen($number);
76
            } else {
77
                $number_length = strlen($number);
78
            }
79
80
            if ($number_length == 0) {
81
                $this->addError($field, 'creditCard', $param);
82
            }
83
84
            $parity = $number_length % 2;
85
86
            $total = 0;
87
88
            for ($i = 0; $i < $number_length; ++$i) {
89
                $digit = $number[$i];
90
91
                if ($i % 2 == $parity) {
92
                    $digit *= 2;
93
94
                    if ($digit > 9) {
95
                        $digit -= 9;
96
                    }
97
                }
98
99
                $total += $digit;
100
            }
101
102
            if ($total % 10 != 0) {
103
                $this->addError($field, 'creditCard', $param);
104
            }
105
        }
106
    }
107
108
    /**
109
     * Checks for a valid IBAN
110
     * @param string $field
111
     * @param string $value
112
     * @param null|mixed $param
113
     */
114
    protected function iban(string $field, string $value, $param = null)
115
    {
116
        if (!empty($value)) {
117
            static $character = [
118
                'A' => 10, 'C' => 12, 'D' => 13, 'E' => 14, 'F' => 15, 'G' => 16,
119
                'H' => 17, 'I' => 18, 'J' => 19, 'K' => 20, 'L' => 21, 'M' => 22,
120
                'N' => 23, 'O' => 24, 'P' => 25, 'Q' => 26, 'R' => 27, 'S' => 28,
121
                'T' => 29, 'U' => 30, 'V' => 31, 'W' => 32, 'X' => 33, 'Y' => 34,
122
                'Z' => 35, 'B' => 11,
123
            ];
124
125
            if (!preg_match("/\A[A-Z]{2}\d{2} ?[A-Z\d]{4}( ?\d{4}){1,} ?\d{1,4}\z/", $value)) {
126
                $this->addError($field, 'iban', $param);
127
            }
128
129
            $iban = str_replace(' ', '', $value);
130
            $iban = substr($iban, 4) . substr($iban, 0, 4);
131
            $iban = strtr($iban, $character);
132
133
            if (bcmod($iban, 97) != 1) {
134
                $this->addError($field, 'iban', $param);
135
            }
136
        }
137
138
139
    }
140
141
    /**
142
     * Checks for a valid format human name
143
     * @param string $field
144
     * @param string $value
145
     * @param null|mixed $param
146
     */
147
    protected function name(string $field, string $value, $param = null)
148
    {
149
        if (!empty($value)) {
150
            if (preg_match("/^([a-z \p{L} '-])+$/i", $value) === 0) {
151
                $this->addError($field, 'name', $param);
152
            }
153
        }
154
    }
155
156
    /**
157
     * Checks that the provided string is a likely street address.
158
     * @param string $field
159
     * @param string $value
160
     * @param null|mixed $param
161
     */
162
    protected function streetAddress(string $field, string $value, $param = null)
163
    {
164
        if (!empty($value)) {
165
            $hasLetter = preg_match('/[a-zA-Z]/', $value);
166
            $hasDigit = preg_match('/\d/', $value);
167
            $hasSpace = preg_match('/\s/', $value);
168
169
            $passes = $hasLetter && $hasDigit && $hasSpace;
170
171
            if (!$passes) {
172
                $this->addError($field, 'streetAddress', $param);
173
            }
174
        }
175
    }
176
177
    /**
178
     * Validates the phone number // 555-555-5555 , 5555425555, 555 555 5555, 1(519) 555-4444, 1 (519) 555-4422, +1-555-555-5555
179
     * @param string $field
180
     * @param string $value
181
     * @param null|mixed $param
182
     */
183
    protected function phoneNumber(string $field, string $value, $param = null)
184
    {
185
        if (!empty($value)) {
186
            $regex = '/^(\+*\d[\s-]?)?[\(\[\s-]{0,2}?\d{3}[\)\]\s-]{0,2}?\d{3}[\s-]?\d{4}$/i';
187
188
            if (!preg_match($regex, $value)) {
189
                $this->addError($field, 'phoneNumber', $param);
190
            }
191
        }
192
    }
193
194
    /**
195
     * Determines if the provided input is a valid date
196
     * @param string $field
197
     * @param string $value
198
     * @param string|null $param format
199
     */
200
    protected function date(string $field, string $value, string $param = null)
201
    {
202
        if (!empty($value)) {
203
            if (!$param) {
204
                $cdate1 = date('Y-m-d', strtotime($value));
205
                $cdate2 = date('Y-m-d H:i:s', strtotime($value));
206
207
                if ($cdate1 != $value && $cdate2 != $value) {
208
                    $this->addError($field, 'date', $param);
209
                }
210
            } else {
211
                $date = \DateTime::createFromFormat($param, $value);
212
213
                if ($date === false || $value != date($param, $date->getTimestamp())) {
214
                    $this->addError($field, 'date', $param);
215
                }
216
            }
217
        }
218
    }
219
220
    /**
221
     * Ensures the value starts with a certain character / set of character
222
     * @param string $field
223
     * @param string $value
224
     * @param string $param
225
     */
226
    protected function starts(string $field, string $value, string $param)
227
    {
228
        if (!empty($value)) {
229
            if (strpos($value, $param) !== 0) {
230
                $this->addError($field, 'starts', $param);
231
            }
232
        }
233
    }
234
235
    /**
236
     * Custom regex validator
237
     * @param string $field
238
     * @param string $value
239
     * @param string $param
240
     */
241
    protected function regex(string $field, string $value, string $param)
242
    {
243
        if (!empty($value)) {
244
            if (!preg_match($param, $value)) {
245
                $this->addError($field, 'regex', $param);
246
            }
247
        }
248
    }
249
250
    /**
251
     * Validates JSON string
252
     * @param string $field
253
     * @param string $value
254
     * @param null|mixed $param
255
     */
256
    protected function jsonString(string $field, string $value, $param = null)
257
    {
258
        if (!empty($value)) {
259
            $value = htmlspecialchars_decode($value, ENT_QUOTES);
260
261
            if (!is_object(json_decode($value))) {
262
                $this->addError($field, 'jsonString', $param);
263
            }
264
        }
265
    }
266
267
    /**
268
     * Validates same value for both fields
269
     * @param string $field
270
     * @param string $value
271
     * @param null|mixed $param
272
     */
273
    protected function same(string $field, string $value, $param = null)
274
    {
275
        if (!empty($value)) {
276
            if ($value != $this->data[$param]) {
277
                $this->addError($field, 'same', $param);
278
            }
279
        }
280
    }
281
282
    /**
283
     * Validates uniqueness
284
     * @param string $field
285
     * @param mixed $value
286
     * @param string $param
287
     * @throws \Quantum\Exceptions\DiException
288
     */
289
    protected function unique(string $field, $value, string $param)
290
    {
291
        if (!empty($value)) {
292
            $model = Di::get(ModelFactory::class)->get(ucfirst($param));
293
294
            $row = $model->findOneBy($field, $value);
295
296
            if ($row->count()) {
297
                $this->addError($field, 'unique', null);
298
            }
299
        }
300
    }
301
302
}