Completed
Push — 6.0 ( 3b655b...fa435c )
by liu
03:01
created

Validate::min()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 3
nop 2
dl 0
loc 11
ccs 0
cts 7
cp 0
crap 12
rs 10
c 0
b 0
f 0
1
<?php
2
// +----------------------------------------------------------------------
1 ignored issue
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: liu21st <[email protected]>
10
// +----------------------------------------------------------------------
11
declare (strict_types = 1);
12
13
namespace think;
14
15
use think\exception\ValidateException;
16
use think\validate\ValidateRule;
17
18
class Validate
1 ignored issue
show
Coding Style introduced by
Missing doc comment for class Validate
Loading history...
19
{
20
    /**
21
     * 自定义验证类型
22
     * @var array
23
     */
24
    protected $type = [];
25
26
    /**
27
     * 验证类型别名
28
     * @var array
29
     */
30
    protected $alias = [
31
        '>' => 'gt', '>=' => 'egt', '<' => 'lt', '<=' => 'elt', '=' => 'eq', 'same' => 'eq',
32
    ];
33
34
    /**
35
     * 当前验证规则
36
     * @var array
37
     */
38
    protected $rule = [];
39
40
    /**
41
     * 验证提示信息
42
     * @var array
43
     */
44
    protected $message = [];
45
46
    /**
47
     * 验证字段描述
48
     * @var array
49
     */
50
    protected $field = [];
51
52
    /**
53
     * 默认规则提示
54
     * @var array
55
     */
56
    protected $typeMsg = [
57
        'require'     => ':attribute require',
58
        'must'        => ':attribute must',
59
        'number'      => ':attribute must be numeric',
60
        'integer'     => ':attribute must be integer',
61
        'float'       => ':attribute must be float',
62
        'boolean'     => ':attribute must be bool',
63
        'email'       => ':attribute not a valid email address',
64
        'mobile'      => ':attribute not a valid mobile',
65
        'array'       => ':attribute must be a array',
66
        'accepted'    => ':attribute must be yes,on or 1',
67
        'date'        => ':attribute not a valid datetime',
68
        'file'        => ':attribute not a valid file',
69
        'image'       => ':attribute not a valid image',
70
        'alpha'       => ':attribute must be alpha',
71
        'alphaNum'    => ':attribute must be alpha-numeric',
72
        'alphaDash'   => ':attribute must be alpha-numeric, dash, underscore',
73
        'activeUrl'   => ':attribute not a valid domain or ip',
74
        'chs'         => ':attribute must be chinese',
75
        'chsAlpha'    => ':attribute must be chinese or alpha',
76
        'chsAlphaNum' => ':attribute must be chinese,alpha-numeric',
77
        'chsDash'     => ':attribute must be chinese,alpha-numeric,underscore, dash',
78
        'url'         => ':attribute not a valid url',
79
        'ip'          => ':attribute not a valid ip',
80
        'dateFormat'  => ':attribute must be dateFormat of :rule',
81
        'in'          => ':attribute must be in :rule',
82
        'notIn'       => ':attribute be notin :rule',
83
        'between'     => ':attribute must between :1 - :2',
84
        'notBetween'  => ':attribute not between :1 - :2',
85
        'length'      => 'size of :attribute must be :rule',
86
        'max'         => 'max size of :attribute must be :rule',
87
        'min'         => 'min size of :attribute must be :rule',
88
        'after'       => ':attribute cannot be less than :rule',
89
        'before'      => ':attribute cannot exceed :rule',
90
        'expire'      => ':attribute not within :rule',
91
        'allowIp'     => 'access IP is not allowed',
92
        'denyIp'      => 'access IP denied',
93
        'confirm'     => ':attribute out of accord with :2',
94
        'different'   => ':attribute cannot be same with :2',
95
        'egt'         => ':attribute must greater than or equal :rule',
96
        'gt'          => ':attribute must greater than :rule',
97
        'elt'         => ':attribute must less than or equal :rule',
98
        'lt'          => ':attribute must less than :rule',
99
        'eq'          => ':attribute must equal :rule',
100
        'unique'      => ':attribute has exists',
101
        'regex'       => ':attribute not conform to the rules',
102
        'method'      => 'invalid Request method',
103
        'token'       => 'invalid token',
104
        'fileSize'    => 'filesize not match',
105
        'fileExt'     => 'extensions to upload is not allowed',
106
        'fileMime'    => 'mimetype to upload is not allowed',
107
    ];
108
109
    /**
110
     * 当前验证场景
111
     * @var string
112
     */
113
    protected $currentScene;
114
115
    /**
116
     * 内置正则验证规则
117
     * @var array
118
     */
119
    protected $defaultRegex = [
120
        'alpha'       => '/^[A-Za-z]+$/',
121
        'alphaNum'    => '/^[A-Za-z0-9]+$/',
122
        'alphaDash'   => '/^[A-Za-z0-9\-\_]+$/',
123
        'chs'         => '/^[\x{4e00}-\x{9fa5}]+$/u',
124
        'chsAlpha'    => '/^[\x{4e00}-\x{9fa5}a-zA-Z]+$/u',
125
        'chsAlphaNum' => '/^[\x{4e00}-\x{9fa5}a-zA-Z0-9]+$/u',
126
        'chsDash'     => '/^[\x{4e00}-\x{9fa5}a-zA-Z0-9\_\-]+$/u',
127
        'mobile'      => '/^1[3-9][0-9]\d{8}$/',
128
        'idCard'      => '/(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}$)/',
129
        'zip'         => '/\d{6}/',
130
    ];
131
132
    /**
133
     * Filter_var 规则
134
     * @var array
135
     */
136
    protected $filter = [
137
        'email'   => FILTER_VALIDATE_EMAIL,
138
        'ip'      => [FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6],
139
        'integer' => FILTER_VALIDATE_INT,
140
        'url'     => FILTER_VALIDATE_URL,
141
        'macAddr' => FILTER_VALIDATE_MAC,
142
        'float'   => FILTER_VALIDATE_FLOAT,
143
    ];
144
145
    /**
146
     * 验证场景定义
147
     * @var array
148
     */
149
    protected $scene = [];
150
151
    /**
152
     * 验证失败错误信息
153
     * @var array
154
     */
155
    protected $error = [];
156
157
    /**
158
     * 是否批量验证
159
     * @var bool
160
     */
161
    protected $batch = false;
162
163
    /**
164
     * 验证失败是否抛出异常
165
     * @var bool
166
     */
167
    protected $failException = false;
168
169
    /**
170
     * 场景需要验证的规则
171
     * @var array
172
     */
173
    protected $only = [];
174
175
    /**
176
     * 场景需要移除的验证规则
177
     * @var array
178
     */
179
    protected $remove = [];
180
181
    /**
182
     * 场景需要追加的验证规则
183
     * @var array
184
     */
185
    protected $append = [];
186
187
    /**
188
     * 验证正则定义
189
     * @var array
190
     */
191
    protected $regex = [];
192
193
    /**
194
     * Db对象
195
     * @var Db
196
     */
197
    protected $db;
198
199
    /**
200
     * 语言对象
201
     * @var Lang
202
     */
203
    protected $lang;
204
205
    public static function __make(Lang $lang, Db $db)
2 ignored issues
show
Coding Style introduced by
Missing doc comment for function __make()
Loading history...
Coding Style introduced by
Method name "Validate::__make" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
Coding Style introduced by
Public method name "Validate::__make" must not be prefixed with an underscore
Loading history...
206
    {
207
        $instance = new static();
208
209
        $instance->lang = $lang;
210
        $instance->db   = $db;
211
        return $instance;
212
    }
213
214
    public function setLang(Lang $lang)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function setLang()
Loading history...
215
    {
216
        $this->lang = $lang;
217
    }
218
219
    public function setDb(Db $db)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function setDb()
Loading history...
220
    {
221
        $this->db = $db;
222
    }
223
224
    /**
225
     * 添加字段验证规则
226
     * @access protected
227
     * @param  string|array  $name  字段名称或者规则数组
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
228
     * @param  mixed         $rule  验证规则或者字段描述信息
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
229
     * @return $this
230
     */
231
    public function rule($name, $rule = '')
232
    {
233
        if (is_array($name)) {
234
            $this->rule = $name + $this->rule;
235
            if (is_array($rule)) {
236
                $this->field = array_merge($this->field, $rule);
237
            }
238
        } else {
239
            $this->rule[$name] = $rule;
240
        }
241
242
        return $this;
243
    }
244
245
    /**
246
     * 注册扩展验证(类型)规则
247
     * @access public
248
     * @param  string|array    $type  验证规则类型
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 2 found
Loading history...
249
     * @param  callable        $callback callback方法(或闭包)
250
     * @return $this
251
     */
252
    public function extend($type, callable $callback = null)
253
    {
254
        if (is_array($type)) {
255
            $this->type = array_merge($this->type, $type);
256
        } else {
257
            $this->type[$type] = $callback;
258
        }
259
260
        return $this;
261
    }
262
263
    /**
264
     * 设置验证规则的默认提示信息
265
     * @access public
266
     * @param  string|array  $type  验证规则类型名称或者数组
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
267
     * @param  string        $msg  验证提示信息
268
     * @return void
269
     */
270
    public function setTypeMsg($type, string $msg = null): void
271
    {
272
        if (is_array($type)) {
273
            $this->typeMsg = array_merge($this->typeMsg, $type);
274
        } else {
275
            $this->typeMsg[$type] = $msg;
276
        }
277
    }
278
279
    /**
280
     * 设置提示信息
281
     * @access public
282
     * @param  string|array  $name  字段名称
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 2 found
Loading history...
283
     * @param  string        $message 提示信息
284
     * @return Validate
285
     */
286
    public function message($name, string $message = '')
287
    {
288
        if (is_array($name)) {
289
            $this->message = array_merge($this->message, $name);
290
        } else {
291
            $this->message[$name] = $message;
292
        }
293
294
        return $this;
295
    }
296
297
    /**
298
     * 设置验证场景
299
     * @access public
300
     * @param  string  $name  场景名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
301
     * @return $this
302
     */
303
    public function scene(string $name)
304
    {
305
        // 设置当前场景
306
        $this->currentScene = $name;
307
308
        return $this;
309
    }
310
311
    /**
312
     * 判断是否存在某个验证场景
313
     * @access public
314
     * @param  string $name 场景名
315
     * @return bool
316
     */
317
    public function hasScene(string $name): bool
318
    {
319
        return isset($this->scene[$name]) || method_exists($this, 'scene' . $name);
320
    }
321
322
    /**
323
     * 设置批量验证
324
     * @access public
325
     * @param  bool $batch  是否批量验证
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
326
     * @return $this
327
     */
328
    public function batch(bool $batch = true)
329
    {
330
        $this->batch = $batch;
331
332
        return $this;
333
    }
334
335
    /**
336
     * 设置验证失败后是否抛出异常
337
     * @access protected
338
     * @param  bool $fail 是否抛出异常
339
     * @return $this
340
     */
341
    public function failException(bool $fail = true)
342
    {
343
        $this->failException = $fail;
344
345
        return $this;
346
    }
347
348
    /**
349
     * 指定需要验证的字段列表
350
     * @access public
351
     * @param  array $fields  字段名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
352
     * @return $this
353
     */
354
    public function only(array $fields)
355
    {
356
        $this->only = $fields;
357
358
        return $this;
359
    }
360
361
    /**
362
     * 移除某个字段的验证规则
363
     * @access public
364
     * @param  string|array  $field  字段名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
365
     * @param  mixed         $rule   验证规则 true 移除所有规则
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 3 found
Loading history...
366
     * @return $this
367
     */
368
    public function remove($field, $rule = null)
369
    {
370
        if (is_array($field)) {
371
            foreach ($field as $key => $rule) {
372
                if (is_int($key)) {
373
                    $this->remove($rule);
374
                } else {
375
                    $this->remove($key, $rule);
376
                }
377
            }
378
        } else {
379
            if (is_string($rule)) {
380
                $rule = explode('|', $rule);
381
            }
382
383
            $this->remove[$field] = $rule;
384
        }
385
386
        return $this;
387
    }
388
389
    /**
390
     * 追加某个字段的验证规则
391
     * @access public
392
     * @param  string|array  $field  字段名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
393
     * @param  mixed         $rule   验证规则
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 3 found
Loading history...
394
     * @return $this
395
     */
396
    public function append($field, $rule = null)
397
    {
398
        if (is_array($field)) {
399
            foreach ($field as $key => $rule) {
400
                $this->append($key, $rule);
401
            }
402
        } else {
403
            if (is_string($rule)) {
404
                $rule = explode('|', $rule);
405
            }
406
407
            $this->append[$field] = $rule;
408
        }
409
410
        return $this;
411
    }
412
413
    /**
414
     * 数据自动验证
415
     * @access public
416
     * @param  array $data  数据
417
     * @param  array $rules  验证规则
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
418
     * @return bool
419
     */
420
    public function check(array $data, array $rules = []): bool
421
    {
422
        $this->error = [];
423
424
        if (empty($rules)) {
425
            // 读取验证规则
426
            $rules = $this->rule;
427
        }
428
429
        if ($this->currentScene) {
430
            $this->getScene($this->currentScene);
431
        }
432
433
        foreach ($this->append as $key => $rule) {
434
            if (!isset($rules[$key])) {
435
                $rules[$key] = $rule;
436
            }
437
        }
438
439
        foreach ($rules as $key => $rule) {
440
            // field => 'rule1|rule2...' field => ['rule1','rule2',...]
441
            if (strpos($key, '|')) {
442
                // 字段|描述 用于指定属性名称
443
                list($key, $title) = explode('|', $key);
444
            } else {
445
                $title = $this->field[$key] ?? $key;
446
            }
447
448
            // 场景检测
449
            if (!empty($this->only) && !in_array($key, $this->only)) {
450
                continue;
451
            }
452
453
            // 获取数据 支持二维数组
454
            $value = $this->getDataValue($data, $key);
455
456
            // 字段验证
457
            if ($rule instanceof \Closure) {
458
                $result = call_user_func_array($rule, [$value, $data]);
459
            } elseif ($rule instanceof ValidateRule) {
460
                //  验证因子
461
                $result = $this->checkItem($key, $value, $rule->getRule(), $data, $rule->getTitle() ?: $title, $rule->getMsg());
462
            } else {
463
                $result = $this->checkItem($key, $value, $rule, $data, $title);
464
            }
465
466
            if (true !== $result) {
467
                // 没有返回true 则表示验证失败
468
                if (!empty($this->batch)) {
469
                    // 批量验证
470
                    if (is_array($result)) {
471
                        $this->error = array_merge($this->error, $result);
472
                    } else {
473
                        $this->error[$key] = $result;
474
                    }
475
                } elseif ($this->failException) {
476
                    throw new ValidateException($result);
477
                } else {
478
                    $this->error = $result;
479
                    return false;
480
                }
481
            }
482
        }
483
484
        if (!empty($this->error)) {
485
            if ($this->failException) {
486
                throw new ValidateException($this->error);
487
            }
488
            return false;
489
        }
490
491
        return true;
492
    }
493
494
    /**
495
     * 根据验证规则验证数据
496
     * @access public
497
     * @param  mixed     $value 字段值
498
     * @param  mixed     $rules 验证规则
499
     * @return bool
500
     */
501
    public function checkRule($value, $rules): bool
502
    {
503
        if ($rules instanceof \Closure) {
504
            return call_user_func_array($rules, [$value]);
505
        } elseif ($rules instanceof ValidateRule) {
506
            $rules = $rules->getRule();
507
        } elseif (is_string($rules)) {
508
            $rules = explode('|', $rules);
509
        }
510
511
        foreach ($rules as $key => $rule) {
512
            if ($rule instanceof \Closure) {
513
                $result = call_user_func_array($rule, [$value]);
514
            } else {
515
                // 判断验证类型
516
                list($type, $rule) = $this->getValidateType($key, $rule);
517
518
                $callback = $this->type[$type] ?? [$this, $type];
519
520
                $result = call_user_func_array($callback, [$value, $rule]);
521
            }
522
523
            if (true !== $result) {
524
                if ($this->failException) {
525
                    throw new ValidateException($result);
526
                }
527
528
                return $result;
529
            }
530
        }
531
532
        return true;
533
    }
534
535
    /**
536
     * 验证单个字段规则
537
     * @access protected
538
     * @param  string    $field  字段名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
539
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
540
     * @param  mixed     $rules  验证规则
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
541
     * @param  array     $data  数据
542
     * @param  string    $title  字段描述
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
543
     * @param  array     $msg  提示信息
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 2 found
Loading history...
544
     * @return mixed
545
     */
546
    protected function checkItem(string $field, $value, $rules, $data, string $title = '', array $msg = [])
547
    {
548
        if (isset($this->remove[$field]) && true === $this->remove[$field] && empty($this->append[$field])) {
549
            // 字段已经移除 无需验证
550
            return true;
551
        }
552
553
        // 支持多规则验证 require|in:a,b,c|... 或者 ['require','in'=>'a,b,c',...]
554
        if (is_string($rules)) {
555
            $rules = explode('|', $rules);
556
        }
557
558
        if (isset($this->append[$field])) {
559
            // 追加额外的验证规则
560
            $rules = array_unique(array_merge($rules, $this->append[$field]));
561
        }
562
563
        $i = 0;
564
        foreach ($rules as $key => $rule) {
565
            if ($rule instanceof \Closure) {
566
                $result = call_user_func_array($rule, [$value, $data]);
567
                $info   = is_numeric($key) ? '' : $key;
568
            } else {
569
                // 判断验证类型
570
                list($type, $rule, $info) = $this->getValidateType($key, $rule);
571
572
                if (isset($this->append[$field]) && in_array($info, $this->append[$field])) {
573
574
                } elseif (isset($this->remove[$field]) && in_array($info, $this->remove[$field])) {
575
                    // 规则已经移除
576
                    $i++;
577
                    continue;
578
                }
579
580
                if (isset($this->type[$type])) {
581
                    $result = call_user_func_array($this->type[$type], [$value, $rule, $data, $field, $title]);
582
                } elseif ('must' == $info || 0 === strpos($info, 'require') || (!is_null($value) && '' !== $value)) {
583
                    $result = call_user_func_array([$this, $type], [$value, $rule, $data, $field, $title]);
584
                } else {
585
                    $result = true;
586
                }
587
            }
588
589
            if (false === $result) {
590
                // 验证失败 返回错误信息
591
                if (!empty($msg[$i])) {
592
                    $message = $msg[$i];
593
                    if (is_string($message) && strpos($message, '{%') === 0) {
594
                        $message = $this->lang->get(substr($message, 2, -1));
595
                    }
596
                } else {
597
                    $message = $this->getRuleMsg($field, $title, $info, $rule);
598
                }
599
600
                return $message;
601
            } elseif (true !== $result) {
602
                // 返回自定义错误信息
603
                if (is_string($result) && false !== strpos($result, ':')) {
604
                    $result = str_replace(':attribute', $title, $result);
605
606
                    if (strpos($result, ':rule') && is_scalar($rule)) {
607
                        $result = str_replace(':rule', (string) $rule, $result);
608
                    }
609
                }
610
611
                return $result;
612
            }
613
            $i++;
614
        }
615
616
        return $result;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.
Loading history...
617
    }
618
619
    /**
620
     * 获取当前验证类型及规则
621
     * @access public
622
     * @param  mixed     $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
623
     * @param  mixed     $rule
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
624
     * @return array
625
     */
626
    protected function getValidateType($key, $rule): array
627
    {
628
        // 判断验证类型
629
        if (!is_numeric($key)) {
630
            return [$key, $rule, $key];
631
        }
632
633
        if (strpos($rule, ':')) {
634
            list($type, $rule) = explode(':', $rule, 2);
635
            if (isset($this->alias[$type])) {
636
                // 判断别名
637
                $type = $this->alias[$type];
638
            }
639
            $info = $type;
640
        } elseif (method_exists($this, $rule)) {
641
            $type = $rule;
642
            $info = $rule;
643
            $rule = '';
644
        } else {
645
            $type = 'is';
646
            $info = $rule;
647
        }
648
649
        return [$type, $rule, $info];
650
    }
651
652
    /**
653
     * 验证是否和某个字段的值一致
654
     * @access public
655
     * @param  mixed     $value 字段值
656
     * @param  mixed     $rule  验证规则
657
     * @param  array     $data  数据
658
     * @param  string    $field 字段名
659
     * @return bool
660
     */
661
    public function confirm($value, $rule, array $data = [], string $field = ''): bool
662
    {
663
        if ('' == $rule) {
664
            if (strpos($field, '_confirm')) {
665
                $rule = strstr($field, '_confirm', true);
666
            } else {
667
                $rule = $field . '_confirm';
668
            }
669
        }
670
671
        return $this->getDataValue($data, $rule) === $value;
672
    }
673
674
    /**
675
     * 验证是否和某个字段的值是否不同
676
     * @access public
677
     * @param  mixed $value 字段值
678
     * @param  mixed $rule  验证规则
679
     * @param  array $data  数据
680
     * @return bool
681
     */
682
    public function different($value, $rule, array $data = []): bool
683
    {
684
        return $this->getDataValue($data, $rule) != $value;
685
    }
686
687
    /**
688
     * 验证是否大于等于某个值
689
     * @access public
690
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
691
     * @param  mixed     $rule  验证规则
692
     * @param  array     $data  数据
693
     * @return bool
694
     */
695
    public function egt($value, $rule, array $data = []): bool
696
    {
697
        return $value >= $this->getDataValue($data, $rule);
698
    }
699
700
    /**
701
     * 验证是否大于某个值
702
     * @access public
703
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
704
     * @param  mixed     $rule  验证规则
705
     * @param  array     $data  数据
706
     * @return bool
707
     */
708
    public function gt($value, $rule, array $data = []): bool
709
    {
710
        return $value > $this->getDataValue($data, $rule);
711
    }
712
713
    /**
714
     * 验证是否小于等于某个值
715
     * @access public
716
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
717
     * @param  mixed     $rule  验证规则
718
     * @param  array     $data  数据
719
     * @return bool
720
     */
721
    public function elt($value, $rule, array $data = []): bool
722
    {
723
        return $value <= $this->getDataValue($data, $rule);
724
    }
725
726
    /**
727
     * 验证是否小于某个值
728
     * @access public
729
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
730
     * @param  mixed     $rule  验证规则
731
     * @param  array     $data  数据
732
     * @return bool
733
     */
734
    public function lt($value, $rule, array $data = []): bool
735
    {
736
        return $value < $this->getDataValue($data, $rule);
737
    }
738
739
    /**
740
     * 验证是否等于某个值
741
     * @access public
742
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
743
     * @param  mixed     $rule  验证规则
744
     * @return bool
745
     */
746
    public function eq($value, $rule): bool
747
    {
748
        return $value == $rule;
749
    }
750
751
    /**
752
     * 必须验证
753
     * @access public
754
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
755
     * @param  mixed     $rule  验证规则
756
     * @return bool
757
     */
758
    public function must($value, $rule = null): bool
759
    {
760
        return !empty($value) || '0' == $value;
761
    }
762
763
    /**
764
     * 验证字段值是否为有效格式
765
     * @access public
766
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
767
     * @param  string    $rule  验证规则
768
     * @param  array     $data  验证数据
769
     * @return bool
770
     */
771
    public function is($value, $rule, array $data = []): bool
772
    {
773
        switch (App::parseName($rule, 1, false)) {
774
            case 'require':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
775
                // 必须
776
                $result = !empty($value) || '0' == $value;
777
                break;
778
            case 'accepted':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
779
                // 接受
780
                $result = in_array($value, ['1', 'on', 'yes']);
781
                break;
782
            case 'date':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
783
                // 是否是一个有效日期
784
                $result = false !== strtotime($value);
785
                break;
786
            case 'activeUrl':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
787
                // 是否为有效的网址
788
                $result = checkdnsrr($value);
789
                break;
790
            case 'boolean':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
791
            case 'bool':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
792
                // 是否为布尔值
793
                $result = in_array($value, [true, false, 0, 1, '0', '1'], true);
794
                break;
795
            case 'number':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
796
                $result = ctype_digit((string) $value);
797
                break;
798
            case 'alphaNum':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
799
                $result = ctype_alnum($value);
800
                break;
801
            case 'array':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
802
                // 是否为数组
803
                $result = is_array($value);
804
                break;
805
            case 'file':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
806
                $result = $value instanceof File;
807
                break;
808
            case 'image':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
809
                $result = $value instanceof File && in_array($this->getImageType($value->getRealPath()), [1, 2, 3, 6]);
810
                break;
811
            case 'token':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
812
                $result = $this->token($value, '__token__', $data);
0 ignored issues
show
Bug introduced by
The method token() does not exist on think\Validate. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

812
                /** @scrutinizer ignore-call */ 
813
                $result = $this->token($value, '__token__', $data);
Loading history...
813
                break;
814
            default:
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
815
                if (isset($this->type[$rule])) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
816
                    // 注册的验证规则
817
                    $result = call_user_func_array($this->type[$rule], [$value]);
818
                } elseif (function_exists('ctype_' . $rule)) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
819
                    // ctype验证规则
820
                    $ctypeFun = 'ctype_' . $rule;
821
                    $result   = $ctypeFun($value);
822
                } elseif (isset($this->filter[$rule])) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
823
                    // Filter_var验证规则
824
                    $result = $this->filter($value, $this->filter[$rule]);
825
                } else {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
826
                    // 正则验证
827
                    $result = $this->regex($value, $rule);
828
                }
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
829
        }
