Passed
Branch master (251dd3)
by refat
04:36
created

Validation::date()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 10
c 1
b 0
f 0
nc 4
nop 2
dl 0
loc 19
rs 9.6111
1
<?php
2
3
namespace System;
4
5
use System\Date;
6
use System\Characters;
7
8
class Validation
9
{
10
  /**
11
   * Application Object
12
   *
13
   * @var \System\Application
14
   */
15
  private $app;
16
17
  /**
18
   * Input name
19
   *
20
   * @var string
21
   */
22
  private $input;
23
24
  /**
25
   * Input value
26
   *
27
   * @var string
28
   */
29
  private $value;
30
31
  /**
32
   * Errors container
33
   *
34
   * @var array
35
   */
36
  private $errors = [];
37
38
  /**
39
   * Constructor
40
   *
41
   * @param \System\Application $app
42
   */
43
  public function __construct(Application $app)
44
  {
45
    $this->app = $app;
46
  }
47
48
  public function input($input, $request = 'post')
49
  {
50
    $this->input = $input;
51
52
    $this->value = $this->app->request->$request($this->input);
53
54
    return $this;
55
  }
56
57
  /**
58
   * Get the value for the input name
59
   *
60
   * @return mixed
61
   */
62
  private function value()
63
  {
64
    return mb_strtolower($this->value);
65
  }
66
67
  /**
68
   * Determine if the input is not empty
69
   *
70
   * @param bool $call
71
   * @param string $msg
72
   * @return $this
73
   */
74
  public function require($call = true, $msg = null)
75
  {
76
    if ($call === false) return $this;
77
78
    $value = $this->value();
79
80
    if ($value === '' || $value === null) {
81
      $msg = $msg ?: 'this field is required';
82
83
      $this->addError($this->input, $msg);
84
    }
85
    return $this;
86
  }
87
88
  /**
89
   * Call the function by given $type
90
   *
91
   * @param string $type
92
   * @return function
0 ignored issues
show
Bug introduced by
The type System\function was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
93
   */
94
  public function type($type)
95
  {
96
    return $this->$type();
97
  }
98
99
  /**
100
   * Determine if the input is valid email
101
   *
102
   * @param bool $call
103
   * @param string $msg
104
   * @return $this
105
   */
106
  public function email($call = true, $msg = null)
107
  {
108
    if ($call === false) return $this;
109
110
    $value = $this->value();
111
112
    if (!$value && $value != '0') return $this;
113
114
    if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
115
      $msg = $msg ?: 'e-mail is not valid';
116
117
      $this->addError($this->input, $msg);
118
    }
119
    return $this;
120
  }
121
122
  /**
123
   * Determine if the input is an image
124
   *
125
   * @param bool $call
126
   * @param string $customErrorMessage
127
   * @return $this
128
   */
129
  public function image($call = true, $msg = null)
130
  {
131
    if ($call === false) return $this;
132
133
    $file = $this->app->request->file($this->input);
134
135
    if (!$file->exists()) return $this;
136
137
    if (!$file->isImage()) {
138
      $msg = $msg ?: 'image is not valid';
139
140
      $this->addError($this->input, $msg);
141
    }
142
    return $this;
143
  }
144
145
  /**
146
   * Determine if the input has number
147
   *
148
   * @param bool $call
149
   * @param string $msg
150
   * @return $this
151
   */
152
  public function number($call = true, $msg = null)
153
  {
154
    if ($call === false) return $this;
155
156
    $value = $this->value();
157
158
    if (!$value && $value != '0') return $this;
159
160
    if (!is_numeric($value)) {
161
      $msg = $msg ?: 'this field must be a number';
162
163
      $this->addError($this->input, $msg);
164
    }
165
    return $this;
166
  }
167
168
  /**
169
   * Determine if the input has float value
170
   *
171
   * @param bool $call
172
   * @param string $msg
173
   * @return $this
174
   */
175
  public function float($call = true, $msg = null)
