Completed
Push — 6.0 ( 40b14a...7136ae )
by liu
02:52
created

Validate::setRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
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 Closure;
16
use think\exception\ValidateException;
17
use think\validate\ValidateRule;
18
19
/**
20
 * 数据验证类
21
 */
5 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @author tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
22
class Validate
23
{
24
    /**
25
     * 自定义验证类型
26
     * @var array
27
     */
28
    protected $type = [];
29
30
    /**
31
     * 验证类型别名
32
     * @var array
33
     */
34
    protected $alias = [
35
        '>' => 'gt', '>=' => 'egt', '<' => 'lt', '<=' => 'elt', '=' => 'eq', 'same' => 'eq',
36
    ];
37
38
    /**
39
     * 当前验证规则
40
     * @var array
41
     */
42
    protected $rule = [];
43
44
    /**
45
     * 验证提示信息
46
     * @var array
47
     */
48
    protected $message = [];
49
50
    /**
51
     * 验证字段描述
52
     * @var array
53
     */
54
    protected $field = [];
55
56
    /**
57
     * 默认规则提示
58
     * @var array
59
     */
60
    protected $typeMsg = [
61
        'require'     => ':attribute require',
62
        'must'        => ':attribute must',
63
        'number'      => ':attribute must be numeric',
64
        'integer'     => ':attribute must be integer',
65
        'float'       => ':attribute must be float',
66
        'boolean'     => ':attribute must be bool',
67
        'email'       => ':attribute not a valid email address',
68
        'mobile'      => ':attribute not a valid mobile',
69
        'array'       => ':attribute must be a array',
70
        'accepted'    => ':attribute must be yes,on or 1',
71
        'date'        => ':attribute not a valid datetime',
72
        'file'        => ':attribute not a valid file',
73
        'image'       => ':attribute not a valid image',
74
        'alpha'       => ':attribute must be alpha',
75
        'alphaNum'    => ':attribute must be alpha-numeric',
76
        'alphaDash'   => ':attribute must be alpha-numeric, dash, underscore',
77
        'activeUrl'   => ':attribute not a valid domain or ip',
78
        'chs'         => ':attribute must be chinese',
79
        'chsAlpha'    => ':attribute must be chinese or alpha',
80
        'chsAlphaNum' => ':attribute must be chinese,alpha-numeric',
81
        'chsDash'     => ':attribute must be chinese,alpha-numeric,underscore, dash',
82
        'url'         => ':attribute not a valid url',
83
        'ip'          => ':attribute not a valid ip',
84
        'dateFormat'  => ':attribute must be dateFormat of :rule',
85
        'in'          => ':attribute must be in :rule',
86
        'notIn'       => ':attribute be notin :rule',
87
        'between'     => ':attribute must between :1 - :2',
88
        'notBetween'  => ':attribute not between :1 - :2',
89
        'length'      => 'size of :attribute must be :rule',
90
        'max'         => 'max size of :attribute must be :rule',
91
        'min'         => 'min size of :attribute must be :rule',
92
        'after'       => ':attribute cannot be less than :rule',
93
        'before'      => ':attribute cannot exceed :rule',
94
        'expire'      => ':attribute not within :rule',
95
        'allowIp'     => 'access IP is not allowed',
96
        'denyIp'      => 'access IP denied',
97
        'confirm'     => ':attribute out of accord with :2',
98
        'different'   => ':attribute cannot be same with :2',
99
        'egt'         => ':attribute must greater than or equal :rule',
100
        'gt'          => ':attribute must greater than :rule',
101
        'elt'         => ':attribute must less than or equal :rule',
102
        'lt'          => ':attribute must less than :rule',
103
        'eq'          => ':attribute must equal :rule',
104
        'unique'      => ':attribute has exists',
105
        'regex'       => ':attribute not conform to the rules',
106
        'method'      => 'invalid Request method',
107
        'token'       => 'invalid token',
108
        'fileSize'    => 'filesize not match',
109
        'fileExt'     => 'extensions to upload is not allowed',
110
        'fileMime'    => 'mimetype to upload is not allowed',
111
    ];
112
113
    /**
114
     * 当前验证场景
115
     * @var string
116
     */
117
    protected $currentScene;
118
119
    /**
120
     * 内置正则验证规则
121
     * @var array
122
     */
123
    protected $defaultRegex = [
124
        'alpha'       => '/^[A-Za-z]+$/',
125
        'alphaNum'    => '/^[A-Za-z0-9]+$/',
126
        'alphaDash'   => '/^[A-Za-z0-9\-\_]+$/',
127
        'chs'         => '/^[\x{4e00}-\x{9fa5}]+$/u',
128
        'chsAlpha'    => '/^[\x{4e00}-\x{9fa5}a-zA-Z]+$/u',
129
        'chsAlphaNum' => '/^[\x{4e00}-\x{9fa5}a-zA-Z0-9]+$/u',
130
        'chsDash'     => '/^[\x{4e00}-\x{9fa5}a-zA-Z0-9\_\-]+$/u',
131
        'mobile'      => '/^1[3-9][0-9]\d{8}$/',
132
        '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}$)/',
133
        'zip'         => '/\d{6}/',
134
    ];
135
136
    /**
137
     * Filter_var 规则
138
     * @var array
139
     */
140
    protected $filter = [
141
        'email'   => FILTER_VALIDATE_EMAIL,
142
        'ip'      => [FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6],
143
        'integer' => FILTER_VALIDATE_INT,
144
        'url'     => FILTER_VALIDATE_URL,
145
        'macAddr' => FILTER_VALIDATE_MAC,
146
        'float'   => FILTER_VALIDATE_FLOAT,
147
    ];
148
149
    /**
150
     * 验证场景定义
151
     * @var array
152
     */
153
    protected $scene = [];
154
155
    /**
156
     * 验证失败错误信息
157
     * @var array
158
     */
159
    protected $error = [];
160
161
    /**
162
     * 是否批量验证
163
     * @var bool
164
     */
165
    protected $batch = false;
166
167
    /**
168
     * 验证失败是否抛出异常
169
     * @var bool
170
     */
171
    protected $failException = false;
172
173
    /**
174
     * 场景需要验证的规则
175
     * @var array
176
     */
177
    protected $only = [];
178
179
    /**
180
     * 场景需要移除的验证规则
181
     * @var array
182
     */
183
    protected $remove = [];
184
185
    /**
186
     * 场景需要追加的验证规则
187
     * @var array
188
     */
189
    protected $append = [];
190
191
    /**
192
     * 验证正则定义
193
     * @var array
194
     */
195
    protected $regex = [];
196
197
    /**
198
     * Db对象
199
     * @var Db
200
     */
201
    protected $db;
202
203
    /**
204
     * 语言对象
205
     * @var Lang
206
     */
207
    protected $lang;
208
209
    /**
210
     * 请求对象
211
     * @var Request
212
     */
213
    protected $request;
214
215
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
216
     * @var Closure
217
     */
218
    protected static $maker;
219
220
    /**
221
     * 设置服务注入
222
     * @access public
223
     * @param  Closure $maker
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
224
     * @return void
225
     */
226
    public static function maker(Closure $maker)
227
    {
228
        static::$maker = $maker;
229
    }
230
231
    /**
232
     * 设置Lang对象
233
     * @access public
234
     * @param  Lang $lang Lang对象
235
     * @return void
236
     */
237
    public function setLang(Lang $lang)
238
    {
239
        $this->lang = $lang;
240
    }
241
242
    /**
243
     * 设置Db对象
244
     * @access public
245
     * @param  Db $db Db对象
246
     * @return void
247
     */
248
    public function setDb(Db $db)
249
    {
250
        $this->db = $db;
251
    }
252
253
    /**
254
     * 设置Request对象
255
     * @access public
256
     * @param  Request $request Request对象
257
     * @return void
258
     */
259
    public function setRequest(Request $request)
260
    {
261
        $this->request = $request;
262
    }
263
264
    /**
265
     * 添加字段验证规则
266
     * @access protected
267
     * @param  string|array  $name  字段名称或者规则数组
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
268
     * @param  mixed         $rule  验证规则或者字段描述信息
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
269
     * @return $this
270
     */
271
    public function rule($name, $rule = '')
272
    {
273
        if (is_array($name)) {
274
            $this->rule = $name + $this->rule;
275
            if (is_array($rule)) {
276
                $this->field = array_merge($this->field, $rule);
277
            }
278
        } else {
279
            $this->rule[$name] = $rule;
280
        }
281
282
        return $this;
283
    }
284
285
    /**
286
     * 注册扩展验证(类型)规则
287
     * @access public
288
     * @param  string   $type  验证规则类型
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 2 found
Loading history...
289
     * @param  callable $callback callback方法(或闭包)
290
     * @param  string   $message  验证失败提示信息
291
     * @return $this
292
     */
293
    public function extend(string $type, callable $callback = null, string $message = null)
294
    {
295
        $this->type[$type] = $callback;
296
297
        if ($message) {
298
            $this->typeMsg[$type] = $message;
299
        }
300
301
        return $this;
302
    }
303
304
    /**
305
     * 设置验证规则的默认提示信息
306
     * @access public
307
     * @param  string|array $type  验证规则类型名称或者数组
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
308
     * @param  string       $msg  验证提示信息
309
     * @return void
310
     */
311
    public function setTypeMsg($type, string $msg = null): void
312
    {
313
        if (is_array($type)) {
314
            $this->typeMsg = array_merge($this->typeMsg, $type);
315
        } else {
316
            $this->typeMsg[$type] = $msg;
317
        }
318
    }
319
320
    /**
321
     * 设置提示信息
322
     * @access public
323
     * @param  array $message 错误信息
324
     * @return Validate
325
     */
326
    public function message(array $message)
327
    {
328
        $this->message = array_merge($this->message, $message);
329
330
        return $this;
331
    }
332
333
    /**
334
     * 设置验证场景
335
     * @access public
336
     * @param  string $name  场景名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
337
     * @return $this
338
     */
339
    public function scene(string $name)
340
    {
341
        // 设置当前场景
342
        $this->currentScene = $name;
343
344
        return $this;
345
    }
346
347
    /**
348
     * 判断是否存在某个验证场景
349
     * @access public
350
     * @param  string $name 场景名
351
     * @return bool
352
     */
353
    public function hasScene(string $name): bool
354
    {
355
        return isset($this->scene[$name]) || method_exists($this, 'scene' . $name);
356
    }
357
358
    /**
359
     * 设置批量验证
360
     * @access public
361
     * @param  bool $batch  是否批量验证
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
362
     * @return $this
363
     */
364
    public function batch(bool $batch = true)
365
    {
366
        $this->batch = $batch;
367
368
        return $this;
369
    }
370
371
    /**
372
     * 设置验证失败后是否抛出异常
373
     * @access protected
374
     * @param  bool $fail 是否抛出异常
375
     * @return $this
376
     */
377
    public function failException(bool $fail = true)
378
    {
379
        $this->failException = $fail;
380
381
        return $this;
382
    }
383
384
    /**
385
     * 指定需要验证的字段列表
386
     * @access public
387
     * @param  array $fields  字段名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
388
     * @return $this
389
     */
390
    public function only(array $fields)
391
    {
392
        $this->only = $fields;
393
394
        return $this;
395
    }
396
397
    /**
398
     * 移除某个字段的验证规则
399
     * @access public
400
     * @param  string|array $field  字段名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
401
     * @param  mixed        $rule   验证规则 true 移除所有规则
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 3 found
Loading history...
402
     * @return $this
403
     */
404
    public function remove($field, $rule = null)
405
    {
406
        if (is_array($field)) {
407
            foreach ($field as $key => $rule) {
408
                if (is_int($key)) {
409
                    $this->remove($rule);
410
                } else {
411
                    $this->remove($key, $rule);
412
                }
413
            }
414
        } else {
415
            if (is_string($rule)) {
416
                $rule = explode('|', $rule);
417
            }
418
419
            $this->remove[$field] = $rule;
420
        }
421
422
        return $this;
423
    }
424
425
    /**
426
     * 追加某个字段的验证规则
427
     * @access public
428
     * @param  string|array $field  字段名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
429
     * @param  mixed        $rule   验证规则
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 3 found
Loading history...
430
     * @return $this
431
     */
432
    public function append($field, $rule = null)
433
    {
434
        if (is_array($field)) {
435
            foreach ($field as $key => $rule) {
436
                $this->append($key, $rule);
437
            }
438
        } else {
439
            if (is_string($rule)) {
440
                $rule = explode('|', $rule);
441
            }
442
443
            $this->append[$field] = $rule;
444
        }
445
446
        return $this;
447
    }
448
449
    /**
450
     * 数据自动验证
451
     * @access public
452
     * @param  array $data  数据
453
     * @param  array $rules  验证规则
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
454
     * @return bool
455
     */
456
    public function check(array $data, array $rules = []): bool
457
    {
458
        if (static::$maker && !$this->lang) {
459
            call_user_func(static::$maker, $this);
460
        }
461
462
        $this->error = [];
463
464
        if (empty($rules)) {
465
            // 读取验证规则
466
            $rules = $this->rule;
467
        }
468
469
        if ($this->currentScene) {
470
            $this->getScene($this->currentScene);
471
        }
472
473
        foreach ($this->append as $key => $rule) {
474
            if (!isset($rules[$key])) {
475
                $rules[$key] = $rule;
476
            }
477
        }
478
479
        foreach ($rules as $key => $rule) {
480
            // field => 'rule1|rule2...' field => ['rule1','rule2',...]
481
            if (strpos($key, '|')) {
482
                // 字段|描述 用于指定属性名称
483
                list($key, $title) = explode('|', $key);
484
            } else {
485
                $title = $this->field[$key] ?? $key;
486
            }
487
488
            // 场景检测
489
            if (!empty($this->only) && !in_array($key, $this->only)) {
490
                continue;
491
            }
492
493
            // 获取数据 支持二维数组
494
            $value = $this->getDataValue($data, $key);
495
496
            // 字段验证
497
            if ($rule instanceof \Closure) {
498
                $result = call_user_func_array($rule, [$value, $data]);
499
            } elseif ($rule instanceof ValidateRule) {
500
                //  验证因子
501
                $result = $this->checkItem($key, $value, $rule->getRule(), $data, $rule->getTitle() ?: $title, $rule->getMsg());
502
            } else {
503
                $result = $this->checkItem($key, $value, $rule, $data, $title);
504
            }
505
506
            if (true !== $result) {
507
                // 没有返回true 则表示验证失败
508
                if (!empty($this->batch)) {
509
                    // 批量验证
510
                    if (is_array($result)) {
511
                        $this->error = array_merge($this->error, $result);
512
                    } else {
513
                        $this->error[$key] = $result;
514
                    }
515
                } elseif ($this->failException) {
516
                    throw new ValidateException($result);
517
                } else {
518
                    $this->error = $result;
519
                    return false;
520
                }
521
            }
522
        }
523
524
        if (!empty($this->error)) {
525
            if ($this->failException) {
526
                throw new ValidateException($this->error);
527
            }
528
            return false;
529
        }
530
531
        return true;
532
    }
533
534
    /**
535
     * 根据验证规则验证数据
536
     * @access public
537
     * @param  mixed $value 字段值
538
     * @param  mixed $rules 验证规则
539
     * @return bool
540
     */
541
    public function checkRule($value, $rules): bool
542
    {
543
        if (static::$maker && !$this->lang) {
544
            call_user_func(static::$maker, $this);
545
        }
546
547
        if ($rules instanceof \Closure) {
548
            return call_user_func_array($rules, [$value]);
549
        } elseif ($rules instanceof ValidateRule) {
550
            $rules = $rules->getRule();
551
        } elseif (is_string($rules)) {
552
            $rules = explode('|', $rules);
553
        }
554
555
        foreach ($rules as $key => $rule) {
556
            if ($rule instanceof \Closure) {
557
                $result = call_user_func_array($rule, [$value]);
558
            } else {
559
                // 判断验证类型
560
                list($type, $rule) = $this->getValidateType($key, $rule);
561
562
                $callback = $this->type[$type] ?? [$this, $type];
563
564
                $result = call_user_func_array($callback, [$value, $rule]);
565
            }
566
567
            if (true !== $result) {
568
                if ($this->failException) {
569
                    throw new ValidateException($result);
570
                }
571
572
                return $result;
573
            }
574
        }
575
576
        return true;
577
    }
578
579
    /**
580
     * 验证单个字段规则
581
     * @access protected
582
     * @param  string $field  字段名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
583
     * @param  mixed  $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
584
     * @param  mixed  $rules  验证规则
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
585
     * @param  array  $data  数据
586
     * @param  string $title  字段描述
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
587
     * @param  array  $msg  提示信息
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 2 found
Loading history...
588
     * @return mixed
589
     */
590
    protected function checkItem(string $field, $value, $rules, $data, string $title = '', array $msg = [])
591
    {
592
        if (isset($this->remove[$field]) && true === $this->remove[$field] && empty($this->append[$field])) {
593
            // 字段已经移除 无需验证
594
            return true;
595
        }
596
597
        // 支持多规则验证 require|in:a,b,c|... 或者 ['require','in'=>'a,b,c',...]
598
        if (is_string($rules)) {
599
            $rules = explode('|', $rules);
600
        }
601
602
        if (isset($this->append[$field])) {
603
            // 追加额外的验证规则
604
            $rules = array_unique(array_merge($rules, $this->append[$field]));
605
        }
606
607
        $i = 0;
608
        foreach ($rules as $key => $rule) {
609
            if ($rule instanceof \Closure) {
610
                $result = call_user_func_array($rule, [$value, $data]);
611
                $info   = is_numeric($key) ? '' : $key;
612
            } else {
613
                // 判断验证类型
614
                list($type, $rule, $info) = $this->getValidateType($key, $rule);
615
616
                if (isset($this->append[$field]) && in_array($info, $this->append[$field])) {
617
618
                } elseif (isset($this->remove[$field]) && in_array($info, $this->remove[$field])) {
619
                    // 规则已经移除
620
                    $i++;
621
                    continue;
622
                }
623
624
                if (isset($this->type[$type])) {
625
                    $result = call_user_func_array($this->type[$type], [$value, $rule, $data, $field, $title]);
626
                } elseif ('must' == $info || 0 === strpos($info, 'require') || (!is_null($value) && '' !== $value)) {
627
                    $result = call_user_func_array([$this, $type], [$value, $rule, $data, $field, $title]);
628
                } else {
629
                    $result = true;
630
                }
631
            }
632
633
            if (false === $result) {
634
                // 验证失败 返回错误信息
635
                if (!empty($msg[$i])) {
636
                    $message = $msg[$i];
637
                    if (is_string($message) && strpos($message, '{%') === 0) {
638
                        $message = $this->lang->get(substr($message, 2, -1));
639
                    }
640
                } else {
641
                    $message = $this->getRuleMsg($field, $title, $info, $rule);
642
                }
643
644
                return $message;
645
            } elseif (true !== $result) {
646
                // 返回自定义错误信息
647
                if (is_string($result) && false !== strpos($result, ':')) {
648
                    $result = str_replace(':attribute', $title, $result);
649
650
                    if (strpos($result, ':rule') && is_scalar($rule)) {
651
                        $result = str_replace(':rule', (string) $rule, $result);
652
                    }
653
                }
654
655
                return $result;
656
            }
657
            $i++;
658
        }
659
660
        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...
661
    }
662
663
    /**
664
     * 获取当前验证类型及规则
665
     * @access public
666
     * @param  mixed $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
667
     * @param  mixed $rule
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
668
     * @return array
669
     */
670
    protected function getValidateType($key, $rule): array
671
    {
672
        // 判断验证类型
673
        if (!is_numeric($key)) {
674
            return [$key, $rule, $key];
675
        }
676
677
        if (strpos($rule, ':')) {
678
            list($type, $rule) = explode(':', $rule, 2);
679
            if (isset($this->alias[$type])) {
680
                // 判断别名
681
                $type = $this->alias[$type];
682
            }
683
            $info = $type;
684
        } elseif (method_exists($this, $rule)) {
685
            $type = $rule;
686
            $info = $rule;
687
            $rule = '';
688
        } else {
689
            $type = 'is';
690
            $info = $rule;
691
        }
692
693
        return [$type, $rule, $info];
694
    }
695
696
    /**
697
     * 验证是否和某个字段的值一致
698
     * @access public
699
     * @param  mixed  $value 字段值
700
     * @param  mixed  $rule  验证规则
701
     * @param  array  $data  数据
702
     * @param  string $field 字段名
703
     * @return bool
704
     */
705
    public function confirm($value, $rule, array $data = [], string $field = ''): bool
706
    {
707
        if ('' == $rule) {
708
            if (strpos($field, '_confirm')) {
709
                $rule = strstr($field, '_confirm', true);
710
            } else {
711
                $rule = $field . '_confirm';
712
            }
713
        }
714
715
        return $this->getDataValue($data, $rule) === $value;
716
    }
717
718
    /**
719
     * 验证是否和某个字段的值是否不同
720
     * @access public
721
     * @param  mixed $value 字段值
722
     * @param  mixed $rule  验证规则
723
     * @param  array $data  数据
724
     * @return bool
725
     */
726
    public function different($value, $rule, array $data = []): bool
727
    {
728
        return $this->getDataValue($data, $rule) != $value;
729
    }
730
731
    /**
732
     * 验证是否大于等于某个值
733
     * @access public
734
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
735
     * @param  mixed $rule  验证规则
736
     * @param  array $data  数据
737
     * @return bool
738
     */
739
    public function egt($value, $rule, array $data = []): bool
740
    {
741
        return $value >= $this->getDataValue($data, $rule);
742
    }
743
744
    /**
745
     * 验证是否大于某个值
746
     * @access public
747
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
748
     * @param  mixed $rule  验证规则
749
     * @param  array $data  数据
750
     * @return bool
751
     */
752
    public function gt($value, $rule, array $data = []): bool
753
    {
754
        return $value > $this->getDataValue($data, $rule);
755
    }
756
757
    /**
758
     * 验证是否小于等于某个值
759
     * @access public
760
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
761
     * @param  mixed $rule  验证规则
762
     * @param  array $data  数据
763
     * @return bool
764
     */
765
    public function elt($value, $rule, array $data = []): bool
766
    {
767
        return $value <= $this->getDataValue($data, $rule);
768
    }
769
770
    /**
771
     * 验证是否小于某个值
772
     * @access public
773
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
774
     * @param  mixed $rule  验证规则
775
     * @param  array $data  数据
776
     * @return bool
777
     */
778
    public function lt($value, $rule, array $data = []): bool
779
    {
780
        return $value < $this->getDataValue($data, $rule);
781
    }
782
783
    /**
784
     * 验证是否等于某个值
785
     * @access public
786
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
787
     * @param  mixed $rule  验证规则
788
     * @return bool
789
     */
790
    public function eq($value, $rule): bool
791
    {
792
        return $value == $rule;
793
    }
794
795
    /**
796
     * 必须验证
797
     * @access public
798
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
799
     * @param  mixed $rule  验证规则
800
     * @return bool
801
     */
802
    public function must($value, $rule = null): bool
803
    {
804
        return !empty($value) || '0' == $value;
805
    }
806
807
    /**
808
     * 验证字段值是否为有效格式
809
     * @access public
810
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
811
     * @param  mixed $rule  验证规则
812
     * @param  array $data  数据
813
     * @return bool
814
     */
815
    public function is($value, $rule, array $data = []): bool
816
    {
817
        switch (App::parseName($rule, 1, false)) {
818
            case 'require':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
819
                // 必须
820
                $result = !empty($value) || '0' == $value;
821
                break;
822
            case 'accepted':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
823
                // 接受
824
                $result = in_array($value, ['1', 'on', 'yes']);
825
                break;
826
            case 'date':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
827
                // 是否是一个有效日期
828
                $result = false !== strtotime($value);
829
                break;
830
            case 'activeUrl':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
831
                // 是否为有效的网址
832
                $result = checkdnsrr($value);
833
                break;
834
            case 'boolean':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
835
            case 'bool':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
836
                // 是否为布尔值
837
                $result = in_array($value, [true, false, 0, 1, '0', '1'], true);
838
                break;
839
            case 'number':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
840
                $result = ctype_digit((string) $value);
841
                break;
842
            case 'alphaNum':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
843
                $result = ctype_alnum($value);
844
                break;
845
            case 'array':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
846
                // 是否为数组
847
                $result = is_array($value);
848
                break;
849
            case 'file':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
850
                $result = $value instanceof File;
851
                break;
852
            case 'image':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
853
                $result = $value instanceof File && in_array($this->getImageType($value->getRealPath()), [1, 2, 3, 6]);
854
                break;
855
            case 'token':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
856
                $result = $this->token($value, '__token__', $data);
857
                break;
858
            default:
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
859
                if (isset($this->type[$rule])) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
860
                    // 注册的验证规则
861
                    $result = call_user_func_array($this->type[$rule], [$value]);
862
                } elseif (function_exists('ctype_' . $rule)) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
863
                    // ctype验证规则
864
                    $ctypeFun = 'ctype_' . $rule;
865
                    $result   = $ctypeFun($value);
866
                } elseif (isset($this->filter[$rule])) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
867
                    // Filter_var验证规则
868
                    $result = $this->filter($value, $this->filter[$rule]);
869
                } else {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
870
                    // 正则验证
871
                    $result = $this->regex($value, $rule);
872
                }
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
873
        }
