Passed
Branch master (7ba29e)
by refat
03:38
created

Validation::dateMethods()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 15
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 12
c 0
b 0
f 0
nc 4
nop 1
dl 0
loc 15
rs 9.5555
1
<?php
2
3
namespace System;
4
use DateTime;
5
use System\Date;
6
7
class Validation
8
{
9
  /**
10
   * Application Object
11
   *
12
   * @var \System\Application
13
   */
14
  private $app;
15
16
  /**
17
   * Input name
18
   *
19
   * @var string
20
   */
21
  private $input;
22
23
  /**
24
   * Input value
25
   *
26
   * @var string
27
   */
28
  private $value;
29
30
  /**
31
   * Errors container
32
   *
33
   * @var array
34
   */
35
  private $errors = [];
36
37
  /**
38
   * Constructor
39
   *
40
   * @param \System\Application $app
41
   */
42
  public function __construct(Application $app)
43
  {
44
    $this->app = $app;
45
  }
46
47
  public function input($input, $request = 'post')
48
  {
49
    $this->input = $input;
50
51
    $this->value = $this->app->request->$request($this->input);
52
53
    return $this;
54
  }
55
56
  /**
57
   * Get the value for the input name
58
   *
59
   * @return mixed
60
   */
61
  private function value()
62
  {
63
    return mb_strtolower($this->value);
64
  }
65
66
  /**
67
   * Determine if the input is not empty
68
   *
69
   * @param bool $call
70
   * @param string $msg
71
   * @return $this
72
   */
73
  public function require($call = true, $msg = null)
74
  {
75
    if ($call === false) return $this;
76
77
    $value = $this->value();
78
79
    if ($value === '' || $value === null) {
80
      $msg = $msg ?: 'this field is required';
81
82
      $this->addError($this->input, $msg);
83
    }
84
    return $this;
85
  }
86
87
  /**
88
   * Call the function by given $type
89
   *
90
   * @param string $type
91
   * @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...
92
   */
93
  public function type($type)
94
  {
95
    return $this->$type();
96
  }
97
98
  /**
99
   * Determine if the input is valid email
100
   *
101
   * @param bool $call
102
   * @param string $msg
103
   * @return $this
104
   */
105
  public function email($call = true, $msg = null)
106
  {
107
    if ($call === false) return $this;
108
109
    $value = $this->value();
110
111
    if (!$value && $value != '0') return $this;
112
113
    if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
114
      $msg = $msg ?: 'e-mail is not valid';
115
116
      $this->addError($this->input, $msg);
117
    }
118
    return $this;
119
  }
120
121
  /**
122
   * Determine if the input is an image
123
   *
124
   * @param bool $call
125
   * @param string $customErrorMessage
126
   * @return $this
127
   */
128
  public function image($call = true, $msg = null)
129
  {
130
    if ($call === false) return $this;
131
132
    $file = $this->app->request->file($this->input);
133
134
    if (!$file->exists()) return $this;
135
136
    if (!$file->isImage()) {
137
      $msg = $msg ?: 'image is not valid';
138
139
      $this->addError($this->input, $msg);
140
    }
141
    return $this;
142
  }
143
144
  /**
145
   * Determine if the input has number
146
   *
147
   * @param bool $call
148
   * @param string $msg
149
   * @return $this
150
   */
151
  public function number($call = true, $msg = null)
152
  {
153
    if ($call === false) return $this;
154
155
    $value = $this->value();
156
157
    if (!$value && $value != '0') return $this;
158
159
    if (!is_numeric($value)) {
160
      $msg = $msg ?: 'this field must be a number';
161
162
      $this->addError($this->input, $msg);
163
    }
164
    return $this;
165
  }
166
167
  /**
168
   * Determine if the input has float value
169
   *
170
   * @param bool $call
171
   * @param string $msg
172
   * @return $this
173
   */
174
  public function float($call = true, $msg = null)
175
  {
176
    if ($call === false) return $this;
177
178
    $value = $this->value();
179
180
    if (!$value && $value != '0') return $this;
181
182
    if (!is_float($value)) {
0 ignored issues
show
introduced by
The condition is_float($value) is always false.
Loading history...
183
      $msg = $msg ?: "this field must be a float number";
184
185
      $this->addError($this->input, $msg);
186
    }
187
    return $this;
188
  }