830
831
        return $result;
832
    }
833
834
    // 判断图像类型
835
    protected function getImageType($image)
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
836
    {
837
        if (function_exists('exif_imagetype')) {
838
            return exif_imagetype($image);
839
        }
840
841
        try {
842
            $info = getimagesize($image);
843
            return $info ? $info[2] : false;
844
        } catch (\Exception $e) {
845
            return false;
846
        }
847
    }
848
849
    /**
850
     * 验证是否为合格的域名或者IP 支持A,MX,NS,SOA,PTR,CNAME,AAAA,A6, SRV,NAPTR,TXT 或者 ANY类型
851
     * @access public
852
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
853
     * @param  mixed     $rule  验证规则
854
     * @return bool
855
     */
856
    public function activeUrl(string $value, string $rule = 'MX'): bool
857
    {
858
        if (!in_array($rule, ['A', 'MX', 'NS', 'SOA', 'PTR', 'CNAME', 'AAAA', 'A6', 'SRV', 'NAPTR', 'TXT', 'ANY'])) {
859
            $rule = 'MX';
860
        }
861
862
        return checkdnsrr($value, $rule);
863
    }
864
865
    /**
866
     * 验证是否有效IP
867
     * @access public
868
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
869
     * @param  mixed     $rule  验证规则 ipv4 ipv6
870
     * @return bool
871
     */
