Completed
Push — master ( 1bbedc...98a21f )
by Dmytro
02:10
created

Validator::validateNotEmpty()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 1
Metric Value
cc 3
eloc 8
nc 4
nop 1
dl 0
loc 13
rs 9.4285
c 1
b 1
f 1
1
<?php
2
3
namespace Asymptix\core;
4
5
use Asymptix\web\Session;
6
use Asymptix\web\Request;
7
8
/**
9
 * Form fields validation functionality.
10
 *
11
 * @category Asymptix PHP Framework
12
 * @author Dmytro Zarezenko <[email protected]>
13
 * @copyright (c) 2009 - 2017, Dmytro Zarezenko
14
 *
15
 * @git https://github.com/Asymptix/Framework
16
 * @license http://opensource.org/licenses/MIT
17
 */
18
class Validator {
19
20
    /**
21
     * Validate field value by regular expression.
22
     *
23
     * @param string $fieldValue Value of the field.
24
     * @param string $regexp Regular expression.
25
     *
26
     * @return bool
27
     */
28
    public static function validateRegexp($fieldValue, $regexp) {
29
        return (bool)preg_match($regexp, $fieldValue);
30
    }
31
32
    /**
33
     * Validate if field value is not empty.
34
     *
35
     * @param string $fieldName Name of the field.
36
     *
37
     * @return bool
38
     */
39
    public static function validateNotEmpty($fieldName) {
40
        $fieldValue = Request::getFieldValue($fieldName);
41
        if (is_string($fieldValue)) {
42
            $fieldValue = trim($fieldValue);
43
        }
44
        if (empty($fieldValue)) {
45
            Errors::saveErrorFor($fieldName, \__ERRORS::FIELD_CANT_BE_EMPTY);
46
47
            return false;
48
        }
49
50
        return true;
51
    }
52
53
    /**
54
     * Validate if checkbox is checked.
55
     *
56
     * @param string $fieldName Name of the field.
57
     *
58
     * @return bool
59
     */
60 View Code Duplication
    public static function validateChecked($fieldName) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
61
        $fieldValue = trim(Request::getFieldValue($fieldName));
62
        if (empty($fieldValue)) {
63
            Errors::saveErrorFor($fieldName, \__ERRORS::CHECK_THIS_FIELD);
64
65
            return false;
66
        }
67
68
        return true;
69
    }
70
71
    /**
72
     * Validate if field value is empty.
73
     *
74
     * @param string $fieldName Name of the field.
75
     *
76
     * @return bool
77
     */
78
    public static function validateEmpty($fieldName) {
79
        $fieldValue = trim(Request::getFieldValue($fieldName));
80
        if (empty($fieldValue)) {
81
            return true;
82
        }
83
84
        return false;
85
    }
86
87
    /**
88
     * Validate if field value haven't spaces.
89
     *
90
     * @param string $fieldName Name of the field.
91
     *
92
     * @return bool
93
     */
94 View Code Duplication
    public static function validateNoSpaces($fieldName) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
95
        $fieldValue = Request::getFieldValue($fieldName);
96
        if (strpos($fieldValue, " ") !== false) {
97
            Errors::saveErrorFor($fieldName, \__ERRORS::SPACES_INACCEPTABLE);
98
99
            return false;
100
        }
101
102
        return true;
103
    }
104
105
    /**
106
     * Validate login value.
107
     *
108
     * @param string $fieldName Login field name.
109
     *
110
     * @return bool
111
     */
112
    public static function validateLogin($fieldName) {
113
        if (!validateNotEmpty($fieldName)) {
114
            return false;
115
        }
116
117
        return validateNoSpaces($fieldName);
118
    }
119
120
    /**
121
     * Validate if field value is real password.
122
     *
123
     * @param string $passwordFieldName Name of password field.
124
     * @param string $rePasswordFieldName Name of password repeting field.
125
     *
126
     * @return bool
127
     */
