Test Failed
Push — master ( 7665f3...4425a6 )
by Julien
04:44
created

Validate::addUuidValidation()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 14
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 5
c 1
b 0
f 0
nc 3
nop 3
dl 0
loc 14
ccs 0
cts 6
cp 0
crap 20
rs 10
1
<?php
2
3
/**
4
 * This file is part of the Zemit Framework.
5
 *
6
 * (c) Zemit Team <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE.txt
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Zemit\Mvc\Model;
13
14
use Phalcon\Security;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Zemit\Mvc\Model\Security. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
15
use Phalcon\Validation\Validator\Between;
16
use Phalcon\Validation\Validator\Date;
17
use Phalcon\Validation\Validator\InclusionIn;
18
use Phalcon\Validation\Validator\Numericality;
19
use Phalcon\Validation\Validator\PresenceOf;
20
use Phalcon\Validation\Validator\StringLength\Max;
21
use Phalcon\Validation\Validator\StringLength\Min;
22
use Phalcon\Validation\Validator\Uniqueness;
23
use Zemit\Mvc\Model\AbstractTrait\AbstractBehavior;
24
use Zemit\Mvc\Model\AbstractTrait\AbstractInjectable;
25
use Zemit\Mvc\Model\Behavior\Transformable;
26
use Zemit\Validation;
27
28
// Boolean
29
const YES = 1;
30
const NO = 0;
31
32
// TinyInt
33
const MIN_UNSIGNED_TINYINT = 0;
34
const MAX_UNSIGNED_TINYINT = 255;
35
const MIN_SIGNED_TINYINT = -128;
36
const MAX_SIGNED_TINYINT = 127;
37
38
// SmallInt
39
const MIN_UNSIGNED_SMALLINT = 0;
40
const MAX_UNSIGNED_SMALLINT = 65535;
41
const MIN_SIGNED_SMALLINT = -32768;
42
const MAX_SIGNED_SMALLINT = 32767;
43
44
// MediumInt
45
const MIN_UNSIGNED_MEDIUMINT = 0;
46
const MAX_UNSIGNED_MEDIUMINT = 16777215;
47
const MIN_SIGNED_MEDIUMINT = -8388608;
48
const MAX_SIGNED_MEDIUMINT = 8388607;
49
50
// Int
51
const MIN_UNSIGNED_INT = 0;
52
const MAX_UNSIGNED_INT = 4294967295;
53
const MIN_SIGNED_INT = -2147483648;
54
const MAX_SIGNED_INT = 2147483647;
55
56
// BigInt
57
const MIN_UNSIGNED_BIGINT = 0;
58
const MAX_UNSIGNED_BIGINT = 18446744073709551615;
59
const MIN_SIGNED_BIGINT = -9223372036854775808;
60
const MAX_SIGNED_BIGINT = 9223372036854775807;
61
62
// Float
63
const MIN_SIGNED_FLOAT = -3.402823466E+38;
64
const MAX_SIGNED_FLOAT = -1.175494351E-38;
65
const MIN_UNSIGNED_FLOAT = 1.175494351E-38;
66
const MAX_UNSIGNED_FLOAT = 3.402823466E+38;
67
68
// Double
69
const MIN_SIGNED_DOUBLE = -1.7976931348623157E+308;
70
const MAX_SIGNED_DOUBLE = -2.2250738585072014E-308;
71
const MIN_UNSIGNED_DOUBLE = 2.2250738585072014E-308;
72
const MAX_UNSIGNED_DOUBLE = 1.7976931348623157E+308;
73
74
// Decimal
75
const MAX_DECIMAL_DIGIT = 65;
76
77
// DateTime
78
const DATETIME_FORMAT = 'Y-m-d H:i:s';
79
const DATETIME_MIN = '1000-01-01 00:00:00';
80
const DATETIME_MAX = '9999-12-31 23:59:59';
81
82
// Date
83
const DATE_FORMAT = 'Y-m-d';
84
const DATE_MIN = '1000-01-01';
85
const DATE_MAX = '9999-12-31';
86
87
// Timestamp
88
const TIMESTAMP_FORMAT = 'Y-m-d H:i:s';
89
const TIMESTAMP_MIN = '1970-01-01 00:00:01';
90
const TIMESTAMP_MAX = '2038-01-19 03:14:07';
91
92
// Year
93
const YEAR_MIN = 1901;
94
const YEAR_MAX = 2155;
95
96
// Char
97
const CHAR_MIN_LENGTH = 0;
98
const CHAR_MAX_LENGTH = 255;
99
100
// VarChar
101
const VARCHAR_MIN_LENGTH = 0;
102
const VARCHAR_MAX_LENGTH = 65535;
103
104
// Binary
105
const BINARY_MIN_BYTES = 0;
106
const BINARY_MAX_BYTES = 255;
107
108
// VarBinary
109
const VARBINARY_MIN_BYTES = 0;
110
const VARBINARY_MAX_BYTES = 65535;
111
112
// Blob
113
const TINYBLOB_MIN_LENGTH = 0;
114
const TINYBLOB_MAX_LENGTH = 255;
115
const BLOB_MIN_LENGTH = 0;
116
const BLOB_MAX_LENGTH = 65535;
117
const MEDIUMBLOB_MIN_LENGTH = 0;
118
const MEDIUMBLOB_MAX_LENGTH = 16777215;
119
const LONGBLOB_MIN_LENGTH = 0;
120
const LONGBLOB_MAX_LENGTH = 4294967295;
121
122
// Text
123
const TINYTEXT_MIN_LENGTH = 0;
124
const TINYTEXT_MAX_LENGTH = 255;
125
const TEXT_MIN_LENGTH = 0;
126
const TEXT_MAX_LENGTH = 65535;
127
const MEDIUMTEXT_MIN_LENGTH = 0;
128
const MEDIUMTEXT_MAX_LENGTH = 16777215;
129
const LONGTEXT_MIN_LENGTH = 0;
130
const LONGTEXT_MAX_LENGTH = 4294967295;
131
132
trait Validate
133
{
134
    /**
135
     * Add default basic validations
136
     * - Position
137
     * - Soft delete
138
     * - Create
139
     * - Update
140
     * - Delete
141
     * - Restore
142
     * - Uuid
143
     * - Uid
144
     * - Guid
145
     *
146
     * @param Validation|null $validator
147
     * @return Validation
148
     */