189
190
  /**
191
   * Determine if the input is a date
192
   * Determine if the input between the range if the $options['start']
193
   * or the $options ['end'] is exists
194
   *
195
   * @param string $options
196
   * @param string $msg
197
   * @return $this
198
   */
199
  public function date($options = [], $msg = null)
200
  {
201
    if ($options === false) return $this;
0 ignored issues
show
introduced by
The condition $options === false is always false.
Loading history...
202
203
    $value = $this->value();
204
205
    if (!$value && $value != '0') return $this;
206
207
    $options = json_encode($options);
208
    $options = json_decode($options);
209
210
    extract($this->dateMethods($options));
211
212
    $date = new Date($options, $value);
213
214
    if (!$date->$method()) {
215
      $this->addError($this->input, $msg);
216
    }
217
    return $this;
218
  }
219
220
  private function dateMethods($options)
221
  {
222
    $method = null;
223
    $msg = null;
224
    if ($options->start && $options->end) {
225
      $method = 'isDateBetween';
226
      $msg = 'this field must be between ' . $options->start  . ' and ' . $options->end;
227
    } elseif ($options->start) {
228
      $method = 'minimum';
229
      $msg = 'the date can\'t be under ' . $options->start;
230
    } elseif ($options->end) {
231
      $method = 'maximum';
232
      $msg = 'the date can\'t be above ' . $options->end;
233
    }
234
    return array ('method' => $method,'msg'=> $msg);
235
  }
236
237
  /**
238
   * Determine if the input has simple text
239
   *
240
   * @param bool $call
241
   * @param string $msg
242
   * @return $this
243
   */
244
  public function text($call = true, $msg = null)
245
  {
246
    if ($call === false) return $this;
247
248
    $value = $this->value();
249
250
    if (!$value && $value != '0') return $this;
251
252
    if (!is_string($value)) {
0 ignored issues
show
introduced by
The condition is_string($value) is always true.
Loading history...
253
      $msg = $msg ?: 'the field must be a text';
254
255
      $this->addError($this->input, $msg);
256
    }
257
    return $this;
258
  }
259
260
  /**
261
   * Determine if the input has pure string
262
   *
263
   * @param bool $call
264
   * @param string $msg
265
   * @return $this
266
   */
267
  public function noNumbers($call = true, $msg = null)
268
  {
269
    if ($call === false) return $this;
270
271
    $value = $this->value();
272
273
    if (!$value && $value != '0') return $this;
274
275
    if (preg_match('~[0-9]~', $value)) {
276
      $msg = $msg ?: 'numbers are not allow';
277
278
      $this->addError($this->input, $msg);
279
    }
280
281
    return $this;
282
  }
283
284
  private function languages($language)
285
  {
286
    $languages = [
287
      'all' => '\\p{L}',
288
      'arabic' =>  '\\x{0621}-\\x{064A}\\x{0660}-\\x{0669} ُ ْ َ ِ ّ~ ً ٍ ٌ',
289
      'english' => 'a-z',
290
      'spanish' => 'a-zñ',
291
      'french' => 'a-zàâçéèêëîïôûùüÿñæœ',
292
      'german' => 'a-zäüöß',
293
    ];
294
    return $languages[$language];
295
  }
296
297
  /**
298
   * Determine if the input has pure string
299
   *
300
   * @param array $excepts
301
   * @param string $msg
302
   * @return $this
303
   */
304
  public function characters($excepts, $msg = null)