874
875
        return $result;
876
    }
877
878
    // 判断图像类型
879
    protected function getImageType($image)
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
880
    {
881
        if (function_exists('exif_imagetype')) {
882
            return exif_imagetype($image);
883
        }
884
885
        try {
886
            $info = getimagesize($image);
887
            return $info ? $info[2] : false;
888
        } catch (\Exception $e) {
889
            return false;
890
        }
891
    }
892
893
    /**
894
     * 验证表单令牌
895
     * @access public
896
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
897
     * @param  mixed     $rule  验证规则
898
     * @param  array     $data  数据
899
     * @return bool
900
     */
901
    public function token($value, string $rule, array $data): bool
902
    {
903
        $rule = !empty($rule) ? $rule : '__token__';
904
        return $this->request->checkToken($rule, $data);
905
    }
906
907
    /**
908
     * 验证是否为合格的域名或者IP 支持A,MX,NS,SOA,PTR,CNAME,AAAA,A6, SRV,NAPTR,TXT 或者 ANY类型
909
     * @access public
910
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
911
     * @param  mixed $rule  验证规则
912
     * @return bool
913
     */
914
    public function activeUrl(string $value, string $rule = 'MX'): bool
915
    {
916
        if (!in_array($rule, ['A', 'MX', 'NS', 'SOA', 'PTR', 'CNAME', 'AAAA', 'A6', 'SRV', 'NAPTR', 'TXT', 'ANY'])) {
917
            $rule = 'MX';
918
        }
919
920
        return checkdnsrr($value, $rule);
921
    }