872
    public function ip($value, string $rule = 'ipv4'): bool
873
    {
874
        if (!in_array($rule, ['ipv4', 'ipv6'])) {
875
            $rule = 'ipv4';
876
        }
877
878
        return $this->filter($value, [FILTER_VALIDATE_IP, 'ipv6' == $rule ? FILTER_FLAG_IPV6 : FILTER_FLAG_IPV4]);
879
    }
880
881
    /**
882
     * 验证上传文件后缀
883
     * @access public
884
     * @param  mixed     $file  上传文件
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
885
     * @param  mixed     $rule  验证规则
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
886
     * @return bool
887
     */
888
    public function fileExt($file, $rule): bool
889
    {
890
        if (is_array($file)) {
891
            foreach ($file as $item) {
892
                if (!($item instanceof File) || !$item->checkExt($rule)) {
893
                    return false;
894
                }
895
            }
896
            return true;
897
        } elseif ($file instanceof File) {
898
            return $file->checkExt($rule);
899
        }
900
901
        return false;
902
    }
903
904
    /**
905
     * 验证上传文件类型
906
     * @access public
907
     * @param  mixed     $file  上传文件
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
908
     * @param  mixed     $rule  验证规则
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
909
     * @return bool
910
     */
911
    public function fileMime($file, $rule): bool