305
  {
306
    if ($excepts === false) return $this;
0 ignored issues
show
introduced by
The condition $excepts === false is always false.
Loading history...
307
308
    $value = $this->value();
309
310
    if (!$value && $value != '0') return $this;
311
312
    $chars = '';
313
    $times = null;
314
    $atFirst = null;
315
    $atEnd = null;
316
    $between = null;
317
    $langsRegex = '';
318
    $languages = '';
319
320
    if (is_object($excepts) && count((array) $excepts)) {
0 ignored issues
show
introduced by
The condition is_object($excepts) is always false.
Loading history...
321
      if (is_string($excepts->chars)) {
322
        if (preg_match('/,/', $excepts->chars) && preg_match_all('/,/', $excepts->chars) > 1) {
323
          $chars = explode(',', $excepts->chars);
324
          $chars = "\\" . implode('\\', $chars);
325
        } else {
326
          $chars = str_split($excepts->chars);
327
          $chars = "\\" . implode('\\', $chars);
328
        }
329
      } else if (is_object($excepts->chars) && count((array) $excepts->chars)) {
330
        $chars = $excepts->chars->value;
331
        if (is_array($chars)) {
332
          $chars = implode('', $chars);
333
        } else if (is_string($chars)) {
334
          if (preg_match('/,/', $chars) && preg_match_all('/,/', $chars) > 1) {
335
            $chars = explode(',', $chars);
336
            $chars = "\\" . implode('\\', $chars);
337
          } else {
338
            $chars = str_split($chars);
339
            $chars = "\\" . implode('\\', $chars);
340
          }
341
        }
342
        $times = $excepts->chars->times ?? null;
343
        $atFirst = $excepts->chars->atFirst;
344
        $atEnd = $excepts->chars->atEnd;
345
        $between = $excepts->chars->between;
346
      }
347
348
      if (is_array($excepts->languages)) {
349
        foreach($excepts->languages as $language) {
350
          $langsRegex .= $this->languages(trim($language));
351
          $languages .= "$language, ";
352
        }
353
        $languages = rtrim($languages, ", ");
354
      } else if (is_string($excepts->languages)) {
355
        if (preg_match('/,/', $excepts->languages) && preg_match_all('/,/', $excepts->languages)) {
356
          foreach(explode(',', $excepts->languages) as $language) {
357
            $langsRegex .= $this->languages(trim($language));
358
            $languages .= "$language, ";
359
          }
360
          $languages = rtrim($languages, ", ");
361
        } else {
362
          $langsRegex = $this->languages(trim($excepts->languages));
363
          $languages = $excepts->languages;
364
        }
365
      }
366
    }
367
368
    if ($times > 0) {
369
      $splitChars = $chars;
370
      if (strlen($chars) > 1) {
371
        $splitChars = str_split($splitChars);
372
        $splitChars = "\\" . implode('|\\', $splitChars);
373
      }
374
      $re1 = "/($splitChars)/";
375
      if (preg_match($re1, $value) && preg_match_all($re1, $value) > $times) {
376
        $msg = $msg ?: 'charachters are too many';
377
378
        $this->addError($this->input, $msg);
379
        return $this;
380
      }
381
    }
382
383
    if ($atFirst === false) {
0 ignored issues
show
introduced by
The condition $atFirst === false is always true.
Loading history...
384
      $splitChars = $chars;
385
      if (strlen($chars) > 1) {
386
        $splitChars = str_split($splitChars);
387
        $splitChars = "\\" . implode('|\\', $splitChars);
388
      }
389
      $re2 = "/^($splitChars"."|\\s+\\$splitChars)/";
390
      if (preg_match_all($re2, $value)) {
391
        $msg = $msg ?: 'charachters cant be in the first';
392
393
        $this->addError($this->input, $msg);
394
        return $this;
395
      }
396
    }
397
398
    if ($atEnd === false) {
399
      $splitChars = $chars;
400
      if (strlen($chars) > 1) {
401
        $splitChars = str_split($splitChars);
402
        $splitChars = "\\" . implode('|\\', $splitChars);
403
      }
404
      $re3 = "/($splitChars"."|\\$splitChars\\s+)$/";
405
      if (preg_match_all($re3, $value)) {
406
        $msg = $msg ?: 'charachters cant be in the end';
407
408
        $this->addError($this->input, $msg);
409
        return $this;
410
      }
411
    }
412
413
    if ($between === false) {
414
      $splitChars = $chars;
415
      if (strlen($chars) > 1) {
416
        $splitChars = str_split($splitChars);
417
        $splitChars = "\\" . implode('|\\', $splitChars);
418
      }
419
      $re4 = "/.+(${splitChars})(.+|\\s)/";
420
      if (preg_match_all($re4, $value)) {
421
        $msg = $msg ?: 'charachters cant be between';
422
423
        $this->addError($this->input, $msg);
424
        return $this;
425
      }
426
    }
427
428
    if ($langsRegex) {
429
      if ($languages !== 'all' && preg_match_all('/a-z/i', $langsRegex) > 1) {
430
        $langsRegex = preg_replace('/a-z/i', '', $langsRegex);
431
        $langsRegex .= 'a-z';
432
      }
433
    } else {
434
      $languages = 'english';
435
      $langsRegex = $this->languages('english');
436
    }
437
438
    $re5 = "/^[0-9\\s$chars$langsRegex]*$/u";
439
    if (!preg_match($re5, $value)) {
440
      $chars =  explode('\\', $chars);
441
      $chars =  implode('', $chars);
442
      $chars = $chars ? "[ $chars ] and" : '';
443
      $languages = $languages ? "[ $languages ]" : '';
444
      $msg = $msg ?: "just $chars $languages letters can be used";
445
      $this->addError($this->input, $msg);
446
    }
447
    return $this;
448
  }