128
    public static function validatePassword($passwordFieldName, $rePasswordFieldName) {
129
        $password = trim(Request::getFieldValue($passwordFieldName));
130
        $rePassword = trim(Request::getFieldValue($rePasswordFieldName));
131
        if (empty($password)) {
132
            Errors::saveErrorFor($passwordFieldName, \__ERRORS::EMPTY_PASSWORD);
133
134
            return false;
135
        }
136
137
        if ($password != $rePassword) {
138
            Errors::saveErrorFor($rePasswordFieldName, \__ERRORS::PASSWORDS_ARE_DIFFERENT);
139
140
            return false;
141
        }
142
143
        return true;
144
    }
145
146
    /**
147
     * Validate if captcha code is correct.
148
     *
149
     * @param string $fieldName Name of the captcha field.
150
     *
151
     * @return bool
152
     */
153
    public static function validateCaptcha($fieldName) {
154
        if (!validateNotEmpty($fieldName)) {
155
            return false;
156
        }
157
        if (!validateNoSpaces($fieldName)) {
158
            return false;
159
        }
160
        if (Request::getFieldValue($fieldName) != Session::get($fieldName)) {
161
            Errors::saveErrorFor($fieldName, \__ERRORS::INVALID_CAPTCHA_CODE);
162
163
            return false;
164
        }
165
166
        return true;
167
    }
168
169
    /**
170
     * Validate if field value is real e-mail address.
171
     *
172
     * @param string $fieldName Name of the field.
173
     *
174
     * @return bool
175
     */
176 View Code Duplication
    public static function validateEmail($fieldName) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
177
        $fieldValue = trim(Request::getFieldValue($fieldName));
178
        if (!self::validateNotEmpty($fieldName)) {
179
            Errors::saveErrorFor($fieldName, \__ERRORS::INVALID_EMAIL);
180
181
            return false;
182
        } elseif (!self::validateRegexp($fieldValue, "#^[A-Za-z0-9\._-]+@([A-Za-z0-9-]+\.)+[A-Za-z0-9-]+$#")) {
183
            Errors::saveErrorFor($fieldName, \__ERRORS::INVALID_EMAIL);
184
185
            return false;
186
        }
187
188
        return true;
189
    }
190
191
    /**
192
     * Validate if variable value is correct e-mail address.
193
     *
194
     * @param string $value Value of the variable.
195
     *
196
     * @return bool
197
     */
198
    public static function isEmail($value) {
199
        if (empty($value)) {
200
            return false;
201
        }
202
203
        return self::validateRegexp($value, "#^[A-Za-z0-9\._-]+@([A-Za-z0-9-]+\.)+[A-Za-z0-9-]+$#");
204
    }
205
206
    /**
207
     * Normalize URL with protocol prefix.
208
     *
209
     * @param string $url Unnormalized URL.
210
     * @param string $protocol Protocol type (default: http).
211
     *
212
     * @return string Normalized URL.
213
     */
214
    public static function normalizeUrl($url, $protocol = "http") {
215
        $url = trim($url);
216
        if (empty($url)) {
217
            return "";
218
        }
219
220
        if (!self::validateRegexp($url, "#^" . $protocol . "://.+#")) {
221
            $url = $protocol . "://" . $url;
222
        }
223
        $url = preg_replace("#/{3,}#", "//", $url);
224
225
        return $url;
226
    }
227
228
    /**
229
     * Validate if field value is correct URL.
230
     *
231
     * @param string $fieldName Name of the field.
232
     *
233
     * @return bool
234
     */
235
    public static function validateUrl($fieldName) {
236
        $fieldValue = Request::getFieldValue($fieldName);
237
238
        if (!self::validateNotEmpty($fieldName)) {
239
            Errors::saveErrorFor($fieldName, \__ERRORS::URL_EMPTY);
240
241
            return false;
242
        } elseif (!self::isUrl($fieldValue)) {
243
            Errors::saveErrorFor($fieldName, \__ERRORS::URL_INVALID);
244
245
            return false;
246
        }
247
248
        return true;
249
    }