912
    {
913
        if (is_array($file)) {
914
            foreach ($file as $item) {
915
                if (!($item instanceof File) || !$item->checkMime($rule)) {
916
                    return false;
917
                }
918
            }
919
            return true;
920
        } elseif ($file instanceof File) {
921
            return $file->checkMime($rule);
922
        }
923
924
        return false;
925
    }
926
927
    /**
928
     * 验证上传文件大小
929
     * @access public
930
     * @param  mixed     $file  上传文件
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
931
     * @param  mixed     $rule  验证规则
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
932
     * @return bool
933
     */
934
    public function fileSize($file, $rule): bool
935
    {
936
        if (is_array($file)) {
937
            foreach ($file as $item) {
938
                if (!($item instanceof File) || !$item->checkSize($rule)) {
939
                    return false;
940
                }
941
            }
942
            return true;
943
        } elseif ($file instanceof File) {
944
            return $file->checkSize($rule);
945
        }
946
947
        return false;
948
    }
949
950
    /**
951
     * 验证图片的宽高及类型
952
     * @access public
953
     * @param  mixed     $file  上传文件
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
954
     * @param  mixed     $rule  验证规则
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
955
     * @return bool
956
     */
957
    public function image($file, $rule): bool
958
    {
959
        if (!($file instanceof File)) {
960
            return false;
961
        }
962
963
        if ($rule) {
964
            $rule = explode(',', $rule);
965
966
            list($width, $height, $type) = getimagesize($file->getRealPath());
967
968
            if (isset($rule[2])) {
969
                $imageType = strtolower($rule[2]);
970
971
                if ('jpeg' == $imageType) {
972
                    $imageType = 'jpg';
973
                }
974
975
                if (image_type_to_extension($type, false) != $imageType) {
976
                    return false;
977
                }
978
            }
979
980
            list($w, $h) = $rule;
981
982
            return $w == $width && $h == $height;
983
        }
984
985
        return in_array($this->getImageType($file->getRealPath()), [1, 2, 3, 6]);
986
    }
