Passed
Branch master (f5823a)
by refat
04:00
created

Validation::charactersMsg()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 3
eloc 4
c 1
b 1
f 0
nc 2
nop 3
dl 0
loc 6
rs 10
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 mix
0 ignored issues
show
Bug introduced by
The type System\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...
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
    $re = "/^[0-9\\s$chars$langsRegex]*$/u";
306
    if (!preg_match($re, $value)) {
307
      $msg = $this->charactersMsg($chars, $languages, $msg);
308
      $this->addError($this->input, $msg);
309
    }
310
    return $this;
311
  }
312
313
  private function charactersMsg($chars, $languages, $msg)
314
  {
315
    $chars = $this->charactersFormatCharsMsg($chars);
316
    $languages = $languages ? "[ $languages ]" : '';
317
    $msg = $msg ?: "just $chars $languages letters can be used";
318
    return $msg;
319
  }
320
321
  private function charactersFormatCharsRegex($chars)
322
  {
323
    if (strlen($chars) > 1) {
324
      $chars = str_split($chars);
325
      $chars = "\\" . implode('|\\', $chars);
326
    }
327
    return $chars;
328
  }
329
330
  private function charactersFormatCharsMsg($chars)
331
  {
332
    $chars = explode('\\', $chars);
333
    $chars = implode('', $chars);
334
    $chars = $chars ? "[ $chars ] and" : '';
335
    return $chars;
336
  }
337
338
  private function charactersvariables($excepts, $value)
339
  {
340
    $characters = new Characters($excepts);
341
    $chars = $characters->getChars();
342
    $langsRegex = $characters->getLangsRegex();
343
    $languages = $characters->getLanguages();
344
    $times = $characters->getTimes();
345
    $atFirst = $characters->getAtFirst();
346
    $atEnd = $characters->getAtEnd();
347
    $between = $characters->getBetween();
348
    $methods = $this->charactersMethods([
349
      "times" => $times,
350
      "atFirst" => $atFirst,
351
      "atEnd" => $atEnd,
352
      "between" => $between,
353
      "chars" => $chars,
354
      "value" => $value,
355
    ]);
356
357
    return [
358
      'characters' => $characters,
359
      'chars' => $chars,
360
      'langsRegex' => $langsRegex,
361
      'languages' => $languages,
362
      'times' => $times,
363
      'atFirst' => $atFirst,
364
      'atEnd' => $atEnd,
365
      'between' => $between,
366
      'methods' => $methods,
367
    ];
368
  }
369
370
  private function charactersMethods($args)
371
  {
372
    extract($args);
373
    return [
374
      'charactersTimes' => [
375
        [$times, $chars, $value],
376
        'charachters are too many',
377
      ],
378
      'charactersAtFirst' => [
379
        [$atFirst, $chars, $value],
380
        'charachters cant be at the first',
381
      ],
382
      'charactersAtEnd' => [
383
        [$atEnd, $chars, $value],
384
        'charachters cant be at the end',
385
      ],
386
      'charactersBetween' => [
387
        [$between, $chars, $value],
388
        'charachters cant be between',
389
      ],
390
    ];
391
  }
392
393
  private function charactersTimes($times, $chars, $value)
394
  {
395
    if ($times > 0) {
396
      $chars = $this->charactersFormatCharsRegex($chars);
397
      $re = "/($chars)/";
398
      if (preg_match($re, $value) && preg_match_all($re, $value) > $times) {
399
        return true;
400
      }
401
      return false;
402
    }
403
  }
404
405
  private function charactersAtFirst($atFirst, $chars, $value)
406
  {
407
    if ($atFirst === false) {
408
      $chars = $this->charactersFormatCharsRegex($chars);
409
      $re = "/^($chars" . "|\\s+\\$chars)/";
410
      if (preg_match_all($re, $value)) {
411
        return true;
412
      }
413
      return false;
414
    }
415
  }
416
417
  private function charactersAtEnd($atEnd, $chars, $value)