449
450
  /**
451
   * Determine if the input has spaces between the letters or the words
452
   *
453
   * @param bool $call
454
   * @param string $msg
455
   * @return $this
456
   */
457
  public function noSpaces($call = true, $msg = null)
458
  {
459
    if ($call === false) return $this;
460
461
    $value = $this->value();
462
463
    if (!$value && $value != '0') return $this;
464
465
    if (preg_match('/\s/', $value)) {
466
      $msg = $msg ?: 'spaces are not allow';
467
468
      $this->addError($this->input, $msg);
469
    }
470
    return $this;
471
  }
472
473
  /**
474
   * Determine if the given input has the value that are passed
475
   *
476
   * @param array $characters
477
   * @param string $msg
478
   * @return $this
479
   */
480
  public function containJust($characters = [], $msg = null)
481
  {
482
    if ($characters === false) return $this;
0 ignored issues
show
introduced by
The condition $characters === false is always false.
Loading history...
483
484
    $value = $this->value();
485
486
    if (!$value && $value != '0') return $this;
487
488
    if (!is_array($characters) && $characters !== '') {
0 ignored issues
show
introduced by
The condition is_array($characters) is always true.
Loading history...
489
      $characters = [$characters];
490
    }
491
492
    $path = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $path is dead and can be removed.
Loading history...
493
    $indexes = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $indexes is dead and can be removed.
Loading history...
494
495
    $files = [];
496
    $final = [];
497
498
    foreach($characters as $key => $character) {
499
      if (strpos($character, 'path:') === 0) {
500
        unset($characters[$key]);
501
502
        $path = substr($character, 5);
503
504
        $getFrom = 'value';
505
506
        if (strpos($path, '::')) {
507
          list($path, $getFrom) = explode('::', $path);
508
        }
509
510
        if (strpos($path, ':[')) {
511
          list($path, $indexes) = explode(':[', $path);
512
513
          $indexes = rtrim($indexes, ']');
514
515
          if (strpos($indexes, '][')) {
516
            $indexesInFiles = [];
517
518
            $indexes = explode('][', $indexes);
519
520
            foreach ($indexes as $index) {
521
              if (!empty($indexesInFiles)) {
522
                $indexesInFiles = $indexesInFiles[$index];
523
524
              } else {
525
                $indexesInFiles = $this->app->file->call($path . '.php')[$index];
526
              }
527
            }
528
            $files += $indexesInFiles;
529
          } else {
530
            $files += $this->app->file->call($path . '.php')[$indexes];
531
          }
532
        } else {
533
          $files += $this->app->file->call($path . '.php');
534
        }
535
        if ($getFrom === 'keys') {
536
          $final += array_keys($files);
537
        } else {
538
          $final += array_values($files);
539
        }
540
      } else {
541
        array_push($final, $character);
542
      }
543
    }
544
545
    if (!in_array($value, $final)) {
546
      $msg = $msg ?: 'wrong value';
547
548
      $this->addError($this->input, $msg);
549
    }
550
    return $this;
551
  }
552
553
  /**
554
   * Determine if the input value should equal length
555
   *
556
   * @param int $length
557
   * @param string $msg
558
   * @return $this
559
   */
560
  public function length($length = null, $msg = null)
561
  {
562
    if ($length === false) return $this;
0 ignored issues
show
introduced by
The condition $length === false is always false.
Loading history...
563
564
    $value = $this->value();
565
566
    if (!$value && $value != '0') return $this;
567
568
    if (strlen($value) !== $length) {
569
      $msg = $msg ?: `this field can be just ${length} charachter`;
570
571
      $this->addError($this->input, $msg);
572
    }
573
    return $this;
574
  }