987
988
    /**
989
     * 验证时间和日期是否符合指定格式
990
     * @access public
991
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
992
     * @param  mixed     $rule  验证规则
993
     * @return bool
994
     */
995
    public function dateFormat($value, $rule): bool
996
    {
997
        $info = date_parse_from_format($rule, $value);
998
        return 0 == $info['warning_count'] && 0 == $info['error_count'];
999
    }
1000
1001
    /**
1002
     * 验证是否唯一
1003
     * @access public
1004
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1005
     * @param  mixed     $rule  验证规则 格式:数据表,字段名,排除ID,主键名
1006
     * @param  array     $data  数据
1007
     * @param  string    $field  验证字段名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1008
     * @return bool
1009
     */
1010
    public function unique($value, $rule, array $data = [], string $field = ''): bool
1011
    {
1012
        if (is_string($rule)) {
1013
            $rule = explode(',', $rule);
1014
        }
1015
1016
        if (false !== strpos($rule[0], '\\')) {
1017
            // 指定模型类
1018
            $db = new $rule[0];
1019
        } else {
1020
            $db = Db::name($rule[0]);
0 ignored issues
show
Bug introduced by
The method name() does not exist on think\Db. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1020
            /** @scrutinizer ignore-call */ 
1021
            $db = Db::name($rule[0]);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1021
        }
1022
1023
        $key = $rule[1] ?? $field;
1024
        $map = [];
1025
1026
        if (strpos($key, '^')) {
1027
            // 支持多个字段验证
1028
            $fields = explode('^', $key);
1029
            foreach ($fields as $key) {
1030
                if (isset($data[$key])) {
1031
                    $map[] = [$key, '=', $data[$key]];
1032
                }
1033
            }
1034
        } elseif (isset($data[$field])) {
1035
            $map[] = [$key, '=', $data[$field]];
1036
        } else {
1037
            $map = [];
1038
        }
1039
1040
        $pk = !empty($rule[3]) ? $rule[3] : $db->getPk();
1041
1042
        if (is_string($pk)) {
1043
            if (isset($rule[2])) {
1044
                $map[] = [$pk, '<>', $rule[2]];
1045
            } elseif (isset($data[$pk])) {
1046
                $map[] = [$pk, '<>', $data[$pk]];
1047
            }
1048
        }
1049
1050
        if ($db->where($map)->field($pk)->find()) {
1051
            return false;
1052
        }
1053
1054
        return true;
1055
    }