418
  {
419
    if ($atEnd === false) {
420
      $chars = $this->charactersFormatCharsRegex($chars);
421
      $re = "/($chars" . "|\\$chars\\s+)$/";
422
      if (preg_match_all($re, $value)) {
423
        return true;
424
      }
425
      return false;
426
    }
427
  }
428
429
  private function charactersBetween($between, $chars, $value)
430
  {
431
    if ($between === false) {
432
      $chars = $this->charactersFormatCharsRegex($chars);
433
      $re = "/.+(${chars})(.+|\\s)/";
434
      if (preg_match_all($re, $value)) {
435
        return true;
436
      }
437
      return false;
438
    }
439
  }
440
441
  private function checkForErrorsInCharactersMethods($methods, $msg)
442
  {
443
    foreach ($methods as $method => $options) {
444
      if (call_user_func_array(array($this, $method), $options[0])) {
445
        $msg = $msg ?: $options[1];
446
        $this->addError($this->input, $msg);
447
        return true;
448
      }
449
    }
450
    return false;
451
  }
452
453
  /**
454
   * Determine if the input has spaces between the letters or the words
455
   *
456
   * @param bool $call
457
   * @param string $msg
458
   * @return $this
459
   */
460
  public function noSpaces($call = true, $msg = null)
461
  {
462
    if ($call === false) return $this;
463
464
    $value = $this->value();
465
466
    if (!$value && $value != '0') return $this;
467
468
    if (preg_match('/\s/', $value)) {
469
      $msg = $msg ?: 'spaces are not allow';
470
471
      $this->addError($this->input, $msg);
472
    }
473
    return $this;
474
  }
475
476
  /**
477
   * Determine if the given input has the value that are passed
478
   *
479
   * @param array $characters
480
   * @param string $msg
481
   * @return $this
482
   */
483
  public function containJust($characters = [], $msg = null)
484
  {
485
    if ($characters === false) return $this;
0 ignored issues
show
introduced by
The condition $characters === false is always false.
Loading history...
486
487
    $value = $this->value();
488
489
    if (!$value && $value != '0') return $this;
490
491
    if (!is_array($characters) && $characters !== '') {
0 ignored issues
show
introduced by
The condition is_array($characters) is always true.
Loading history...
492
      $characters = [$characters];
493
    }
494
495
    $path = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $path is dead and can be removed.
Loading history...
496
    $indexes = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $indexes is dead and can be removed.
Loading history...
497
498
    $files = [];
499
    $final = [];
500
501
    foreach ($characters as $key => $character) {
502
      if (strpos($character, 'path:') === 0) {
503
        unset($characters[$key]);
504
505
        $path = substr($character, 5);
506
507
        $getFrom = 'value';
508
509
        if (strpos($path, '::')) {
510
          list($path, $getFrom) = explode('::', $path);
511
        }
512
513
        if (strpos($path, ':[')) {
514
          list($path, $indexes) = explode(':[', $path);
515
516
          $indexes = rtrim($indexes, ']');
517
518
          if (strpos($indexes, '][')) {
519
            $indexesInFiles = [];
520
521
            $indexes = explode('][', $indexes);
522
523
            foreach ($indexes as $index) {
524
              if (!empty($indexesInFiles)) {
525
                $indexesInFiles = $indexesInFiles[$index];
526
527
              } else {
528
                $indexesInFiles = $this->app->file->call($path . '.php')[$index];
529
              }
530
            }
531
            $files += $indexesInFiles;
532
          } else {
533
            $files += $this->app->file->call($path . '.php')[$indexes];
534
          }
535
        } else {
536
          $files += $this->app->file->call($path . '.php');
537
        }
538
        if ($getFrom === 'keys') {
539
          $final += array_keys($files);
540
        } else {
541
          $final += array_values($files);
542
        }
543
      } else {
544
        array_push($final, $character);
545
      }
546
    }
547
548
    if (!in_array($value, $final)) {
549
      $msg = $msg ?: 'wrong value';
550
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