Completed
Push — 6.0 ( e9af16...c91531 )
by liu
02:45
created

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

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