1056
1057
    /**
1058
     * 使用filter_var方式验证
1059
     * @access public
1060
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1061
     * @param  mixed     $rule  验证规则
1062
     * @return bool
1063
     */
1064
    public function filter($value, $rule): bool
1065
    {
1066
        if (is_string($rule) && strpos($rule, ',')) {
1067
            list($rule, $param) = explode(',', $rule);
1068
        } elseif (is_array($rule)) {
1069
            $param = $rule[1] ?? null;
1070
            $rule  = $rule[0];
1071
        } else {
1072
            $param = null;
1073
        }
1074
1075
        return false !== filter_var($value, is_int($rule) ? $rule : filter_id($rule), $param);
1076
    }
1077
1078
    /**
1079
     * 验证某个字段等于某个值的时候必须
1080
     * @access public
1081
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1082
     * @param  mixed     $rule  验证规则
1083
     * @param  array     $data  数据
1084
     * @return bool
1085
     */
1086
    public function requireIf($value, $rule, array $data = []): bool
1087
    {
1088
        list($field, $val) = explode(',', $rule);
1089
1090
        if ($this->getDataValue($data, $field) == $val) {
1091
            return !empty($value) || '0' == $value;
1092
        }
1093
1094
        return true;
1095
    }
1096
1097
    /**
1098
     * 通过回调方法验证某个字段是否必须
1099
     * @access public
1100
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1101
     * @param  mixed     $rule  验证规则
1102
     * @param  array     $data  数据
1103
     * @return bool
1104
     */
1105
    public function requireCallback($value, $rule, array $data = []): bool
1106
    {
1107
        $result = call_user_func_array([$this, $rule], [$value, $data]);
1108
1109
        if ($result) {
1110
            return !empty($value) || '0' == $value;
1111
        }
1112
1113
        return true;
1114
    }
1115
1116
    /**
1117
     * 验证某个字段有值的情况下必须
1118
     * @access public
1119
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1120
     * @param  mixed     $rule  验证规则
1121
     * @param  array     $data  数据
1122
     * @return bool
1123
     */
1124
    public function requireWith($value, $rule, array $data = []): bool
1125
    {
1126
        $val = $this->getDataValue($data, $rule);
1127
1128
        if (!empty($val)) {
1129
            return !empty($value) || '0' == $value;
1130
        }
1131
1132
        return true;
1133
    }
1134
1135
    /**
1136
     * 验证是否在范围内
1137
     * @access public
1138
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1139
     * @param  mixed     $rule  验证规则
1140
     * @return bool
1141
     */
1142
    public function in($value, $rule): bool
1143
    {
1144
        return in_array($value, is_array($rule) ? $rule : explode(',', $rule));
1145
    }