176
  {
177
    if ($call === false) return $this;
178
179
    $value = $this->value();
180
181
    if (!$value && $value != '0') return $this;
182
183
    if (!is_float($value)) {
0 ignored issues
show
introduced by
The condition is_float($value) is always false.
Loading history...
184
      $msg = $msg ?: "this field must be a float number";
185
186
      $this->addError($this->input, $msg);
187
    }
188
    return $this;
189
  }
190
191
  /**
192
   * Determine if the input is a date
193
   * Determine if the input between the range if the $options['start']
194
   * or the $options ['end'] is exists
195
   *
196
   * @param string $options
197
   * @param string $msg
198
   * @return $this
199
   */
200
  public function date($options = [], $msg = null)
201
  {
202
    if ($options === false) return $this;
0 ignored issues
show
introduced by
The condition $options === false is always false.
Loading history...
203
204
    $value = $this->value();
205
206
    if (!$value && $value != '0') return $this;
207
208
    $options = json_encode($options);
209
    $options = json_decode($options);
210
211
    extract($this->dateMethods($options));
212
213
    $date = new Date($value, $options);
214
215
    if (!$date->$method()) {
216
      $this->addError($this->input, $msg);
217
    }
218
    return $this;
219
  }
220
221
  private function dateMethods($options)
222
  {
223
    $method = null;
224
    $msg = null;
225
    if ($options->start && $options->end) {
226
      $method = 'isDateBetween';
227
      $msg = 'this field must be between ' . $options->start . ' and ' . $options->end;
228
    } elseif ($options->start) {
229
      $method = 'minimum';
230
      $msg = 'the date can\'t be under ' . $options->start;
231
    } elseif ($options->end) {
232
      $method = 'maximum';
233
      $msg = 'the date can\'t be above ' . $options->end;
234
    }
235
    return array('method' => $method, 'msg'=> $msg);
236
  }
237
238
  /**
239
   * Determine if the input has simple text
240
   *
241
   * @param bool $call
242
   * @param string $msg
243
   * @return $this
244
   */
245
  public function text($call = true, $msg = null)
246
  {
247
    if ($call === false) return $this;
248
249
    $value = $this->value();
250
251
    if (!$value && $value != '0') return $this;
252
253
    if (!is_string($value)) {
0 ignored issues
show
introduced by
The condition is_string($value) is always true.
Loading history...
254
      $msg = $msg ?: 'the field must be a text';
255
256
      $this->addError($this->input, $msg);
257
    }
258
    return $this;
259
  }
260
261
  /**
262
   * Determine if the input has pure string
263
   *
264
   * @param bool $call
265
   * @param string $msg
266
   * @return $this
267
   */
268
  public function noNumbers($call = true, $msg = null)
269
  {
270
    if ($call === false) return $this;
271
272
    $value = $this->value();
273
274
    if (!$value && $value != '0') return $this;
275
276
    if (preg_match('~[0-9]~', $value)) {
277
      $msg = $msg ?: 'numbers are not allow';
278
279
      $this->addError($this->input, $msg);
280
    }
281
282
    return $this;
283
  }
284
285
  /**
286
   * Determine if the input has pure string
287
   *
288
   * @param array $excepts
289
   * @param string $msg
290
   * @return $this
291
   */
292
  public function characters($excepts, $msg = null)
293
  {
294
    if ($excepts === false) return $this;
0 ignored issues
show
introduced by
The condition $excepts === false is always false.
Loading history...
295
296
    $value = $this->value();
297
298
    if (!$value && $value != '0') return $this;
299
300
    extract($this->charactersvariables($excepts, $value));
301
302
    if ($this->checkForErrorsInCharactersMethods($methods, $msg)) {
303
      return $this;
304
    }
305
306
    $re = "/^[0-9\\s$chars$langsRegex]*$/u";
307
    if (!preg_match($re, $value)) {
308
      $chars = $this->charactersFormatCharsMsg($chars);
309
      $languages = $languages ? "[ $languages ]" : '';
310
      $msg = $msg ?: "just $chars $languages letters can be used";
311
      $this->addError($this->input, $msg);
312
    }
313
    return $this;
314
  }