149
    public function genericValidation(?Validation $validator = null)
150
    {
151
        $validator ??= new Validation();
152
        
153
        $this->addPositionValidation($validator);
154
        $this->addSoftDeleteValidation($validator);
155
        $this->addCreatedValidation($validator);
156
        $this->addUpdatedValidation($validator);
157
        $this->addDeletedValidation($validator);
158
        $this->addRestoredValidation($validator);
159
        $this->addUuidValidation($validator, 'uid');
160
        $this->addUuidValidation($validator, 'uuid');
161
        $this->addUuidValidation($validator, 'guid');
162
        
163
        return $validator;
164
    }
165
    
166
    /**
167
     * Add basic validations for an unsigned field to the validator
168
     * - Must be numeric
169
     * - Must be an unsigned integer
170
     *
171
     * @param Validation $validator
172
     * @param string $field
173
     * @param bool $allowEmpty
174
     * @return Validation
175
     */
176
    public function addUnsignedIntValidation(Validation $validator, string $field = 'id', bool $allowEmpty = true): Validation
177
    {
178
        if (property_exists($this, $field)) {
179
            
180
            if (!$allowEmpty) {
181
                $validator->add($field, new PresenceOf([
182
                    'message' => $this->_('required'),
0 ignored issues
show
Bug introduced by
It seems like _() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

182
                    'message' => $this->/** @scrutinizer ignore-call */ _('required'),
Loading history...
183
                ]));
184
            }
185
            
186
            // Must be numeric
187
            $validator->add($field, new Numericality([
188
                'message' => $this->_('not-numeric'),
189
                'allowEmpty' => $allowEmpty,
190
            ]));
191
            
192
            // Must be an unsigned integer
193
            $validator->add($field, new Between([
194
                'minimum' => 0,
195
                'maximum' => MAX_UNSIGNED_INT,
196
                'message' => $this->_('not-an-unsigned-integer'),
197
                'allowEmpty' => $allowEmpty,
198
            ]));
199
        }
200
        
201
        return $validator;
202
    }