1146
1147
    /**
1148
     * 验证是否不在某个范围
1149
     * @access public
1150
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1151
     * @param  mixed     $rule  验证规则
1152
     * @return bool
1153
     */
1154
    public function notIn($value, $rule): bool
1155
    {
1156
        return !in_array($value, is_array($rule) ? $rule : explode(',', $rule));
1157
    }
1158
1159
    /**
1160
     * between验证数据
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
1161
     * @access public
1162
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1163
     * @param  mixed     $rule  验证规则
1164
     * @return bool
1165
     */
1166
    public function between($value, $rule): bool
1167
    {
1168
        if (is_string($rule)) {
1169
            $rule = explode(',', $rule);
1170
        }
1171
        list($min, $max) = $rule;
1172
1173
        return $value >= $min && $value <= $max;
1174
    }
1175
1176
    /**
1177
     * 使用notbetween验证数据
1178
     * @access public
1179
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1180
     * @param  mixed     $rule  验证规则
1181
     * @return bool
1182
     */
1183
    public function notBetween($value, $rule): bool
1184
    {
1185
        if (is_string($rule)) {
1186
            $rule = explode(',', $rule);
1187
        }
1188
        list($min, $max) = $rule;
1189
1190
        return $value < $min || $value > $max;
1191
    }
1192
1193
    /**
1194
     * 验证数据长度
1195
     * @access public
1196
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1197
     * @param  mixed     $rule  验证规则
1198
     * @return bool
1199
     */
1200
    public function length($value, $rule): bool
1201
    {
1202
        if (is_array($value)) {
1203
            $length = count($value);
1204
        } elseif ($value instanceof File) {
1205
            $length = $value->getSize();
1206
        } else {
1207
            $length = mb_strlen((string) $value);
1208
        }
1209
1210
        if (strpos($rule, ',')) {
1211
            // 长度区间
1212
            list($min, $max) = explode(',', $rule);
1213
            return $length >= $min && $length <= $max;
1214
        }
1215
1216
        // 指定长度
1217
        return $length == $rule;
1218
    }
1219
1220
    /**
1221
     * 验证数据最大长度
1222
     * @access public
1223
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1224
     * @param  mixed     $rule  验证规则
1225
     * @return bool
1226
     */
1227
    public function max($value, $rule): bool
1228
    {
1229
        if (is_array($value)) {
1230
            $length = count($value);
1231
        } elseif ($value instanceof File) {
1232
            $length = $value->getSize();
1233
        } else {
1234
            $length = mb_strlen((string) $value);
1235
        }
1236
1237
        return $length <= $rule;
1238
    }
1239
1240
    /**
1241
     * 验证数据最小长度
1242
     * @access public
1243
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1244
     * @param  mixed     $rule  验证规则
1245
     * @return bool
1246
     */
1247
    public function min($value, $rule): bool
1248
    {
1249
        if (is_array($value)) {
1250
            $length = count($value);
1251
        } elseif ($value instanceof File) {
1252
            $length = $value->getSize();
1253
        } else {
1254
            $length = mb_strlen((string) $value);
1255
        }
1256
1257
        return $length >= $rule;
1258
    }
1259
1260
    /**
1261
     * 验证日期
1262
     * @access public
1263
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1264
     * @param  mixed     $rule  验证规则
1265
     * @param  array     $data  数据
1266
     * @return bool
1267
     */
1268
    public function after($value, $rule, array $data = []): bool
1269
    {
1270
        return strtotime($value) >= strtotime($rule);
1271
    }
1272
1273
    /**
1274
     * 验证日期
1275
     * @access public
1276
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1277
     * @param  mixed     $rule  验证规则
1278
     * @param  array     $data  数据
1279
     * @return bool
1280
     */
1281
    public function before($value, $rule, array $data = []): bool
1282
    {
1283
        return strtotime($value) <= strtotime($rule);
1284
    }
1285
1286
    /**
1287
     * 验证日期
1288
     * @access public
1289
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1290
     * @param  mixed     $rule  验证规则
1291
     * @param  array     $data  数据
1292
     * @return bool
1293
     */
1294
    public function afterWith($value, $rule, array $data = []): bool
1295
    {
1296
        $rule = $this->getDataValue($data, $rule);
1297
        return !is_null($rule) && strtotime($value) >= strtotime($rule);
1298
    }
1299
1300
    /**
1301
     * 验证日期
1302
     * @access public
1303
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1304
     * @param  mixed     $rule  验证规则
1305
     * @param  array     $data  数据
1306
     * @return bool
1307
     */
1308
    public function beforeWith($value, $rule, array $data = []): bool
1309
    {
1310
        $rule = $this->getDataValue($data, $rule);
1311
        return !is_null($rule) && strtotime($value) <= strtotime($rule);
1312
    }
1313
1314
    /**
1315
     * 验证有效期
1316
     * @access public
1317
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1318
     * @param  mixed     $rule  验证规则
1319
     * @return bool
1320
     */
1321
    public function expire($value, $rule): bool
1322
    {
1323
        if (is_string($rule)) {
1324
            $rule = explode(',', $rule);
1325
        }
1326
1327
        list($start, $end) = $rule;
1328
1329
        if (!is_numeric($start)) {
1330
            $start = strtotime($start);
1331
        }
1332
1333
        if (!is_numeric($end)) {
1334
            $end = strtotime($end);
1335
        }
1336
1337
        return $_SERVER['REQUEST_TIME'] >= $start && $_SERVER['REQUEST_TIME'] <= $end;
1338
    }
1339
1340
    /**
1341
     * 验证IP许可
1342
     * @access public
1343
     * @param  string    $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1344
     * @param  mixed     $rule  验证规则
1345
     * @return bool
1346
     */
1347
    public function allowIp($value, $rule): bool
1348
    {
1349
        return in_array($value, is_array($rule) ? $rule : explode(',', $rule));
1350
    }
1351
1352
    /**
1353
     * 验证IP禁用
1354
     * @access public
1355
     * @param  string    $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1356
     * @param  mixed     $rule  验证规则
1357
     * @return bool
1358
     */