315
316
  private function charactersFormatCharsRegex($chars)
317
  {
318
    if (strlen($chars) > 1) {
319
      $chars = str_split($chars);
320
      $chars = "\\" . implode('|\\', $chars);
321
    }
322
    return $chars;
323
  }
324
325
  private function charactersFormatCharsMsg($chars)
326
  {
327
    $chars = explode('\\', $chars);
328
    $chars = implode('', $chars);
329
    $chars = $chars ? "[ $chars ] and" : '';
330
    return $chars;
331
  }
332
333
  private function charactersvariables($excepts, $value)
334
  {
335
    $characters = new Characters($excepts);
336
    $chars = $characters->getChars();
337
    $langsRegex = $characters->getLangsRegex();
338
    $languages = $characters->getLanguages();
339
    $times = $characters->getTimes();
340
    $atFirst = $characters->getAtFirst();
341
    $atEnd = $characters->getAtEnd();
342
    $between = $characters->getBetween();
343
    $methods = $this->charactersMethods([
344
      "times" => $times,
345
      "atFirst" => $atFirst,
346
      "atEnd" => $atEnd,
347
      "between" => $between,
348
      "chars" => $chars,
349
      "value" => $value,
350
    ]);
351
352
    return [
353
      'characters' => $characters,
354
      'chars' => $chars,
355
      'langsRegex' => $langsRegex,
356
      'languages' => $languages,
357
      'times' => $times,
358
      'atFirst' => $atFirst,
359
      'atEnd' => $atEnd,
360
      'between' => $between,
361
      'methods' => $methods,
362
    ];
363
  }
364
365
  private function charactersMethods($args)
366
  {
367
    extract($args);
368
    return [
369
      'charactersTimes' => [
370
        [$times, $chars, $value],
371
        'charachters are too many',
372
      ],
373
      'charactersAtFirst' => [
374
        [$atFirst, $chars, $value],
375
        'charachters cant be at the first',
376
      ],
377
      'charactersAtEnd' => [
378
        [$atEnd, $chars, $value],
379
        'charachters cant be at the end',
380
      ],
381
      'charactersBetween' => [
382
        [$between, $chars, $value],
383
        'charachters cant be between',
384
      ],
385
    ];
386
  }
387
388
  private function charactersTimes($times, $chars, $value)
389
  {
390
    if ($times > 0) {
391
      $chars = $this->charactersFormatCharsRegex($chars);
392
      $re = "/($chars)/";
393
      if (preg_match($re, $value) && preg_match_all($re, $value) > $times) {
394
        return true;
395
      }
396
      return false;
397
    }
398
  }
399
400
  private function charactersAtFirst($atFirst, $chars, $value)
401
  {
402
    if ($atFirst === false) {
403
      $chars = $this->charactersFormatCharsRegex($chars);
404
      $re = "/^($chars" . "|\\s+\\$chars)/";
405
      if (preg_match_all($re, $value)) {
406
        return true;
407
      }
408
      return false;
409
    }
410
  }
411
412
  private function charactersAtEnd($atEnd, $chars, $value)
413
  {
414
    if ($atEnd === false) {
415
      $chars = $this->charactersFormatCharsRegex($chars);
416
      $re = "/($chars" . "|\\$chars\\s+)$/";
417
      if (preg_match_all($re, $value)) {
418
        return true;
419
      }
420
      return false;
421
    }
422
  }
423
424
  private function charactersBetween($between, $chars, $value)
425
  {
426
    if ($between === false) {
427
      $chars = $this->charactersFormatCharsRegex($chars);
428
      $re = "/.+(${chars})(.+|\\s)/";
429
      if (preg_match_all($re, $value)) {
430
        return true;
431
      }
432
      return false;
433
    }
434
  }
435
436
  private function checkForErrorsInCharactersMethods($methods, $msg)