922
923
    /**
924
     * 验证是否有效IP
925
     * @access public
926
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
927
     * @param  mixed $rule  验证规则 ipv4 ipv6
928
     * @return bool
929
     */
930
    public function ip($value, string $rule = 'ipv4'): bool
931
    {
932
        if (!in_array($rule, ['ipv4', 'ipv6'])) {
933
            $rule = 'ipv4';
934
        }
935
936
        return $this->filter($value, [FILTER_VALIDATE_IP, 'ipv6' == $rule ? FILTER_FLAG_IPV6 : FILTER_FLAG_IPV4]);
937
    }
938
939
    /**
940
     * 验证上传文件后缀
941
     * @access public
942
     * @param  mixed $file  上传文件
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
943
     * @param  mixed $rule  验证规则
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
944
     * @return bool
945
     */
946
    public function fileExt($file, $rule): bool
947
    {
948
        if (is_array($file)) {
949
            foreach ($file as $item) {
950
                if (!($item instanceof File) || !$item->checkExt($rule)) {
951
                    return false;
952
                }
953
            }
954
            return true;
955
        } elseif ($file instanceof File) {
956
            return $file->checkExt($rule);
957
        }
958
959
        return false;
960
    }
961
962
    /**
963
     * 验证上传文件类型
964
     * @access public
965
     * @param  mixed $file  上传文件
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
966
     * @param  mixed $rule  验证规则
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
967
     * @return bool
968
     */