250
251
    /**
252
     * Validate if variable value is correct URL.
253
     *
254
     * @param string $value Value of the variable.
255
     *
256
     * @return bool
257
     */
258
    public static function isUrl($value) {
259
        $topLevelDomainsList = [
260
            // 3 letters
261
            'com', 'org', 'net', 'gov', 'mil', 'biz', 'xyz', 'int', 'edu', 'win',
262
            'top', 'ltd',
263
264
            // 4 letters
265
            'info', 'mobi', 'name', 'aero', 'jobs', 'news', 'blog', 'rest',
266
            'arpa', 'guru', 'club', 'asia', 'site', 'tech', 'link', 'life',
267
            'fund',
268
269
            // 5 letters
270
            'photo', 'click', 'cloud',
271
272
            // 6 letters
273
            'museum', 'travel', 'review',
274
275
            // 7 letters
276
            'network',
277
        ];
278
279
        return self::validateRegexp(
280
            $value,
281
            "<^(?#Protocol)(?:(?:ht|f)tp(?:s?)\:\/\/|~/|/)?(?#Username:Password)(?:\w+:\w+@)?(?#Subdomains)(?:(?:[-\w]+\.)+(?#TopLevel Domains)(?:" . implode("|", $topLevelDomainsList) . "|[a-z]{2}))(?#Port)(?::[\d]{1,5})?(?#Directories)(?:(?:(?:/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|/)+|\?|#)?(?#Query)(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?#Anchor)(?:#(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)?$>"
282
        );
283
    }
284
285
    /**
286
     * Validate maximum length of the text without HTML tags.
287
     *
288
     * @global array<string> $_ERRORS Global list of form fields validation errors.
289
     * @param string $fieldName Name of the field.
290
     * @param string $maxTextLength Text length limit.
291
     *
292
     * @return bool
293
     */
294 View Code Duplication
    public static function validateTextMaxLength($fieldName, $maxTextLength) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
295
        $text = trim(strip_tags(Request::getFieldValue($fieldName)));
296
        if (strlen($text) > $maxTextLength) {
297
            Errors::saveErrorFor(
298
                $fieldName,
299
                str_replace("[[1]]", $maxTextLength, \__ERRORS::MAX_TEXT_LENGTH)
300
            );
301
302
            return false;
303
        }
304
305
        return true;
306
    }
307
308
    /**
309
     * Validate minimum length of the text without HTML tags.
310
     *
311
     * @global array<string> $_ERRORS Global list of form fields validation errors.
312
     * @param string $fieldName Name of the field.
313
     * @param string $minTextLength Text length limit.
314
     *
315
     * @return bool
316
     */
317 View Code Duplication
    public static function validateTextMinLength($fieldName, $minTextLength) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
318
        $text = trim(strip_tags(Request::getFieldValue($fieldName)));
319
        if (strlen($text) < $minTextLength) {
320
            Errors::saveErrorFor(
321
                $fieldName,
322
                str_replace("[[1]]", $minTextLength, \__ERRORS::MIN_TEXT_LENGTH)
323
            );
324
325
            return false;
326
        }
327
328
        return true;
329
    }
330
331
    /**
332
     * Validate if field value is integer.
333
     *
334
     * @param string $fieldName Name of the field.
335
     * @return bool
336
     */
337 View Code Duplication
    public static function validateInteger($fieldName) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
338
        $fieldValue = trim(Request::getFieldValue($fieldName));
339
        if (!self::validateNotEmpty($fieldName)) {
340
            Errors::saveErrorFor($fieldName, \__ERRORS::FIELD_CANT_BE_EMPTY);
341
342
            return false;
343
        } elseif (!Tools::isInteger($fieldValue)) {
344
            Errors::saveErrorFor($fieldName, \__ERRORS::INVALID_INTEGER);
345
346
            return false;
347
        }
348
349
        return true;
350
    }
