Passed
Branch master (7c8e9a)
by refat
04:09
created

Validation::charactersAtEnd()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 3
nop 3
dl 0
loc 9
rs 10
c 0
b 0
f 0
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
    $characters = new Characters($excepts);
301
    $chars = $characters->getChars();
302
    $langsRegex = $characters->getLangsRegex();
303
    $languages = $characters->getLanguages();
304
    $times = $characters->getTimes();
305
    $atFirst = $characters->getAtFirst();
306
    $atEnd = $characters->getAtEnd();
307
    $between = $characters->getBetween();
308
    $methods = $this->charactersMethods([
309
      "times" => $times,
310
      "atFirst" => $atFirst,
311
      "atEnd" => $atEnd,
312
      "between" => $between,
313
      "chars" => $chars,
314
      "value" => $value,
315
    ]);
316
317
    foreach($methods as $method => $options) {
318
      if (call_user_func_array(array($this, $method), $options[0])) {
319
        $msg = $msg ?: $options[1];
320
        $this->addError($this->input, $msg);
321
        return $this;
322
      }
323
    }
324
325
    $re = "/^[0-9\\s$chars$langsRegex]*$/u";
326
    if (!preg_match($re, $value)) {
327
      $chars = $this->charactersFormatCharsMsg($chars);
328
      $languages = $languages ? "[ $languages ]" : '';
329
      $msg = $msg ?: "just $chars $languages letters can be used";
330
      $this->addError($this->input, $msg);
331
    }
332
    return $this;
333
  }
334
335
  private function charactersFormatCharsRegex($chars)
336
  {
337
    if (strlen($chars) > 1) {
338
      $chars = str_split($chars);
339
      $chars = "\\" . implode('|\\', $chars);
340
    }
341
    return $chars;
342
  }
343
344
  private function charactersFormatCharsMsg($chars)
345
  {
346
    $chars =  explode('\\', $chars);
347
    $chars =  implode('', $chars);
348
    $chars = $chars ? "[ $chars ] and" : '';
349
    return $chars;
350
  }
351
352
  private function charactersMethods($args)
353
  {
354
    extract($args);
355
    return [
356
      'charactersTimes' => [
357
        [$times, $chars, $value],
358
        'charachters are too many',
359
      ],
360
      'charactersAtFirst' => [
361
        [$atFirst, $chars, $value],
362
        'charachters cant be at the first',
363
      ],
364
      'charactersAtEnd' => [
365
        [$atEnd, $chars, $value],
366
        'charachters cant be at the end',
367
      ],
368
      'charactersBetween' => [
369
        [$between, $chars, $value],
370
        'charachters cant be between',
371
      ],
372
    ];
373
  }
374
375
  private function charactersTimes($times, $chars, $value)
376
  {
377
    if ($times > 0) {
378
      $chars = $this->charactersFormatCharsRegex($chars);
379
      $re = "/($chars)/";
380
      if (preg_match($re, $value) && preg_match_all($re, $value) > $times) {
381
        return true;
382
      }
383
      return false;
384
    }
385
  }
386
387
  private function charactersAtFirst($atFirst, $chars, $value)
388
  {
389
    if ($atFirst === false) {
390
      $chars = $this->charactersFormatCharsRegex($chars);
391
      $re = "/^($chars"."|\\s+\\$chars)/";
392
      if (preg_match_all($re, $value)) {
393
        return true;
394
      }
395
      return false;
396
    }
397
  }
398
399
  private function charactersAtEnd($atEnd, $chars, $value)
400
  {
401
    if ($atEnd === false) {
402
      $chars = $this->charactersFormatCharsRegex($chars);
403
      $re = "/($chars"."|\\$chars\\s+)$/";
404
      if (preg_match_all($re, $value)) {
405
        return true;
406
      }
407
      return false;
408
    }
409
  }
410
411
  private function charactersBetween($between, $chars, $value)