437
  {
438
    foreach ($methods as $method => $options) {
439
      if (call_user_func_array(array($this, $method), $options[0])) {
440
        $msg = $msg ?: $options[1];
441
        $this->addError($this->input, $msg);
442
        return true;
443
      }
444
    }
445
    return false;
446
  }
447
448
  /**
449
   * Determine if the input has spaces between the letters or the words
450
   *
451
   * @param bool $call
452
   * @param string $msg
453
   * @return $this
454
   */
455
  public function noSpaces($call = true, $msg = null)
456
  {
457
    if ($call === false) return $this;
458
459
    $value = $this->value();
460
461
    if (!$value && $value != '0') return $this;
462
463
    if (preg_match('/\s/', $value)) {
464
      $msg = $msg ?: 'spaces are not allow';
465
466
      $this->addError($this->input, $msg);
467
    }
468
    return $this;
469
  }
470
471
  /**
472
   * Determine if the given input has the value that are passed
473
   *
474
   * @param array $characters
475
   * @param string $msg
476
   * @return $this
477
   */
478
  public function containJust($characters = [], $msg = null)
479
  {
480
    if ($characters === false) return $this;
0 ignored issues
show
introduced by
The condition $characters === false is always false.
Loading history...
481
482
    $value = $this->value();
483
484
    if (!$value && $value != '0') return $this;
485
486
    if (!is_array($characters) && $characters !== '') {
0 ignored issues
show
introduced by
The condition is_array($characters) is always true.
Loading history...
487
      $characters = [$characters];
488
    }
489
490
    $path = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $path is dead and can be removed.
Loading history...
491
    $indexes = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $indexes is dead and can be removed.
Loading history...
492
493
    $files = [];
494
    $final = [];
495
496
    foreach ($characters as $key => $character) {
497
      if (strpos($character, 'path:') === 0) {
498
        unset($characters[$key]);
499
500
        $path = substr($character, 5);
501
502
        $getFrom = 'value';
503
504
        if (strpos($path, '::')) {
505
          list($path, $getFrom) = explode('::', $path);
506
        }
507
508
        if (strpos($path, ':[')) {
509
          list($path, $indexes) = explode(':[', $path);
510
511
          $indexes = rtrim($indexes, ']');
512
513
          if (strpos($indexes, '][')) {
514
            $indexesInFiles = [];
515
516
            $indexes = explode('][', $indexes);
517
518
            foreach ($indexes as $index) {
519
              if (!empty($indexesInFiles)) {
520
                $indexesInFiles = $indexesInFiles[$index];
521
522
              } else {
523
                $indexesInFiles = $this->app->file->call($path . '.php')[$index];
524
              }
525
            }
526
            $files += $indexesInFiles;
527
          } else {
528
            $files += $this->app->file->call($path . '.php')[$indexes];
529
          }
530
        } else {
531
          $files += $this->app->file->call($path . '.php');
532
        }
533
        if ($getFrom === 'keys') {
534
          $final += array_keys($files);
535
        } else {
536
          $final += array_values($files);
537
        }
538
      } else {
539
        array_push($final, $character);
540
      }
541
    }
542
543
    if (!in_array($value, $final)) {
544
      $msg = $msg ?: 'wrong value';
545
546
      $this->addError($this->input, $msg);
547
    }
548
    return $this;
549
  }
550
551
  /**
552
   * Determine if the input value should equal length
553
   *
554
   * @param int $length
555
   * @param string $msg
556
   * @return $this
557
   */
558
  public function length($length = null, $msg = null)
559
  {
560
    if ($length === false) return $this;
0 ignored issues
show
introduced by
The condition $length === false is always false.
Loading history...
561
562
    $value = $this->value();
563
564
    if (!$value && $value != '0') return $this;
565
566
    if (strlen($value) !== $length) {
567
      $msg = $msg ?: `this field can be just ${length} charachter`;
568
569
      $this->addError($this->input, $msg);
570
    }
571
    return $this;
572
  }
573
574
  /**
575
   * Determine if the input value should be at most the given length
576
   *
577
   * @param int $length
578
   * @param string $msg
579
   * @return $this
580
   */