203
    
204
    /**
205
     * Add basic validations for an unsigned field to the validator
206
     * - Must be numeric
207
     * - Must be an unsigned integer
208
     *
209
     * @param Validation $validator
210
     * @param string $field
211
     * @param bool $allowEmpty
212
     * @return Validation
213
     */
214
    public function addUnsignedBigIntValidation(Validation $validator, string $field = 'id', bool $allowEmpty = true): Validation
215
    {
216
        if (property_exists($this, $field)) {
217
            
218
            if (!$allowEmpty) {
219
                $validator->add($field, new PresenceOf([
220
                    'message' => $this->_('required'),
221
                ]));
222
            }
223
            
224
            // Must be numeric
225
            $validator->add($field, new Numericality([
226
                'message' => $this->_('not-numeric'),
227
                'allowEmpty' => $allowEmpty,
228
            ]));
229
            
230
            // Must be an unsigned integer
231
            $validator->add($field, new Between([
232
                'minimum' => 0,
233
                'maximum' => MAX_UNSIGNED_BIGINT,
234
                'message' => $this->_('not-an-unsigned-big-integer'),
235
                'allowEmpty' => $allowEmpty,
236
            ]));
237
        }
238
        
239
        return $validator;
240
    }
241
    
242
    public function addNumberValidation(Validation $validator, string $field, int $min, int $max, bool $allowEmpty = true)
243
    {
244
        if (!$allowEmpty) {
245
            $validator->add($field, new PresenceOf([
246
                'message' => $this->_('required'),
247
            ]));
248
        }
249
        
250
        // Must be numeric
251
        $validator->add($field, new Numericality([
252
            'message' => $this->_('not-numeric'),
253
            'allowEmpty' => $allowEmpty,
254
        ]));
255
        
256
        // Must be an unsigned integer
257
        $validator->add($field, new Between([
258
            'minimum' => $min,
259
            'maximum' => $max,
260
            'message' => $this->_('not-between'),
261
            'allowEmpty' => $allowEmpty,
262
        ]));
263
    }
264
    
265
    public function addStringLengthValidation(Validation $validator, string $field, int $minChar = 0, int $maxChar = 255, bool $allowEmpty = true)
266
    {
267
        
268
        if (!$allowEmpty) {
269
            $validator->add($field, new PresenceOf([
270
                'message' => $this->_('required'),
271
            ]));
272
        }
273
        
274
        $validator->add($field, new Min([
275
            'min' => $minChar,
276
            'message' => $this->_('min-length'),
277
        ]));
278
        
279
        $validator->add($field, new Max([
280
            'max' => $maxChar,
281
            'message' => $this->_('max-length'),
282
        ]));
283
        
284
        return $validator;
285
    }
286
    
287
    public function addInclusionInValidation(Validation $validator, string $field, array $domainList = [], bool $allowEmpty = true)
288
    {
289
        
290
        if (!$allowEmpty) {
291
            $validator->add($field, new PresenceOf([
292
                'message' => $this->_('required'),
293
            ]));
294
        }
295
        
296
        $validator->add($field, new InclusionIn([
297
            'message' => $this->_('not-valid'),
298
            'domain' => $domainList,
299
        ]));
300
    }
301
    
302
    public function addBooleanValidation(Validation $validator, string $field, bool $allowEmpty = true)