412
  {
413
    if ($between === false) {
414
      $chars = $this->charactersFormatCharsRegex($chars);
415
      $re = "/.+(${chars})(.+|\\s)/";
416
      if (preg_match_all($re, $value)) {
417
        return true;
418
      }
419
      return false;
420
    }
421
  }
422
423
  /**
424
   * Determine if the input has spaces between the letters or the words
425
   *
426
   * @param bool $call
427
   * @param string $msg
428
   * @return $this
429
   */
430
  public function noSpaces($call = true, $msg = null)
431
  {
432
    if ($call === false) return $this;
433
434
    $value = $this->value();
435
436
    if (!$value && $value != '0') return $this;
437
438
    if (preg_match('/\s/', $value)) {
439
      $msg = $msg ?: 'spaces are not allow';
440
441
      $this->addError($this->input, $msg);
442
    }
443
    return $this;
444
  }
445
446
  /**
447
   * Determine if the given input has the value that are passed
448
   *
449
   * @param array $characters
450
   * @param string $msg
451
   * @return $this
452
   */
453
  public function containJust($characters = [], $msg = null)
454
  {
455
    if ($characters === false) return $this;
0 ignored issues
show
introduced by
The condition $characters === false is always false.
Loading history...
456
457
    $value = $this->value();
458
459
    if (!$value && $value != '0') return $this;
460
461
    if (!is_array($characters) && $characters !== '') {
0 ignored issues
show
introduced by
The condition is_array($characters) is always true.
Loading history...
462
      $characters = [$characters];
463
    }
464
465
    $path = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $path is dead and can be removed.
Loading history...
466
    $indexes = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $indexes is dead and can be removed.
Loading history...
467
468
    $files = [];
469
    $final = [];
470
471
    foreach($characters as $key => $character) {
472
      if (strpos($character, 'path:') === 0) {
473
        unset($characters[$key]);
474
475
        $path = substr($character, 5);
476
477
        $getFrom = 'value';
478
479
        if (strpos($path, '::')) {
480
          list($path, $getFrom) = explode('::', $path);
481
        }
482
483
        if (strpos($path, ':[')) {
484
          list($path, $indexes) = explode(':[', $path);
485
486
          $indexes = rtrim($indexes, ']');
487
488
          if (strpos($indexes, '][')) {
489
            $indexesInFiles = [];
490
491
            $indexes = explode('][', $indexes);
492
493
            foreach ($indexes as $index) {
494
              if (!empty($indexesInFiles)) {
495
                $indexesInFiles = $indexesInFiles[$index];
496
497
              } else {
498
                $indexesInFiles = $this->app->file->call($path . '.php')[$index];
499
              }
500
            }
501
            $files += $indexesInFiles;
502
          } else {
503
            $files += $this->app->file->call($path . '.php')[$indexes];
504
          }
505
        } else {
506
          $files += $this->app->file->call($path . '.php');
507
        }
508
        if ($getFrom === 'keys') {
509
          $final += array_keys($files);
510
        } else {
511
          $final += array_values($files);
512
        }
513
      } else {
514
        array_push($final, $character);
515
      }
516
    }
517
518
    if (!in_array($value, $final)) {
519
      $msg = $msg ?: 'wrong value';
520
521
      $this->addError($this->input, $msg);
522
    }
523
    return $this;
524
  }
525
526
  /**
527
   * Determine if the input value should equal length
528
   *
529
   * @param int $length
530
   * @param string $msg
531
   * @return $this
532
   */
533
  public function length($length = null, $msg = null)
534
  {
535
    if ($length === false) return $this;
0 ignored issues
show
introduced by
The condition $length === false is always false.
Loading history...
536
537
    $value = $this->value();
538
539
    if (!$value && $value != '0') return $this;
540
541
    if (strlen($value) !== $length) {
542
      $msg = $msg ?: `this field can be just ${length} charachter`;
543
544
      $this->addError($this->input, $msg);
545
    }
546
    return $this;
547
  }
548
549
  /**
550
   * Determine if the input value should be at most the given length
551
   *
552
   * @param int $length
553
   * @param string $msg
554
   * @return $this
555
   */