581
  public function maxLen($length = null, $msg = null)
582
  {
583
    if ($length === false) return $this;
0 ignored issues
show
introduced by
The condition $length === false is always false.
Loading history...
584
585
    $value = $this->value();
586
587
    if (!$value && $value != '0') return $this;
588
589
    if (strlen($value) > $length) {
590
      $msg = $msg ?: "this field can be maximum $length charachter";
591
592
      $this->addError($this->input, $msg);
593
    }
594
    return $this;
595
  }
596
597
  /**
598
   * Determine if the input value should be at least the given length
599
   *
600
   * @param int $length
601
   * @param string $msg
602
   * @return $this
603
   */
604
  public function minLen($length = null, $msg = null)
605
  {
606
    if ($length === false) return $this;
0 ignored issues
show
introduced by
The condition $length === false is always false.
Loading history...
607
608
    $value = $this->value();
609
610
    if (!$value && $value != '0') return $this;
611
612
    if (strlen($value) < $length) {
613
      $msg = $msg ?: "this field can be minimum $length charachter";
614
615
      $this->addError($this->input, $msg);
616
    }
617
    return $this;
618
  }
619
620
  /**
621
   * Determine if the $input matches the given input
622
   *
623
   * @param string $input
624
   * @param string $msg
625
   * @return $this
626
   */
627
  public function match($input, $msg = null)
628
  {
629
    if ($input === false) return $this;
0 ignored issues
show
introduced by
The condition $input === false is always false.
Loading history...
630
631
    $value = $this->value();
632
633
    $valueConfirm = $this->app->request->post($input);
634
635
    if ($value && $valueConfirm) {
636
      if ($value !== $valueConfirm) {
637
        $msg = $msg ?: 'passwords doesn\'t match';
638
639
        $this->addError('match', $msg);
640
      }
641
    }
642
    return $this;
643
  }
644
645
  /**
646
   * Determine if the input is unique in database
647
   *
648
   * @param array $data
649
   * @param string $msg
650
   * @return $this
651
   */
652
  public function unique($data = [], $msg = null)
653
  {
654
    if ($data === false) return $this;
0 ignored issues
show
introduced by
The condition $data === false is always false.
Loading history...
655
656
    $value = $this->value();
657
658
    if (!$data) return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression $data of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
659
660
    if (is_array($data)) {
0 ignored issues
show
introduced by
The condition is_array($data) is always true.
Loading history...
661
      list($table, $column) = $data;
662
    } else {
663
      $table = $data;
664
      $column = $this->input;
665
    }
666
667
    $result = $this->app->db->select($column)->from($table)->where($column . ' = ? ', $value)->fetch();
668
669
    if ($result) {
670
      $msg = $msg ?: sprintf('%s is already exist', ucfirst($this->input));
671
672
      $this->addError($this->input, $msg);
673
    }
674
    return $this;
675
  }
676
677
  /**
678
   * Determine if all inputs are valid
679
   *
680
   * @return bool
681
   */
682
  public function passes()
683
  {
684
    return empty($this->errors);
685
  }
686
687
  /**
688
   * Determine if there are any invalid inputs
689
   *
690
   * @return bool
691
   */
692
  public function fails()
693
  {
694
    return !empty($this->errors);
695
  }
696
697
  /**
698
   * Determine if the given input has previous errors
699
   *
700
   * @param string $input
701
   */
702
  private function hasError($input)
703
  {
704
    return array_key_exists($input, $this->errors);
705
  }
706
707
  /**
708
   * Add input error
709
   *
710
   * @param string $inputName
711
   * @param string $msg
712
   * @return void
713
   */
714
  public function addError($input, $msg)
715
  {
716
    if (!$this->hasError($input)) $this->errors[$input] = $msg;
717
  }
718
719
  /**
720
   * Get all errors
721
   *
722
   * @return array
723
   */
724
  public function getErrors()
725
  {
726
    return $this->errors;
727
  }
728
}
729