969
    public function fileMime($file, $rule): bool
970
    {
971
        if (is_array($file)) {
972
            foreach ($file as $item) {
973
                if (!($item instanceof File) || !$item->checkMime($rule)) {
974
                    return false;
975
                }
976
            }
977
            return true;
978
        } elseif ($file instanceof File) {
979
            return $file->checkMime($rule);
980
        }
981
982
        return false;
983
    }
984
985
    /**
986
     * 验证上传文件大小
987
     * @access public
988
     * @param  mixed $file  上传文件
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
989
     * @param  mixed $rule  验证规则
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
990
     * @return bool
991
     */
992
    public function fileSize($file, $rule): bool
993
    {
994
        if (is_array($file)) {
995
            foreach ($file as $item) {
996
                if (!($item instanceof File) || !$item->checkSize($rule)) {
997
                    return false;
998
                }
999
            }
1000
            return true;
1001
        } elseif ($file instanceof File) {
1002
            return $file->checkSize($rule);
1003
        }
1004
1005
        return false;
1006
    }
1007
1008
    /**
1009
     * 验证图片的宽高及类型
1010
     * @access public
1011
     * @param  mixed $file  上传文件
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1012
     * @param  mixed $rule  验证规则
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1013
     * @return bool
1014
     */
1015
    public function image($file, $rule): bool