575
576
  /**
577
   * Determine if the input value should be at most the given length
578
   *
579
   * @param int $length
580
   * @param string $msg
581
   * @return $this
582
   */
583
  public function maxLen($length = null, $msg = null)
584
  {
585
    if ($length === false) return $this;
0 ignored issues
show
introduced by
The condition $length === false is always false.
Loading history...
586
587
    $value = $this->value();
588
589
    if (!$value && $value != '0') return $this;
590
591
    if (strlen($value) > $length) {
592
      $msg = $msg ?: "this field can be maximum $length charachter";
593
594
      $this->addError($this->input, $msg);
595
    }
596
    return $this;
597
  }
598
599
  /**
600
   * Determine if the input value should be at least the given length
601
   *
602
   * @param int $length
603
   * @param string $msg
604
   * @return $this
605
   */
606
  public function minLen($length = null, $msg = null)
607
  {
608
    if ($length === false) return $this;
0 ignored issues
show
introduced by
The condition $length === false is always false.
Loading history...
609
610
    $value = $this->value();
611
612
    if (!$value && $value != '0') return $this;
613
614
    if (strlen($value) < $length) {
615
      $msg = $msg ?: "this field can be minimum $length charachter";
616
617
      $this->addError($this->input, $msg);
618
    }
619
    return $this;
620
  }
621
622
  /**
623
   * Determine if the $input matches the given input
624
   *
625
   * @param string $input
626
   * @param string $msg
627
   * @return $this
628
   */
629
  public function match($input, $msg = null)
630
  {
631
    if ($input === false) return $this;
0 ignored issues
show
introduced by
The condition $input === false is always false.
Loading history...
632
633
    $value = $this->value();
634
635
    $valueConfirm = $this->app->request->post($input);
636
637
    if ($value && $valueConfirm) {
638
      if ($value !== $valueConfirm) {
639
        $msg = $msg ?: 'passwords doesn\'t match';
640
641
        $this->addError('match', $msg);
642
      }
643
    }
644
    return $this;
645
  }
646
647
  /**
648
   * Determine if the input is unique in database
649
   *
650
   * @param array $data
651
   * @param string $msg
652
   * @return $this
653
   */
654
  public function unique($data = [], $msg = null)
655
  {
656
    if ($data === false) return $this;
0 ignored issues
show
introduced by
The condition $data === false is always false.
Loading history...
657
658
    $value = $this->value();
659
660
    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...
661
662
    if (is_array($data)) {
0 ignored issues
show
introduced by
The condition is_array($data) is always true.
Loading history...
663
      list($table, $column) = $data;
664
    } else {
665
      $table = $data;
666
      $column = $this->input;
667
    }
668
669
    $result = $this->app->db->select($column)->from($table)->where($column . ' = ? ', $value)->fetch();
670
671
    if ($result) {
672
      $msg = $msg ?: sprintf('%s is already exist', ucfirst($this->input));
673
674
      $this->addError($this->input, $msg);
675
    }
676
    return $this;
677
  }
678
679
  /**
680
   * Determine if all inputs are valid
681
   *
682
   * @return bool
683
   */
684
  public function passes()
685
  {
686
    return empty($this->errors);
687
  }
688
689
  /**
690
   * Determine if there are any invalid inputs
691
   *
692
   * @return bool
693
   */
694
  public function fails()
695
  {
696
    return !empty($this->errors);
697
  }
698
699
  /**
700
   * Determine if the given input has previous errors
701
   *
702
   * @param string $input
703
   */
704
  private function hasError($input)
705
  {
706
    return array_key_exists($input, $this->errors);
707
  }
708
709
  /**
710
   * Add input error
711
   *
712
   * @param string $inputName
713
   * @param string $msg
714
   * @return void
715
   */
716
  public function addError($input, $msg)
717
  {
718
    if (!$this->hasError($input)) $this->errors[$input] = $msg;
719
  }
720
721
  /**
722
   * Get all errors
723
   *
724
   * @return array
725
   */
726
  public function getErrors()
727
  {
728
    return $this->errors;
729
  }
730
}
731