303
    {
304
        
305
        if (!$allowEmpty) {
306
            $validator->add($field, new PresenceOf([
307
                'message' => $this->_('required'),
308
            ]));
309
        }
310
        
311
        $validator->add($field, new InclusionIn([
312
            'message' => $this->_('not-boolean'),
313
            'domain' => [YES, NO, 1, 0, true, false],
314
        ]));
315
    }
316
    
317
    /**
318
     * Add basic validations for the position field to the validator
319
     * - Must be numeric
320
     * - Must be an unsigned integer
321
     *
322
     * @param Validation $validator
323
     * @param string $field
324
     * @param bool $allowEmpty
325
     * @return Validation
326
     */
327
    public function addPositionValidation(Validation $validator, string $field = 'position', bool $allowEmpty = true): Validation
328
    {
329
        if (property_exists($this, $field)) {
330
            
331
            // Must be numeric
332
            $validator->add($field, new Numericality([
333
                'message' => $this->_('not-numeric'),
334
                'allowEmpty' => $allowEmpty,
335
            ]));
336
            
337
            // Must be an unsigned integer
338
            $validator->add($field, new Between([
339
                'minimum' => 0,
340
                'maximum' => MAX_UNSIGNED_INT,
341
                'message' => $this->_('not-an-unsigned-integer'),
342
                'allowEmpty' => $allowEmpty,
343
            ]));
344
        }
345
        
346
        return $validator;
347
    }
348
    
349
    /**
350
     * Add basic validations for the position field to the validator
351
     * - Must be 0 or 1
352
     * - Must be numeric
353
     *
354
     * @param Validation $validator
355
     * @param string $field
356
     * @param bool $allowEmpty
357
     * @return void
358
     */
359
    public function addSoftDeleteValidation(Validation $validator, string $field = 'deleted', bool $allowEmpty = true)
360
    {
361
        if (property_exists($this, $field)) {
362
            
363
            // Must be 0 or 1
364
            $validator->add($field, new Between([
365
                'minimum' => 0,
366
                'maximum' => 1,
367
                'message' => $this->_('not-0-or-1'),
368
            ]));
369
            
370
            // Must be numeric
371
            $validator->add($field, new Numericality([
372
                'message' => $this->_('not-numeric'),
373
                'allowEmpty' => $allowEmpty,
374
            ]));
375
        }
376
    }
377
    
378
    /**
379
     * Disable audit & audit details blamable behavior
380
     * @return void
381
     */
382
    public function addBlameableBehavior(): void
383
    {
384
        // disabled
385
    }
386
    
387
    /**
388
     * Add basic validations for the $field to the validator
389
     * - Must be unique
390
     * - Field is required
391
     *
392
     * @param Validation $validator
393
     * @param string $field uuid field to validate
394
     * @param bool $required set to true to add the PresenceOf validation
395
     * @return Validation
396
     */
397
    public function addUuidValidation(Validation $validator, string $field = 'uuid', bool $required = true)