556
  public function maxLen($length = null, $msg = null)
557
  {
558
    if ($length === false) return $this;
0 ignored issues
show
introduced by
The condition $length === false is always false.
Loading history...
559
560
    $value = $this->value();
561
562
    if (!$value && $value != '0') return $this;
563
564
    if (strlen($value) > $length) {
565
      $msg = $msg ?: "this field can be maximum $length charachter";
566
567
      $this->addError($this->input, $msg);
568
    }
569
    return $this;
570
  }
571
572
  /**
573
   * Determine if the input value should be at least the given length
574
   *
575
   * @param int $length
576
   * @param string $msg
577
   * @return $this
578
   */
579
  public function minLen($length = null, $msg = null)
580
  {
581
    if ($length === false) return $this;
0 ignored issues
show
introduced by
The condition $length === false is always false.
Loading history...
582
583
    $value = $this->value();
584
585
    if (!$value && $value != '0') return $this;
586
587
    if (strlen($value) < $length) {
588
      $msg = $msg ?: "this field can be minimum $length charachter";
589
590
      $this->addError($this->input, $msg);
591
    }
592
    return $this;
593
  }
594
595
  /**
596
   * Determine if the $input matches the given input
597
   *
598
   * @param string $input
599
   * @param string $msg
600
   * @return $this
601
   */
602
  public function match($input, $msg = null)
603
  {
604
    if ($input === false) return $this;
0 ignored issues
show
introduced by
The condition $input === false is always false.
Loading history...
605
606
    $value = $this->value();
607
608
    $valueConfirm = $this->app->request->post($input);
609
610
    if ($value && $valueConfirm) {
611
      if ($value !== $valueConfirm) {
612
        $msg = $msg ?: 'passwords doesn\'t match';
613
614
        $this->addError('match', $msg);
615
      }
616
    }
617
    return $this;
618
  }
619
620
  /**
621
   * Determine if the input is unique in database
622
   *
623
   * @param array $data
624
   * @param string $msg
625
   * @return $this
626
   */
627
  public function unique($data = [], $msg = null)
628
  {
629
    if ($data === false) return $this;
0 ignored issues
show
introduced by
The condition $data === false is always false.
Loading history...
630
631
    $value = $this->value();
632
633
    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...
634
635
    if (is_array($data)) {
0 ignored issues
show
introduced by
The condition is_array($data) is always true.
Loading history...
636
      list($table, $column) = $data;
637
    } else {
638
      $table = $data;
639
      $column = $this->input;
640
    }
641
642
    $result = $this->app->db->select($column)->from($table)->where($column . ' = ? ', $value)->fetch();
643
644
    if ($result) {
645
      $msg = $msg ?: sprintf('%s is already exist', ucfirst($this->input));
646
647
      $this->addError($this->input, $msg);
648
    }
649
    return $this;
650
  }
651
652
  /**
653
   * Determine if all inputs are valid
654
   *
655
   * @return bool
656
   */
657
  public function passes()
658
  {
659
    return empty($this->errors);
660
  }
661
662
  /**
663
   * Determine if there are any invalid inputs
664
   *
665
   * @return bool
666
   */
667
  public function fails()
668
  {
669
    return !empty($this->errors);
670
  }
671
672
  /**
673
   * Determine if the given input has previous errors
674
   *
675
   * @param string $input
676
   */
677
  private function hasError($input)
678
  {
679
    return array_key_exists($input, $this->errors);
680
  }
681
682
  /**
683
   * Add input error
684
   *
685
   * @param string $inputName
686
   * @param string $msg
687
   * @return void
688
   */
689
  public function addError($input, $msg)
690
  {
691
    if (!$this->hasError($input)) $this->errors[$input] = $msg;
692
  }
693
694
  /**
695
   * Get all errors
696
   *
697
   * @return array
698
   */
699
  public function getErrors()
700
  {
701
    return $this->errors;
702
  }
703
}
704