1016
    {
1017
        if (!($file instanceof File)) {
1018
            return false;
1019
        }
1020
1021
        if ($rule) {
1022
            $rule = explode(',', $rule);
1023
1024
            list($width, $height, $type) = getimagesize($file->getRealPath());
1025
1026
            if (isset($rule[2])) {
1027
                $imageType = strtolower($rule[2]);
1028
1029
                if ('jpeg' == $imageType) {
1030
                    $imageType = 'jpg';
1031
                }
1032
1033
                if (image_type_to_extension($type, false) != $imageType) {
1034
                    return false;
1035
                }
1036
            }
1037
1038
            list($w, $h) = $rule;
1039
1040
            return $w == $width && $h == $height;
1041
        }
1042
1043
        return in_array($this->getImageType($file->getRealPath()), [1, 2, 3, 6]);
1044
    }
1045
1046
    /**
1047
     * 验证时间和日期是否符合指定格式
1048
     * @access public
1049
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1050
     * @param  mixed $rule  验证规则
1051
     * @return bool
1052
     */
1053
    public function dateFormat($value, $rule): bool
1054
    {
1055
        $info = date_parse_from_format($rule, $value);
1056
        return 0 == $info['warning_count'] && 0 == $info['error_count'];
1057
    }
1058
1059
    /**
1060
     * 验证是否唯一
1061
     * @access public
1062
     * @param  mixed  $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1063
     * @param  mixed  $rule  验证规则 格式:数据表,字段名,排除ID,主键名
1064
     * @param  array  $data  数据
1065
     * @param  string $field  验证字段名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1066
     * @return bool
1067
     */