1359
    public function denyIp($value, $rule): bool
1360
    {
1361
        return !in_array($value, is_array($rule) ? $rule : explode(',', $rule));
1362
    }
1363
1364
    /**
1365
     * 使用正则验证数据
1366
     * @access public
1367
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1368
     * @param  mixed     $rule  验证规则 正则规则或者预定义正则名
1369
     * @return bool
1370
     */
1371
    public function regex($value, $rule): bool
1372
    {
1373
        if (isset($this->regex[$rule])) {
1374
            $rule = $this->regex[$rule];
1375
        } elseif (isset($this->defaultRegex[$rule])) {
1376
            $rule = $this->defaultRegex[$rule];
1377
        }
1378
1379
        if (0 !== strpos($rule, '/') && !preg_match('/\/[imsU]{0,4}$/', $rule)) {
1380
            // 不是正则表达式则两端补上/
1381
            $rule = '/^' . $rule . '$/';
1382
        }
1383
1384
        return is_scalar($value) && 1 === preg_match($rule, (string) $value);
1385
    }
1386
1387
    // 获取错误信息
1388
    public function getError()
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
1389
    {
1390
        return $this->error;
1391
    }
1392
1393
    /**
1394
     * 获取数据值
1395
     * @access protected
1396
     * @param  array     $data  数据
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1397
     * @param  string    $key  数据标识 支持二维
1398
     * @return mixed
1399
     */
1400
    protected function getDataValue(array $data, $key)
1401
    {
1402
        if (is_numeric($key)) {
1403
            $value = $key;
1404
        } elseif (strpos($key, '.')) {
1405
            // 支持多维数组验证
1406
            foreach (explode('.', $key) as $key) {
0 ignored issues
show
introduced by
$key is overwriting one of the parameters of this function.
Loading history...
1407
                if (!isset($data[$key])) {
1408
                    $value = null;
1409
                    break;
1410
                }
1411
                $value = $data = $data[$key];
1412
            }
1413
        } else {
1414
            $value = $data[$key] ?? null;
1415
        }
1416
1417
        return $value;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $value does not seem to be defined for all execution paths leading up to this point.
Loading history...
1418
    }
1419
1420
    /**
1421
     * 获取验证规则的错误提示信息
1422
     * @access protected
1423
     * @param  string    $attribute  字段英文名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1424
     * @param  string    $title  字段描述名
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 2 found
Loading history...
1425
     * @param  string    $type  验证规则名称
0 ignored issues
show
Coding Style introduced by
Expected 6 spaces after parameter name; 2 found
Loading history...
1426
     * @param  mixed     $rule  验证规则数据
0 ignored issues
show
Coding Style introduced by
Expected 6 spaces after parameter name; 2 found
Loading history...
1427
     * @return string
1428
     */
1429
    protected function getRuleMsg(string $attribute, string $title, string $type, $rule): string
1430
    {
1431
        if (isset($this->message[$attribute . '.' . $type])) {
1432
            $msg = $this->message[$attribute . '.' . $type];
1433
        } elseif (isset($this->message[$attribute][$type])) {
1434
            $msg = $this->message[$attribute][$type];
1435
        } elseif (isset($this->message[$attribute])) {
1436
            $msg = $this->message[$attribute];
1437
        } elseif (isset($this->typeMsg[$type])) {
1438
            $msg = $this->typeMsg[$type];
1439
        } elseif (0 === strpos($type, 'require')) {
1440
            $msg = $this->typeMsg['require'];
1441
        } else {
1442
            $msg = $title . $this->lang->get('not conform to the rules');
1443
        }
1444
1445
        if (!is_string($msg)) {
1446
            return $msg;
1447
        }
1448
1449
        if (0 === strpos($msg, '{%')) {
1450
            $msg = $this->lang->get(substr($msg, 2, -1));
1451
        } elseif ($this->lang->has($msg)) {
1452
            $msg = $this->lang->get($msg);
1453
        }
1454
1455
        if (is_scalar($rule) && false !== strpos($msg, ':')) {
1456
            // 变量替换
1457
            if (is_string($rule) && strpos($rule, ',')) {
1458
                $array = array_pad(explode(',', $rule), 3, '');
1459
            } else {
1460
                $array = array_pad([], 3, '');
1461
            }
1462
1463
            $msg = str_replace(
1464
                [':attribute', ':1', ':2', ':3'],
1465
                [$title, $array[0], $array[1], $array[2]],
1466
                $msg);
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 12 spaces, but found 16.
Loading history...
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
1467
1468
            if (strpos($msg, ':rule')) {
1469
                $msg = str_replace(':rule', (string) $rule, $msg);
1470
            }
1471
        }
1472
1473
        return $msg;
1474
    }
1475
1476
    /**
1477
     * 获取数据验证的场景
1478
     * @access protected
1479
     * @param  string $scene  验证场景
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1480
     * @return void
1481
     */
1482
    protected function getScene(string $scene): void
1483
    {
1484
        $this->only = $this->append = $this->remove = [];
1485
1486
        if (method_exists($this, 'scene' . $scene)) {
1487
            call_user_func([$this, 'scene' . $scene]);
1488
        } elseif (isset($this->scene[$scene])) {
1489
            // 如果设置了验证适用场景
1490
            $this->only = $this->scene[$scene];
1491
        }
1492
    }
1493
1494
    /**
1495
     * 动态方法 直接调用is方法进行验证
1496
     * @access public
1497
     * @param  string $method  方法名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1498
     * @param  array $args  调用参数
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 2 found
Loading history...
1499
     * @return bool
1500
     */
1501
    public function __call($method, $args)
1502
    {
1503
        if ('is' == strtolower(substr($method, 0, 2))) {
1504
            $method = substr($method, 2);
1505
        }
1506
1507
        array_push($args, lcfirst($method));
1508
1509
        return call_user_func_array([$this, 'is'], $args);
1510
    }
1511
}
1512