398
    {
399
        if (property_exists($this, $field) && $this->getModelsMetaData()->hasAttribute($this, $field)) {
0 ignored issues
show
Bug introduced by
It seems like getModelsMetaData() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

399
        if (property_exists($this, $field) && $this->/** @scrutinizer ignore-call */ getModelsMetaData()->hasAttribute($this, $field)) {
Loading history...
400
            
401
            // If field is required
402
            if ($required) {
403
                $validator->add($field, new PresenceOf(['message' => $this->_('required')]));
404
            }
405
            
406
            // Must be unique
407
            $validator->add($field, new Uniqueness(['message' => $this->_('not-unique')]));
408
        }
409
        
410
        return $validator;
411
    }
412
    
413
    /**
414
     * Add basic validations for the $userIdField and $dateField field to the validator
415
     * - $userIdField: Must be numeric
416
     * - $userIdField: Must be an unsigned integer
417
     * - $dateField: Must be a valid date
418
     *
419
     * @param Validation $validator
420
     * @param string $userIdField user id field to validate
421
     * @param string $dateField date field to validate
422
     * @param bool $allowEmpty set true to allow empty values in user and date field
423
     * @return Validation
424
     */
425
    public function addCrudValidation(Validation $validator, string $userIdField, string $dateField, bool $allowEmpty = true): Validation
426
    {
427
        if (property_exists($this, $userIdField)) {
428
            
429
            // Must be numeric
430
            $validator->add($userIdField, new Numericality([
431
                'message' => $this->_('not-numeric'),
432
                'allowEmpty' => $allowEmpty,
433
            ]));
434
            
435
            // Must be an unsigned integer
436
            $validator->add($userIdField, new Between([
437
                'minimum' => 0,
438
                'maximum' => MAX_UNSIGNED_INT,
439
                'message' => $this->_('not-an-unsigned-integer'),
440
                'allowEmpty' => $allowEmpty,
441
            ]));
442
        }
443
        
444
        if (property_exists($this, $dateField)) {
445
            
446
            // Must be a valid date format
447
            $validator->add($dateField, new Date([
448
                'format' => DATETIME_FORMAT,
449
                'message' => $this->_('invalid-date-format'),
450
                'allowEmpty' => $allowEmpty,
451
            ]));
452
        }
453
        
454
        return $validator;
455
    }
456
    
457
    /**
458
     * Add crud validation to the user id and date field
459
     *
460
     * @param Validation $validator
461
     * @param string $createdByField user id field to validate
462
     * @param string $createdAtField date field to validate
463
     * @param bool $allowEmpty set true to allow empty values in user and date field
464
     * @return Validation
465
     */
466
    public function addCreatedValidation(Validation $validator, string $createdByField = 'createdBy', string $createdAtField = 'createdAt', bool $allowEmpty = true): Validation
467
    {
468
        return $this->addCrudValidation($validator, $createdByField, $createdAtField, $allowEmpty);
469
    }
470
    
471
    /**
472
     * Add crud validation to the user id and date field
473
     *
474
     * @param Validation $validator
475
     * @param string $updatedByField user id field to validate
476
     * @param string $updatedAtField date field to validate
477
     * @param bool $allowEmpty set true to allow empty values in user and date field
478
     * @return Validation
479
     */
480
    public function addUpdatedValidation(Validation $validator, string $updatedByField = 'updatedBy', string $updatedAtField = 'updatedAt', bool $allowEmpty = true): Validation
481
    {
482
        return $this->addCrudValidation($validator, $updatedByField, $updatedAtField, $allowEmpty);
483
    }
484
    
485
    /**
486
     * Add crud validation to the user id and date field
487
     *
488
     * @param Validation $validator
489
     * @param string $deletedField user id field to validate
490
     * @param string $dateField date field to validate
491
     * @param bool $allowEmpty set true to allow empty values in user and date field
492
     * @return Validation
493
     */
494
    public function addDeletedValidation(Validation $validator, string $deletedField = 'deletedBy', string $dateField = 'deletedAt', bool $allowEmpty = true): Validation
495
    {
496
        return $this->addCrudValidation($validator, $deletedField, $dateField, $allowEmpty);
497
    }
498
    
499
    /**
500
     * Add crud validation to the user id and date field
501
     *
502
     * @param Validation $validator
503
     * @param string $restoredByField user id field to validate
504
     * @param string $restoredAtField date field to validate
505
     * @param bool $allowEmpty set true to allow empty values in user and date field
506
     * @return Validation
507
     */
508
    public function addRestoredValidation(Validation $validator, string $restoredByField = 'restoredBy', string $restoredAtField = 'restoredAt', bool $allowEmpty = true): Validation
509
    {
510
        return $this->addCrudValidation($validator, $restoredByField, $restoredAtField, $allowEmpty);
511
    }
512
}
513