1068
    public function unique($value, $rule, array $data = [], string $field = ''): bool
1069
    {
1070
        if (is_string($rule)) {
1071
            $rule = explode(',', $rule);
1072
        }
1073
1074
        if (false !== strpos($rule[0], '\\')) {
1075
            // 指定模型类
1076
            $db = new $rule[0];
1077
        } else {
1078
            $db = $this->db->name($rule[0]);
0 ignored issues
show
Bug introduced by
The method name() does not exist on think\Db. 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

1078
            /** @scrutinizer ignore-call */ 
1079
            $db = $this->db->name($rule[0]);
Loading history...
1079
        }
1080
1081
        $key = $rule[1] ?? $field;
1082
        $map = [];
1083
1084
        if (strpos($key, '^')) {
1085
            // 支持多个字段验证
1086
            $fields = explode('^', $key);
1087
            foreach ($fields as $key) {
1088
                if (isset($data[$key])) {
1089
                    $map[] = [$key, '=', $data[$key]];
1090
                }
1091
            }
1092
        } elseif (isset($data[$field])) {
1093
            $map[] = [$key, '=', $data[$field]];
1094
        } else {
1095
            $map = [];
1096
        }
1097
1098
        $pk = !empty($rule[3]) ? $rule[3] : $db->getPk();
1099
1100
        if (is_string($pk)) {
1101
            if (isset($rule[2])) {
1102
                $map[] = [$pk, '<>', $rule[2]];
1103
            } elseif (isset($data[$pk])) {
1104
                $map[] = [$pk, '<>', $data[$pk]];
1105
            }
1106
        }
1107
1108
        if ($db->where($map)->field($pk)->find()) {
1109
            return false;
1110
        }
1111
1112
        return true;
1113
    }
1114
1115
    /**
1116
     * 使用filter_var方式验证
1117
     * @access public
1118
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1119
     * @param  mixed $rule  验证规则
1120
     * @return bool
1121
     */
1122
    public function filter($value, $rule): bool
1123
    {
1124
        if (is_string($rule) && strpos($rule, ',')) {
1125
            list($rule, $param) = explode(',', $rule);
1126
        } elseif (is_array($rule)) {
1127
            $param = $rule[1] ?? null;
1128
            $rule  = $rule[0];
1129
        } else {
1130
            $param = null;
1131
        }
1132
1133
        return false !== filter_var($value, is_int($rule) ? $rule : filter_id($rule), $param);
1134
    }
1135
1136
    /**
1137
     * 验证某个字段等于某个值的时候必须
1138
     * @access public
1139
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1140
     * @param  mixed $rule  验证规则
1141
     * @param  array $data  数据
1142
     * @return bool
1143
     */
1144
    public function requireIf($value, $rule, array $data = []): bool
1145
    {
1146
        list($field, $val) = explode(',', $rule);
1147
1148
        if ($this->getDataValue($data, $field) == $val) {
1149
            return !empty($value) || '0' == $value;
1150
        }
1151
1152
        return true;
1153
    }
1154
1155
    /**
1156
     * 通过回调方法验证某个字段是否必须
1157
     * @access public
1158
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1159
     * @param  mixed $rule  验证规则
1160
     * @param  array $data  数据
1161
     * @return bool
1162
     */
1163
    public function requireCallback($value, $rule, array $data = []): bool
1164
    {
1165
        $result = call_user_func_array([$this, $rule], [$value, $data]);
1166
1167
        if ($result) {
1168
            return !empty($value) || '0' == $value;
1169
        }
1170
1171
        return true;
1172
    }
1173
1174
    /**
1175
     * 验证某个字段有值的情况下必须
1176
     * @access public
1177
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1178
     * @param  mixed $rule  验证规则
1179
     * @param  array $data  数据
1180
     * @return bool
1181
     */
1182
    public function requireWith($value, $rule, array $data = []): bool
