Passed
Branch master (7fff21)
by refat
05:12
created

Validator::require()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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