351
352
    /**
353
     * Validate if field value is double(float).
354
     *
355
     * @param string $fieldName Name of the field.
356
     *
357
     * @return bool
358
     */
359
    public static function validateDouble($fieldName) {
360
        $fieldValue = trim(Request::getFieldValue($fieldName));
361
        $doubleValue = (float)$fieldValue;
362
        if (!validateNotEmpty($fieldName)) {
363
            Errors::saveErrorFor($fieldName, \__ERRORS::FIELD_CANT_BE_EMPTY);
364
365
            return false;
366
        } elseif (sprintf("%.2f", $doubleValue) != $fieldValue) {
367
            Errors::saveErrorFor($fieldName, \__ERRORS::INVALID_NUMBER);
368
369
            return false;
370
        }
371
        changeFieldValue($fieldName, $doubleValue);
372
373
        return true;
374
    }
375
376
    /**
377
     * Validate if field value is double(float).
378
     *
379
     * @param string $fieldName Name of the field.
380
     *
381
     * @return bool
382
     */
383
    public static function validateFloat($fieldName) {
384
        return self::validateDouble($fieldName);
385
    }
386
387
    /**
388
     * Validate if field value is positive numeric value.
389
     *
390
     * @param string $fieldName Name of the field.
391
     *
392
     * @return bool
393
     */
394 View Code Duplication
    public static function validatePositive($fieldName) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
395
        $fieldValue = trim(Request::getFieldValue($fieldName));
396
        if ($fieldValue <= 0) {
397
            Errors::saveErrorFor($fieldName, \__ERRORS::INVALID_POSITIVE);
398
399
            return false;
400
        }
401
402
        return true;
403
    }
404
405
    /**
406
     * Validate if login data is correct.
407
     *
408
     * @param string $loginFieldName Name of the login field.
409
     * @param string $passwordFieldName Name of the password field.
410
     *
411
     * @return bool
412
     */
413
    public static function validateSignIn($loginFieldName, $passwordFieldName) {
414
        $login = Request::getFieldValue($loginFieldName);
415
        $password = Request::getFieldValue($passwordFieldName);
416
417
        $validationResult = true;
418
        if ($login == null || trim($login) == "") {
419
            Errors::saveErrorFor($loginFieldName, \__ERRORS::EMPTY_LOGIN);
420
            $validationResult = false;
421
        }
422
        if ($password == null || trim($password) == "") {
423
            Errors::saveErrorFor($passwordFieldName, \__ERRORS::EMPTY_PASSWORD);
424
            $validationResult = false;
425
        }
426
427
        return $validationResult;
428
    }
429
430
    /**
431
     * Validate if file was uploaded.
432
     *
433
     * @global array $_FILES Global array of uploaded files.
434
     * @param string $fileFieldName Name of the file field.
435
     *
436
     * @return bool
437
     */
438
    public static function validateFileUpload($fileFieldName) {
0 ignored issues
show
Coding Style introduced by
validateFileUpload uses the super-global variable $_FILES which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
439
        global $_FILES;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
440
441
        if (isset($_FILES[$fileFieldName]) && $_FILES[$fileFieldName]['error'] == UPLOAD_ERR_OK) {
442
            return true;
443
        }
444
        Errors::saveErrorFor($fileFieldName, \__ERRORS::FILE_UPLOAD_ERROR);
445
446
        return false;
447
    }
448
449
    /**
450
     * Validates if some value is in array.
451
     *
452
     * @param string $fieldName Field name.
453
     * @param array $range Array with values.
454
     *
455
     * @return bool
456
     */
457 View Code Duplication
    public static function validateRange($fieldName, $range) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
458
        $fieldValue = Request::getFieldValue($fieldName);
459
        if (!in_array($fieldValue, $range)) {
460
            Errors::saveErrorFor($fieldName, \__ERRORS::INCORRECT_VALUE);
461
462
            return false;
463
        }
464
465
        return true;
466
    }
467
468
}
469