1183
    {
1184
        $val = $this->getDataValue($data, $rule);
1185
1186
        if (!empty($val)) {
1187
            return !empty($value) || '0' == $value;
1188
        }
1189
1190
        return true;
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 in($value, $rule): bool
1201
    {
1202
        return in_array($value, is_array($rule) ? $rule : explode(',', $rule));
1203
    }
1204
1205
    /**
1206
     * 验证是否不在某个范围
1207
     * @access public
1208
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1209
     * @param  mixed $rule  验证规则
1210
     * @return bool
1211
     */
1212
    public function notIn($value, $rule): bool
1213
    {
1214
        return !in_array($value, is_array($rule) ? $rule : explode(',', $rule));
1215
    }
1216
1217
    /**
1218
     * between验证数据
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
1219
     * @access public
1220
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1221
     * @param  mixed $rule  验证规则
1222
     * @return bool
1223
     */
1224
    public function between($value, $rule): bool
1225
    {
1226
        if (is_string($rule)) {
1227
            $rule = explode(',', $rule);
1228
        }
1229
        list($min, $max) = $rule;
1230
1231
        return $value >= $min && $value <= $max;
1232
    }
1233
1234
    /**
1235
     * 使用notbetween验证数据
1236
     * @access public
1237
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1238
     * @param  mixed $rule  验证规则
1239
     * @return bool
1240
     */
1241
    public function notBetween($value, $rule): bool
1242
    {
1243
        if (is_string($rule)) {
1244
            $rule = explode(',', $rule);
1245
        }
1246
        list($min, $max) = $rule;
1247
1248
        return $value < $min || $value > $max;
1249
    }
1250
1251
    /**
1252
     * 验证数据长度
1253
     * @access public
1254
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1255
     * @param  mixed $rule  验证规则
1256
     * @return bool
1257
     */
1258
    public function length($value, $rule): bool
1259
    {
1260
        if (is_array($value)) {
1261
            $length = count($value);
1262
        } elseif ($value instanceof File) {
1263
            $length = $value->getSize();
1264
        } else {
1265
            $length = mb_strlen((string) $value);
1266
        }
1267
1268
        if (strpos($rule, ',')) {
1269
            // 长度区间
1270
            list($min, $max) = explode(',', $rule);
1271
            return $length >= $min && $length <= $max;
1272
        }
1273
1274
        // 指定长度
1275
        return $length == $rule;
1276
    }
1277
1278
    /**
1279
     * 验证数据最大长度
1280
     * @access public
1281
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1282
     * @param  mixed $rule  验证规则
1283
     * @return bool
1284
     */
1285
    public function max($value, $rule): bool
1286
    {
1287
        if (is_array($value)) {
1288
            $length = count($value);
1289
        } elseif ($value instanceof File) {
1290
            $length = $value->getSize();
1291
        } else {
1292
            $length = mb_strlen((string) $value);
1293
        }
1294
1295
        return $length <= $rule;
1296
    }
1297
1298
    /**
1299
     * 验证数据最小长度
1300
     * @access public
1301
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1302
     * @param  mixed $rule  验证规则
1303
     * @return bool
1304
     */
1305
    public function min($value, $rule): bool
1306
    {
1307
        if (is_array($value)) {
1308
            $length = count($value);
1309
        } elseif ($value instanceof File) {
1310
            $length = $value->getSize();
1311
        } else {
1312
            $length = mb_strlen((string) $value);
1313
        }
1314
1315
        return $length >= $rule;
1316
    }
1317
1318
    /**
1319
     * 验证日期
1320
     * @access public
1321
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1322
     * @param  mixed $rule  验证规则
1323
     * @param  array $data  数据
1324
     * @return bool
1325
     */
1326
    public function after($value, $rule, array $data = []): bool
1327
    {
1328
        return strtotime($value) >= strtotime($rule);
1329
    }
1330
1331
    /**
1332
     * 验证日期
1333
     * @access public
1334
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1335
     * @param  mixed $rule  验证规则
1336
     * @param  array $data  数据
1337
     * @return bool
1338
     */
1339
    public function before($value, $rule, array $data = []): bool
1340
    {
1341
        return strtotime($value) <= strtotime($rule);
1342
    }
1343
1344
    /**
1345
     * 验证日期
1346
     * @access public
1347
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1348
     * @param  mixed $rule  验证规则
1349
     * @param  array $data  数据
1350
     * @return bool
1351
     */
1352
    public function afterWith($value, $rule, array $data = []): bool
1353
    {
1354
        $rule = $this->getDataValue($data, $rule);
1355
        return !is_null($rule) && strtotime($value) >= strtotime($rule);
1356
    }
1357
1358
    /**
1359
     * 验证日期
1360
     * @access public
1361
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1362
     * @param  mixed $rule  验证规则
1363
     * @param  array $data  数据
1364
     * @return bool
1365
     */
1366
    public function beforeWith($value, $rule, array $data = []): bool
1367
    {
1368
        $rule = $this->getDataValue($data, $rule);
1369
        return !is_null($rule) && strtotime($value) <= strtotime($rule);
1370
    }
1371
1372
    /**
1373
     * 验证有效期
1374
     * @access public
1375
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1376
     * @param  mixed $rule  验证规则
1377
     * @return bool
1378
     */
1379
    public function expire($value, $rule): bool
1380
    {
1381
        if (is_string($rule)) {
1382
            $rule = explode(',', $rule);
1383
        }
1384
1385
        list($start, $end) = $rule;
1386
1387
        if (!is_numeric($start)) {
1388
            $start = strtotime($start);
1389
        }
1390
1391
        if (!is_numeric($end)) {
1392
            $end = strtotime($end);
1393
        }
1394
1395
        return time() >= $start && time() <= $end;
1396
    }
1397
1398
    /**
1399
     * 验证IP许可
1400
     * @access public
1401
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1402
     * @param  mixed $rule  验证规则
1403
     * @return bool
1404
     */
1405
    public function allowIp($value, $rule): bool
1406
    {
1407
        return in_array($value, is_array($rule) ? $rule : explode(',', $rule));
1408
    }
1409
1410
    /**
1411
     * 验证IP禁用
1412
     * @access public
1413
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1414
     * @param  mixed $rule  验证规则
1415
     * @return bool
1416
     */
1417
    public function denyIp($value, $rule): bool
1418
    {
1419
        return !in_array($value, is_array($rule) ? $rule : explode(',', $rule));
1420
    }
1421
1422
    /**
1423
     * 使用正则验证数据
1424
     * @access public
1425
     * @param  mixed $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1426
     * @param  mixed $rule  验证规则 正则规则或者预定义正则名
1427
     * @return bool
1428
     */
1429
    public function regex($value, $rule): bool
1430
    {
1431
        if (isset($this->regex[$rule])) {
1432
            $rule = $this->regex[$rule];
1433
        } elseif (isset($this->defaultRegex[$rule])) {
1434
            $rule = $this->defaultRegex[$rule];
1435
        }
1436
1437
        if (0 !== strpos($rule, '/') && !preg_match('/\/[imsU]{0,4}$/', $rule)) {
1438
            // 不是正则表达式则两端补上/
1439
            $rule = '/^' . $rule . '$/';
1440
        }
1441
1442
        return is_scalar($value) && 1 === preg_match($rule, (string) $value);
1443
    }
1444
1445
    // 获取错误信息
1446
    public function getError()
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
1447
    {
1448
        return $this->error;
1449
    }
1450
1451
    /**
1452
     * 获取数据值
1453
     * @access protected
1454
     * @param  array  $data  数据
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1455
     * @param  string $key  数据标识 支持二维
1456
     * @return mixed
1457
     */
1458
    protected function getDataValue(array $data, $key)
1459
    {
1460
        if (is_numeric($key)) {
1461
            $value = $key;
1462
        } elseif (strpos($key, '.')) {
1463
            // 支持多维数组验证
1464
            foreach (explode('.', $key) as $key) {
0 ignored issues
show
introduced by
$key is overwriting one of the parameters of this function.
Loading history...
1465
                if (!isset($data[$key])) {
1466
                    $value = null;
1467
                    break;
1468
                }
1469
                $value = $data = $data[$key];
1470
            }
1471
        } else {
1472
            $value = $data[$key] ?? null;
1473
        }
1474
1475
        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...
1476
    }
1477
1478
    /**
1479
     * 获取验证规则的错误提示信息
1480
     * @access protected
1481
     * @param  string $attribute  字段英文名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1482
     * @param  string $title  字段描述名
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 2 found
Loading history...
1483
     * @param  string $type  验证规则名称
0 ignored issues
show
Coding Style introduced by
Expected 6 spaces after parameter name; 2 found
Loading history...
1484
     * @param  mixed  $rule  验证规则数据
0 ignored issues
show
Coding Style introduced by
Expected 6 spaces after parameter name; 2 found
Loading history...
1485
     * @return string
1486
     */
1487
    protected function getRuleMsg(string $attribute, string $title, string $type, $rule): string
1488
    {
1489
        if (isset($this->message[$attribute . '.' . $type])) {
1490
            $msg = $this->message[$attribute . '.' . $type];
1491
        } elseif (isset($this->message[$attribute][$type])) {
1492
            $msg = $this->message[$attribute][$type];
1493
        } elseif (isset($this->message[$attribute])) {
1494
            $msg = $this->message[$attribute];
1495
        } elseif (isset($this->typeMsg[$type])) {
1496
            $msg = $this->typeMsg[$type];
1497
        } elseif (0 === strpos($type, 'require')) {
1498
            $msg = $this->typeMsg['require'];
1499
        } else {
1500
            $msg = $title . $this->lang->get('not conform to the rules');
1501
        }
1502
1503
        if (!is_string($msg)) {
1504
            return $msg;
1505
        }
1506
1507
        if (0 === strpos($msg, '{%')) {
1508
            $msg = $this->lang->get(substr($msg, 2, -1));
1509
        } elseif ($this->lang->has($msg)) {
1510
            $msg = $this->lang->get($msg);
1511
        }
1512
1513
        if (is_scalar($rule) && false !== strpos($msg, ':')) {
1514
            // 变量替换
1515
            if (is_string($rule) && strpos($rule, ',')) {
1516
                $array = array_pad(explode(',', $rule), 3, '');
1517
            } else {
1518
                $array = array_pad([], 3, '');
1519
            }
1520
1521
            $msg = str_replace(
1522
                [':attribute', ':1', ':2', ':3'],
1523
                [$title, $array[0], $array[1], $array[2]],
1524
                $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...
1525
1526
            if (strpos($msg, ':rule')) {
1527
                $msg = str_replace(':rule', (string) $rule, $msg);
1528
            }
1529
        }
1530
1531
        return $msg;
1532
    }
1533
1534
    /**
1535
     * 获取数据验证的场景
1536
     * @access protected
1537
     * @param  string $scene  验证场景
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1538
     * @return void
1539
     */
1540
    protected function getScene(string $scene): void
1541
    {
1542
        $this->only = $this->append = $this->remove = [];
1543
1544
        if (method_exists($this, 'scene' . $scene)) {
1545
            call_user_func([$this, 'scene' . $scene]);
1546
        } elseif (isset($this->scene[$scene])) {
1547
            // 如果设置了验证适用场景
1548
            $this->only = $this->scene[$scene];
1549
        }
1550
    }
1551
1552
    /**
1553
     * 动态方法 直接调用is方法进行验证
1554
     * @access public
1555
     * @param  string $method  方法名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1556
     * @param  array $args  调用参数
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 2 found
Loading history...
1557
     * @return bool
1558
     */
1559
    public function __call($method, $args)
1560
    {
1561
        if ('is' == strtolower(substr($method, 0, 2))) {
1562
            $method = substr($method, 2);
1563
        }
1564
1565
        array_push($args, lcfirst($method));
1566
1567
        return call_user_func_array([$this, 'is'], $args);
1568
    }
1569
}
1570