Passed
Pull Request — 5.1 (#1723)
by
unknown
09:46
created

Validate::different()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 3
dl 0
loc 3
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~2018 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
12
namespace think;
13
14
use think\exception\ClassNotFoundException;
15
use think\validate\ValidateRule;
16
17
class Validate
1 ignored issue
show
Coding Style introduced by
Missing class doc comment
Loading history...
18
{
19
20
    /**
21
     * 自定义验证类型
22
     * @var array
23
     */
24
    protected static $type = [];
25
26
    /**
27
     * 验证类型别名
28
     * @var array
29
     */
30
    protected $alias = [
31
        '>' => 'gt', '>=' => 'egt', '<' => 'lt', '<=' => 'elt', '=' => 'eq', 'same' => 'eq',
32
    ];
33
34
    /**
35
     * 当前验证规则
36
     * @var array
37
     */
38
    protected $rule = [];
39
40
    /**
41
     * 验证提示信息
42
     * @var array
43
     */
44
    protected $message = [];
45
46
    /**
47
     * 验证字段描述
48
     * @var array
49
     */
50
    protected $field = [];
51
52
    /**
53
     * 默认规则提示
54
     * @var array
55
     */
56
    protected static $typeMsg = [
57
        'require'     => ':attribute require',
58
        'must'        => ':attribute must',
59
        'number'      => ':attribute must be numeric',
60
        'integer'     => ':attribute must be integer',
61
        'float'       => ':attribute must be float',
62
        'boolean'     => ':attribute must be bool',
63
        'email'       => ':attribute not a valid email address',
64
        'mobile'      => ':attribute not a valid mobile',
65
        'array'       => ':attribute must be a array',
66
        'accepted'    => ':attribute must be yes,on or 1',
67
        'date'        => ':attribute not a valid datetime',
68
        'file'        => ':attribute not a valid file',
69
        'image'       => ':attribute not a valid image',
70
        'alpha'       => ':attribute must be alpha',
71
        'alphaNum'    => ':attribute must be alpha-numeric',
72
        'alphaDash'   => ':attribute must be alpha-numeric, dash, underscore',
73
        'activeUrl'   => ':attribute not a valid domain or ip',
74
        'chs'         => ':attribute must be chinese',
75
        'chsAlpha'    => ':attribute must be chinese or alpha',
76
        'chsAlphaNum' => ':attribute must be chinese,alpha-numeric',
77
        'chsDash'     => ':attribute must be chinese,alpha-numeric,underscore, dash',
78
        'url'         => ':attribute not a valid url',
79
        'ip'          => ':attribute not a valid ip',
80
        'dateFormat'  => ':attribute must be dateFormat of :rule',
81
        'in'          => ':attribute must be in :rule',
82
        'notIn'       => ':attribute be notin :rule',
83
        'between'     => ':attribute must between :1 - :2',
84
        'notBetween'  => ':attribute not between :1 - :2',
85
        'length'      => 'size of :attribute must be :rule',
86
        'max'         => 'max size of :attribute must be :rule',
87
        'min'         => 'min size of :attribute must be :rule',
88
        'after'       => ':attribute cannot be less than :rule',
89
        'before'      => ':attribute cannot exceed :rule',
90
        'afterWith'   => ':attribute cannot be less than :rule',
91
        'beforeWith'  => ':attribute cannot exceed :rule',
92
        'expire'      => ':attribute not within :rule',
93
        'allowIp'     => 'access IP is not allowed',
94
        'denyIp'      => 'access IP denied',
95
        'confirm'     => ':attribute out of accord with :2',
96
        'different'   => ':attribute cannot be same with :2',
97
        'egt'         => ':attribute must greater than or equal :rule',
98
        'gt'          => ':attribute must greater than :rule',
99
        'elt'         => ':attribute must less than or equal :rule',
100
        'lt'          => ':attribute must less than :rule',
101
        'eq'          => ':attribute must equal :rule',
102
        'unique'      => ':attribute has exists',
103
        'regex'       => ':attribute not conform to the rules',
104
        'method'      => 'invalid Request method',
105
        'token'       => 'invalid token',
106
        'fileSize'    => 'filesize not match',
107
        'fileExt'     => 'extensions to upload is not allowed',
108
        'fileMime'    => 'mimetype to upload is not allowed',
109
    ];
110
111
    /**
112
     * 当前验证场景
113
     * @var array
114
     */
115
    protected $currentScene = null;
116
117
    /**
118
     * Filter_var 规则
119
     * @var array
120
     */
121
    protected $filter = [
122
        'email'   => FILTER_VALIDATE_EMAIL,
123
        'ip'      => [FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6],
124
        'integer' => FILTER_VALIDATE_INT,
125
        'url'     => FILTER_VALIDATE_URL,
126
        'macAddr' => FILTER_VALIDATE_MAC,
127
        'float'   => FILTER_VALIDATE_FLOAT,
128
    ];
129
130
    /**
131
     * 内置正则验证规则
132
     * @var array
133
     */
134
    protected $defaultRegex = [
135
        'alphaDash'   => '/^[A-Za-z0-9\-\_]+$/',
136
        'chs'         => '/^[\x{4e00}-\x{9fa5}]+$/u',
137
        'chsAlpha'    => '/^[\x{4e00}-\x{9fa5}a-zA-Z]+$/u',
138
        'chsAlphaNum' => '/^[\x{4e00}-\x{9fa5}a-zA-Z0-9]+$/u',
139
        'chsDash'     => '/^[\x{4e00}-\x{9fa5}a-zA-Z0-9\_\-]+$/u',
140
        'mobile'      => '/^1[3-9][0-9]\d{8}$/',
141
        '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}$)/',
142
        'zip'         => '/\d{6}/',
143
    ];
144
145
    /**
146
     * 验证场景定义
147
     * @var array
148
     */
149
    protected $scene = [];
150
151
    /**
152
     * 验证失败错误信息
153
     * @var array
154
     */
155
    protected $error = [];
156
157
    /**
158
     * 是否批量验证
159
     * @var bool
160
     */
161
    protected $batch = false;
162
163
    /**
164
     * 场景需要验证的规则
165
     * @var array
166
     */
167
    protected $only = [];
168
169
    /**
170
     * 场景需要移除的验证规则
171
     * @var array
172
     */
173
    protected $remove = [];
174
175
    /**
176
     * 场景需要追加的验证规则
177
     * @var array
178
     */
179
    protected $append = [];
180
181
    /**
182
     * 验证正则定义
183
     * @var array
184
     */
185
    protected $regex = [];
186
187
    /**
188
     * 架构函数
189
     * @access public
190
     * @param  array $rules 验证规则
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
191
     * @param  array $message 验证提示信息
192
     * @param  array $field 验证字段描述信息
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
193
     */
194
    public function __construct(array $rules = [], array $message = [], array $field = [])
195
    {
196
        $this->rule    = $rules + $this->rule;
197
        $this->message = array_merge($this->message, $message);
198
        $this->field   = array_merge($this->field, $field);
199
    }
200
201
    /**
202
     * 创建一个验证器类
203
     * @access public
204
     * @param  array $rules 验证规则
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
205
     * @param  array $message 验证提示信息
206
     * @param  array $field 验证字段描述信息
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
207
     * @return Validate
208
     */
209
    public static function make(array $rules = [], array $message = [], array $field = [])
210
    {
211
        return new self($rules, $message, $field);
212
    }
213
214
    /**
215
     * 添加字段验证规则
216
     * @access protected
217
     * @param  string|array  $name  字段名称或者规则数组
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
218
     * @param  mixed         $rule  验证规则或者字段描述信息
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
219
     * @return $this
220
     */
221
    public function rule($name, $rule = '')
222
    {
223
        if (is_array($name)) {
224
            $this->rule = $name + $this->rule;
225
            if (is_array($rule)) {
226
                $this->field = array_merge($this->field, $rule);
227
            }
228
        } else {
229
            $this->rule[$name] = $rule;
230
        }
231
232
        return $this;
233
    }
234
235
    /**
236
     * 注册扩展验证(类型)规则
237
     * @access public
238
     * @param  string    $type  验证规则类型
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 2 found
Loading history...
239
     * @param  mixed     $callback callback方法(或闭包)
240
     * @return void
241
     */
242
    public static function extend($type, $callback = null)
243
    {
244
        if (is_array($type)) {
0 ignored issues
show
introduced by
The condition is_array($type) is always false.
Loading history...
245
            self::$type = array_merge(self::$type, $type);
246
        } else {
247
            self::$type[$type] = $callback;
248
        }
249
    }
250
251
    /**
252
     * 设置验证规则的默认提示信息
253
     * @access public
254
     * @param  string|array  $type  验证规则类型名称或者数组
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
255
     * @param  string        $msg  验证提示信息
256
     * @return void
257
     */
258
    public static function setTypeMsg($type, $msg = null)
259
    {
260
        if (is_array($type)) {
261
            self::$typeMsg = array_merge(self::$typeMsg, $type);
262
        } else {
263
            self::$typeMsg[$type] = $msg;
264
        }
265
    }
266
267
    /**
268
     * 设置提示信息
269
     * @access public
270
     * @param  string|array  $name  字段名称
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 2 found
Loading history...
271
     * @param  string        $message 提示信息
272
     * @return Validate
273
     */
274
    public function message($name, $message = '')
275
    {
276
        if (is_array($name)) {
277
            $this->message = array_merge($this->message, $name);
278
        } else {
279
            $this->message[$name] = $message;
280
        }
281
282
        return $this;
283
    }
284
285
    /**
286
     * 设置验证场景
287
     * @access public
288
     * @param  string  $name  场景名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
289
     * @return $this
290
     */
291
    public function scene($name)
292
    {
293
        // 设置当前场景
294
        $this->currentScene = $name;
0 ignored issues
show
Documentation Bug introduced by
It seems like $name of type string is incompatible with the declared type array of property $currentScene.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
295
296
        return $this;
297
    }
298
299
    /**
300
     * 判断是否存在某个验证场景
301
     * @access public
302
     * @param  string $name 场景名
303
     * @return bool
304
     */
305
    public function hasScene($name)
306
    {
307
        return isset($this->scene[$name]) || method_exists($this, 'scene' . $name);
308
    }
309
310
    /**
311
     * 设置批量验证
312
     * @access public
313
     * @param  bool $batch  是否批量验证
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
314
     * @return $this
315
     */
316
    public function batch($batch = true)
317
    {
318
        $this->batch = $batch;
319
320
        return $this;
321
    }
322
323
    /**
324
     * 指定需要验证的字段列表
325
     * @access public
326
     * @param  array $fields  字段名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
327
     * @return $this
328
     */
329
    public function only($fields)
330
    {
331
        $this->only = $fields;
332
333
        return $this;
334
    }
335
336
    /**
337
     * 移除某个字段的验证规则
338
     * @access public
339
     * @param  string|array  $field  字段名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
340
     * @param  mixed         $rule   验证规则 null 移除所有规则
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 3 found
Loading history...
341
     * @return $this
342
     */
343
    public function remove($field, $rule = null)
344
    {
345
        if (is_array($field)) {
346
            foreach ($field as $key => $rule) {
347
                if (is_int($key)) {
348
                    $this->remove($rule);
349
                } else {
350
                    $this->remove($key, $rule);
351
                }
352
            }
353
        } else {
354
            if (is_string($rule)) {
355
                $rule = explode('|', $rule);
356
            }
357
358
            $this->remove[$field] = $rule;
359
        }
360
361
        return $this;
362
    }
363
364
    /**
365
     * 追加某个字段的验证规则
366
     * @access public
367
     * @param  string|array  $field  字段名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
368
     * @param  mixed         $rule   验证规则
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 3 found
Loading history...
369
     * @return $this
370
     */
371
    public function append($field, $rule = null)
372
    {
373
        if (is_array($field)) {
374
            foreach ($field as $key => $rule) {
375
                $this->append($key, $rule);
376
            }
377
        } else {
378
            if (is_string($rule)) {
379
                $rule = explode('|', $rule);
380
            }
381
382
            $this->append[$field] = $rule;
383
        }
384
385
        return $this;
386
    }
387
388
389
    /**
390
     * 获取当前规则
391
     * @access public
392
     * @param  string    $scene 验证场景
393
     * @return array
394
     */
395
    public function getRules($scene = '')
396
    {
397
        if (empty($rules)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $rules seems to never exist and therefore empty should always be true.
Loading history...
398
            // 读取验证规则
399
            $rules = $this->rule;
400
        }
401
        // 获取场景定义
402
        $this->getScene($scene);
403
        foreach ($this->append as $key => $rule) {
404
            if (!isset($rules[$key])) {
405
                $rules[$key] = $rule;
406
            }
407
        }
408
        return $rules;
409
    }
410
411
    /**
412
     * 数据自动验证
413
     * @access public
414
     * @param  array     $data  数据
415
     * @param  mixed     $rules  验证规则
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
416
     * @param  string    $scene 验证场景
417
     * @return bool
418
     */
419
    public function check($data, $rules = [], $scene = '')
420
    {
421
        $this->error = [];
422
423
        if (empty($rules)) {
424
            // 读取验证规则
425
            $rules = $this->getRules($scene);
426
        } else {
427
            // 设置验证场景
428
            $this->getScene($scene);
429
            foreach ($this->append as $key => $rule) {
430
                if (!isset($rules[$key])) {
431
                    $rules[$key] = $rule;
432
                }
433
            }
434
        }
435
436
437
        foreach ($rules as $key => $rule) {
438
            // field => 'rule1|rule2...' field => ['rule1','rule2',...]
439
            if (strpos($key, '|')) {
440
                // 字段|描述 用于指定属性名称
441
                list($key, $title) = explode('|', $key);
442
            } else {
443
                $title = isset($this->field[$key]) ? $this->field[$key] : $key;
444
            }
445
446
            // 场景检测
447
            if (!empty($this->only) && !in_array($key, $this->only)) {
448
                continue;
449
            }
450
451
            // 获取数据 支持多维数组
452
            $value = $this->getDataValue($data, $key);
453
454
            // 字段验证
455
            if ($rule instanceof \Closure) {
456
                $result = call_user_func_array($rule, [$value, $data, $title, $this]);
457
            } elseif ($rule instanceof ValidateRule) {
458
                //  验证因子
459
                $result = $this->checkItem($key, $value, $rule->getRule(), $data, $rule->getTitle() ?: $title, $rule->getMsg());
460
            } else {
461
                $result = $this->checkItem($key, $value, $rule, $data, $title);
462
            }
463
464
            if (true !== $result) {
465
                // 没有返回true 则表示验证失败
466
                if (!empty($this->batch)) {
467
                    // 批量验证
468
                    if (is_array($result)) {
469
                        $this->error = array_merge($this->error, $result);
470
                    } else {
471
                        $this->error[$key] = $result;
472
                    }
473
                } else {
474
                    $this->error = $result;
475
                    return false;
476
                }
477
            }
478
        }
479
480
        return !empty($this->error) ? false : true;
481
    }
482
483
    /**
484
     * 根据验证规则验证数据
485
     * @access public
486
     * @param  mixed     $value 字段值
487
     * @param  mixed     $rules 验证规则
488
     * @return bool
489
     */
490
    public function checkRule($value, $rules)
491
    {
492
        if ($rules instanceof \Closure) {
493
            return call_user_func_array($rules, [$value]);
494
        } elseif ($rules instanceof ValidateRule) {
495
            $rules = $rules->getRule();
496
        } elseif (is_string($rules)) {
497
            $rules = explode('|', $rules);
498
        }
499
500
        foreach ($rules as $key => $rule) {
501
            if ($rule instanceof \Closure) {
502
                $result = call_user_func_array($rule, [$value]);
503
            } else {
504
                // 判断验证类型
505
                list($type, $rule) = $this->getValidateType($key, $rule);
506
507
                $callback = isset(self::$type[$type]) ? self::$type[$type] : [$this, $type];
508
509
                $result = call_user_func_array($callback, [$value, $rule]);
510
            }
511
512
            if (true !== $result) {
513
                return $result;
514
            }
515
        }
516
517
        return true;
518
    }
519
520
    /**
521
     * 验证单个字段规则
522
     * @access protected
523
     * @param  string    $field  字段名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
524
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
525
     * @param  mixed     $rules  验证规则
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
526
     * @param  array     $data  数据
527
     * @param  string    $title  字段描述
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
528
     * @param  array     $msg  提示信息
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 2 found
Loading history...
529
     * @return mixed
530
     */
531
    protected function checkItem($field, $value, $rules, $data, $title = '', $msg = [])
532
    {
533
        if (isset($this->remove[$field]) && true === $this->remove[$field] && empty($this->append[$field])) {
534
            // 字段已经移除 无需验证
535
            return true;
536
        }
537
538
        // 支持多规则验证 require|in:a,b,c|... 或者 ['require','in'=>'a,b,c',...]
539
        if (is_string($rules)) {
540
            $rules = explode('|', $rules);
541
        }
542
543
        if (isset($this->append[$field])) {
544
            // 追加额外的验证规则
545
            $rules = array_unique(array_merge($rules, $this->append[$field]));
546
        }
547
548
        $i      = 0;
549
        $result = true;
550
551
        foreach ($rules as $key => $rule) {
552
            if ($rule instanceof \Closure) {
553
                $result = call_user_func_array($rule, [$value, $data]);
554
                $info   = is_numeric($key) ? '' : $key;
555
            } else {
556
                // 判断验证类型
557
                list($type, $rule, $info) = $this->getValidateType($key, $rule);
558
559
                if (isset($this->append[$field]) && in_array($info, $this->append[$field])) {
560
561
                } elseif (array_key_exists($field, $this->remove) && (null === $this->remove[$field] || in_array($info, $this->remove[$field]))) {
562
                    // 规则已经移除
563
                    $i++;
564
                    continue;
565
                }
566
567
                // 验证类型
568
                if (isset(self::$type[$type])) {
569
                    $result = call_user_func_array(self::$type[$type], [$value, $rule, $data, $field, $title]);
570
                } elseif ('must' == $info || 0 === strpos($info, 'require') || (!is_null($value) && '' !== $value)) {
571
                    // 验证数据
572
                    $result = call_user_func_array([$this, $type], [$value, $rule, $data, $field, $title]);
573
                } else {
574
                    $result = true;
575
                }
576
            }
577
578
            if (false === $result) {
579
                // 验证失败 返回错误信息
580
                if (!empty($msg[$i])) {
581
                    $message = $msg[$i];
582
                    if (is_string($message) && strpos($message, '{%') === 0) {
583
                        $message = facade\Lang::get(substr($message, 2, -1));
584
                    }
585
                } else {
586
                    $message = $this->getRuleMsg($field, $title, $info, $rule);
587
                }
588
589
                return $message;
590
            } elseif (true !== $result) {
591
                // 返回自定义错误信息
592
                if (is_string($result) && false !== strpos($result, ':')) {
593
                    $result = str_replace(':attribute', $title, $result);
594
595
                    if (strpos($result, ':rule') && is_scalar($rule)) {
596
                        $msg = str_replace(':rule', (string) $rule, $result);
0 ignored issues
show
Unused Code introduced by
The assignment to $msg is dead and can be removed.
Loading history...
597
                    }
598
                }
599
600
                return $result;
601
            }
602
            $i++;
603
        }
604
605
        return $result;
606
    }
607
608
    /**
609
     * 获取当前验证类型及规则
610
     * @access public
611
     * @param  mixed     $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
612
     * @param  mixed     $rule
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
613
     * @return array
614
     */
615
    protected function getValidateType($key, $rule)
616
    {
617
        // 判断验证类型
618
        if (!is_numeric($key)) {
619
            return [$key, $rule, $key];
620
        }
621
622
        if (strpos($rule, ':')) {
623
            list($type, $rule) = explode(':', $rule, 2);
624
            if (isset($this->alias[$type])) {
625
                // 判断别名
626
                $type = $this->alias[$type];
627
            }
628
            $info = $type;
629
        } elseif (method_exists($this, $rule)) {
630
            $type = $rule;
631
            $info = $rule;
632
            $rule = '';
633
        } else {
634
            $type = 'is';
635
            $info = $rule;
636
        }
637
638
        return [$type, $rule, $info];
639
    }
640
641
    /**
642
     * 验证是否和某个字段的值一致
643
     * @access public
644
     * @param  mixed     $value 字段值
645
     * @param  mixed     $rule  验证规则
646
     * @param  array     $data  数据
647
     * @param  string    $field 字段名
648
     * @return bool
649
     */
650
    public function confirm($value, $rule, $data = [], $field = '')
651
    {
652
        if ('' == $rule) {
653
            if (strpos($field, '_confirm')) {
654
                $rule = strstr($field, '_confirm', true);
655
            } else {
656
                $rule = $field . '_confirm';
657
            }
658
        }
659
660
        return $this->getDataValue($data, $rule) === $value;
661
    }
662
663
    /**
664
     * 验证是否和某个字段的值是否不同
665
     * @access public
666
     * @param  mixed $value 字段值
667
     * @param  mixed $rule  验证规则
668
     * @param  array $data  数据
669
     * @return bool
670
     */
671
    public function different($value, $rule, $data = [])
672
    {
673
        return $this->getDataValue($data, $rule) != $value;
674
    }
675
676
    /**
677
     * 验证是否大于等于某个值
678
     * @access public
679
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
680
     * @param  mixed     $rule  验证规则
681
     * @param  array     $data  数据
682
     * @return bool
683
     */
684
    public function egt($value, $rule, $data = [])
685
    {
686
        return $value >= $this->getDataValue($data, $rule);
687
    }
688
689
    /**
690
     * 验证是否大于某个值
691
     * @access public
692
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
693
     * @param  mixed     $rule  验证规则
694
     * @param  array     $data  数据
695
     * @return bool
696
     */
697
    public function gt($value, $rule, $data)
698
    {
699
        return $value > $this->getDataValue($data, $rule);
700
    }
701
702
    /**
703
     * 验证是否小于等于某个值
704
     * @access public
705
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
706
     * @param  mixed     $rule  验证规则
707
     * @param  array     $data  数据
708
     * @return bool
709
     */
710
    public function elt($value, $rule, $data = [])
711
    {
712
        return $value <= $this->getDataValue($data, $rule);
713
    }
714
715
    /**
716
     * 验证是否小于某个值
717
     * @access public
718
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
719
     * @param  mixed     $rule  验证规则
720
     * @param  array     $data  数据
721
     * @return bool
722
     */
723
    public function lt($value, $rule, $data = [])
724
    {
725
        return $value < $this->getDataValue($data, $rule);
726
    }
727
728
    /**
729
     * 验证是否等于某个值
730
     * @access public
731
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
732
     * @param  mixed     $rule  验证规则
733
     * @return bool
734
     */
735
    public function eq($value, $rule)
736
    {
737
        return $value == $rule;
738
    }
739
740
    /**
741
     * 必须验证
742
     * @access public
743
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
744
     * @param  mixed     $rule  验证规则
745
     * @return bool
746
     */
747
    public function must($value, $rule = null)
748
    {
749
        return !empty($value) || '0' == $value;
750
    }
751
752
    /**
753
     * 验证字段值是否为有效格式
754
     * @access public
755
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
756
     * @param  string    $rule  验证规则
757
     * @param  array     $data  验证数据
758
     * @return bool
759
     */
760
    public function is($value, $rule, $data = [])
761
    {
762
        switch (Loader::parseName($rule, 1, false)) {
763
            case 'require':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
764
                // 必须
765
                $result = !empty($value) || '0' == $value;
766
                break;
767
            case 'accepted':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
768
                // 接受
769
                $result = in_array($value, ['1', 'on', 'yes']);
770
                break;
771
            case 'date':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
772
                // 是否是一个有效日期
773
                $result = false !== strtotime($value);
774
                break;
775
            case 'activeUrl':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
776
                // 是否为有效的网址
777
                $result = checkdnsrr($value);
778
                break;
779
            case 'boolean':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
780
            case 'bool':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
781
                // 是否为布尔值
782
                $result = in_array($value, [true, false, 0, 1, '0', '1'], true);
783
                break;
784
            case 'number':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
785
                $result = ctype_digit((string) $value);
786
                break;
787
            case 'alphaNum':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
788
                $result = ctype_alnum($value);
789
                break;
790
            case 'array':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
791
                // 是否为数组
792
                $result = is_array($value);
793
                break;
794
            case 'file':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
795
                $result = $value instanceof File;
796
                break;
797
            case 'image':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
798
                $result = $value instanceof File && in_array($this->getImageType($value->getRealPath()), [1, 2, 3, 6]);
799
                break;
800
            case 'token':
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
801
                $result = $this->token($value, '__token__', $data);
802
                break;
803
            default:
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
804
                if (isset(self::$type[$rule])) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
805
                    // 注册的验证规则
806
                    $result = call_user_func_array(self::$type[$rule], [$value]);
807
                } elseif (function_exists('ctype_' . $rule)) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
808
                    // ctype验证规则
809
                    $ctypeFun = 'ctype_' . $rule;
810
                    $result   = $ctypeFun($value);
811
                } elseif (isset($this->filter[$rule])) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
812
                    // Filter_var验证规则
813
                    $result = $this->filter($value, $this->filter[$rule]);
814
                } else {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
815
                    // 正则验证
816
                    $result = $this->regex($value, $rule);
817
                }
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
818
        }
819
820
        return $result;
821
    }
822
823
    // 判断图像类型
824
    protected function getImageType($image)
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
825
    {
826
        if (function_exists('exif_imagetype')) {
827
            return exif_imagetype($image);
828
        }
829
830
        try {
831
            $info = getimagesize($image);
832
            return $info ? $info[2] : false;
833
        } catch (\Exception $e) {
834
            return false;
835
        }
836
    }
837
838
    /**
839
     * 验证是否为合格的域名或者IP 支持A,MX,NS,SOA,PTR,CNAME,AAAA,A6, SRV,NAPTR,TXT 或者 ANY类型
840
     * @access public
841
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
842
     * @param  mixed     $rule  验证规则
843
     * @return bool
844
     */
845
    public function activeUrl($value, $rule = 'MX')
846
    {
847
        if (!in_array($rule, ['A', 'MX', 'NS', 'SOA', 'PTR', 'CNAME', 'AAAA', 'A6', 'SRV', 'NAPTR', 'TXT', 'ANY'])) {
848
            $rule = 'MX';
849
        }
850
851
        return checkdnsrr($value, $rule);
852
    }
853
854
    /**
855
     * 验证是否有效IP
856
     * @access public
857
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
858
     * @param  mixed     $rule  验证规则 ipv4 ipv6
859
     * @return bool
860
     */
861
    public function ip($value, $rule = 'ipv4')
862
    {
863
        if (!in_array($rule, ['ipv4', 'ipv6'])) {
864
            $rule = 'ipv4';
865
        }
866
867
        return $this->filter($value, [FILTER_VALIDATE_IP, 'ipv6' == $rule ? FILTER_FLAG_IPV6 : FILTER_FLAG_IPV4]);
868
    }
869
870
    /**
871
     * 验证上传文件后缀
872
     * @access public
873
     * @param  mixed     $file  上传文件
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
874
     * @param  mixed     $rule  验证规则
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
875
     * @return bool
876
     */
877
    public function fileExt($file, $rule)
878
    {
879
        if (is_array($file)) {
880
            foreach ($file as $item) {
881
                if (!($item instanceof File) || !$item->checkExt($rule)) {
882
                    return false;
883
                }
884
            }
885
            return true;
886
        } elseif ($file instanceof File) {
887
            return $file->checkExt($rule);
888
        }
889
890
        return false;
891
    }
892
893
    /**
894
     * 验证上传文件类型
895
     * @access public
896
     * @param  mixed     $file  上传文件
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
897
     * @param  mixed     $rule  验证规则
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
898
     * @return bool
899
     */
900
    public function fileMime($file, $rule)
901
    {
902
        if (is_array($file)) {
903
            foreach ($file as $item) {
904
                if (!($item instanceof File) || !$item->checkMime($rule)) {
905
                    return false;
906
                }
907
            }
908
            return true;
909
        } elseif ($file instanceof File) {
910
            return $file->checkMime($rule);
911
        }
912
913
        return false;
914
    }
915
916
    /**
917
     * 验证上传文件大小
918
     * @access public
919
     * @param  mixed     $file  上传文件
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
920
     * @param  mixed     $rule  验证规则
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
921
     * @return bool
922
     */
923
    public function fileSize($file, $rule)
924
    {
925
        if (is_array($file)) {
926
            foreach ($file as $item) {
927
                if (!($item instanceof File) || !$item->checkSize($rule)) {
928
                    return false;
929
                }
930
            }
931
            return true;
932
        } elseif ($file instanceof File) {
933
            return $file->checkSize($rule);
934
        }
935
936
        return false;
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 image($file, $rule)
947
    {
948
        if (!($file instanceof File)) {
949
            return false;
950
        }
951
952
        if ($rule) {
953
            $rule = explode(',', $rule);
954
955
            list($width, $height, $type) = getimagesize($file->getRealPath());
956
957
            if (isset($rule[2])) {
958
                $imageType = strtolower($rule[2]);
959
960
                if ('jpeg' == $imageType) {
961
                    $imageType = 'jpg';
962
                }
963
964
                if (image_type_to_extension($type, false) != $imageType) {
965
                    return false;
966
                }
967
            }
968
969
            list($w, $h) = $rule;
970
971
            return $w == $width && $h == $height;
972
        }
973
974
        return in_array($this->getImageType($file->getRealPath()), [1, 2, 3, 6]);
975
    }
976
977
    /**
978
     * 验证请求类型
979
     * @access public
980
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
981
     * @param  mixed     $rule  验证规则
982
     * @return bool
983
     */
984
    public function method($value, $rule)
985
    {
986
        $method = Container::get('request')->method();
987
        return strtoupper($rule) == $method;
988
    }
989
990
    /**
991
     * 验证时间和日期是否符合指定格式
992
     * @access public
993
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
994
     * @param  mixed     $rule  验证规则
995
     * @return bool
996
     */
997
    public function dateFormat($value, $rule)
998
    {
999
        $info = date_parse_from_format($rule, $value);
1000
        return 0 == $info['warning_count'] && 0 == $info['error_count'];
1001
    }
1002
1003
    /**
1004
     * 验证是否唯一
1005
     * @access public
1006
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1007
     * @param  mixed     $rule  验证规则 格式:数据表,字段名,排除ID,主键名
1008
     * @param  array     $data  数据
1009
     * @param  string    $field  验证字段名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1010
     * @return bool
1011
     */
1012
    public function unique($value, $rule, $data, $field)
1013
    {
1014
        if (is_string($rule)) {
1015
            $rule = explode(',', $rule);
1016
        }
1017
1018
        if (false !== strpos($rule[0], '\\')) {
1019
            // 指定模型类
1020
            $db = new $rule[0];
1021
        } else {
1022
            try {
1023
                $db = Container::get('app')->model($rule[0]);
1024
            } catch (ClassNotFoundException $e) {
1025
                $db = Db::name($rule[0]);
1026
            }
1027
        }
1028
1029
        $key = isset($rule[1]) ? $rule[1] : $field;
1030
1031
        if (strpos($key, '^')) {
1032
            // 支持多个字段验证
1033
            $fields = explode('^', $key);
1034
            foreach ($fields as $key) {
1035
                if (isset($data[$key])) {
1036
                    $map[] = [$key, '=', $data[$key]];
1037
                }
1038
            }
1039
        } elseif (strpos($key, '=')) {
1040
            parse_str($key, $map);
1041
        } elseif (isset($data[$field])) {
1042
            $map[] = [$key, '=', $data[$field]];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$map was never initialized. Although not strictly required by PHP, it is generally a good practice to add $map = array(); before regardless.
Loading history...
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()) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $map does not seem to be defined for all execution paths leading up to this point.
Loading history...
1058
            return false;
1059
        }
1060
1061
        return true;
1062
    }
1063
1064
    /**
1065
     * 使用行为类验证
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
     * @param  array     $data  数据
1070
     * @return mixed
1071
     */
1072
    public function behavior($value, $rule, $data)
1073
    {
1074
        return Container::get('hook')->exec($rule, $data);
1075
    }
1076
1077
    /**
1078
     * 使用filter_var方式验证
1079
     * @access public
1080
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1081
     * @param  mixed     $rule  验证规则
1082
     * @return bool
1083
     */
1084
    public function filter($value, $rule)
1085
    {
1086
        if (is_string($rule) && strpos($rule, ',')) {
1087
            list($rule, $param) = explode(',', $rule);
1088
        } elseif (is_array($rule)) {
1089
            $param = isset($rule[1]) ? $rule[1] : null;
1090
            $rule  = $rule[0];
1091
        } else {
1092
            $param = null;
1093
        }
1094
1095
        return false !== filter_var($value, is_int($rule) ? $rule : filter_id($rule), $param);
1096
    }
1097
1098
    /**
1099
     * 验证某个字段等于某个值的时候必须
1100
     * @access public
1101
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1102
     * @param  mixed     $rule  验证规则
1103
     * @param  array     $data  数据
1104
     * @return bool
1105
     */
1106
    public function requireIf($value, $rule, $data)
1107
    {
1108
        list($field, $val) = explode(',', $rule);
1109
1110
        if ($this->getDataValue($data, $field) == $val) {
1111
            return !empty($value) || '0' == $value;
1112
        }
1113
1114
        return true;
1115
    }
1116
1117
    /**
1118
     * 通过回调方法验证某个字段是否必须
1119
     * @access public
1120
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1121
     * @param  mixed     $rule  验证规则
1122
     * @param  array     $data  数据
1123
     * @return bool
1124
     */
1125
    public function requireCallback($value, $rule, $data)
1126
    {
1127
        $result = call_user_func_array([$this, $rule], [$value, $data]);
1128
1129
        if ($result) {
1130
            return !empty($value) || '0' == $value;
1131
        }
1132
1133
        return true;
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 requireWith($value, $rule, $data)
1145
    {
1146
        $val = $this->getDataValue($data, $rule);
1147
1148
        if (!empty($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
     * @return bool
1161
     */
1162
    public function in($value, $rule)
1163
    {
1164
        return in_array($value, is_array($rule) ? $rule : explode(',', $rule));
1165
    }
1166
1167
    /**
1168
     * 验证是否不在某个范围
1169
     * @access public
1170
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1171
     * @param  mixed     $rule  验证规则
1172
     * @return bool
1173
     */
1174
    public function notIn($value, $rule)
1175
    {
1176
        return !in_array($value, is_array($rule) ? $rule : explode(',', $rule));
1177
    }
1178
1179
    /**
1180
     * between验证数据
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
1181
     * @access public
1182
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1183
     * @param  mixed     $rule  验证规则
1184
     * @return bool
1185
     */
1186
    public function between($value, $rule)
1187
    {
1188
        if (is_string($rule)) {
1189
            $rule = explode(',', $rule);
1190
        }
1191
        list($min, $max) = $rule;
1192
1193
        return $value >= $min && $value <= $max;
1194
    }
1195
1196
    /**
1197
     * 使用notbetween验证数据
1198
     * @access public
1199
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1200
     * @param  mixed     $rule  验证规则
1201
     * @return bool
1202
     */
1203
    public function notBetween($value, $rule)
1204
    {
1205
        if (is_string($rule)) {
1206
            $rule = explode(',', $rule);
1207
        }
1208
        list($min, $max) = $rule;
1209
1210
        return $value < $min || $value > $max;
1211
    }
1212
1213
    /**
1214
     * 验证数据长度
1215
     * @access public
1216
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1217
     * @param  mixed     $rule  验证规则
1218
     * @return bool
1219
     */
1220
    public function length($value, $rule)
1221
    {
1222
        if (is_array($value)) {
1223
            $length = count($value);
1224
        } elseif ($value instanceof File) {
1225
            $length = $value->getSize();
1226
        } else {
1227
            $length = mb_strlen((string) $value);
1228
        }
1229
1230
        if (strpos($rule, ',')) {
1231
            // 长度区间
1232
            list($min, $max) = explode(',', $rule);
1233
            return $length >= $min && $length <= $max;
1234
        }
1235
1236
        // 指定长度
1237
        return $length == $rule;
1238
    }
1239
1240
    /**
1241
     * 验证数据最大长度
1242
     * @access public
1243
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1244
     * @param  mixed     $rule  验证规则
1245
     * @return bool
1246
     */
1247
    public function max($value, $rule)
1248
    {
1249
        if (is_array($value)) {
1250
            $length = count($value);
1251
        } elseif ($value instanceof File) {
1252
            $length = $value->getSize();
1253
        } else {
1254
            $length = mb_strlen((string) $value);
1255
        }
1256
1257
        return $length <= $rule;
1258
    }
1259
1260
    /**
1261
     * 验证数据最小长度
1262
     * @access public
1263
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1264
     * @param  mixed     $rule  验证规则
1265
     * @return bool
1266
     */
1267
    public function min($value, $rule)
1268
    {
1269
        if (is_array($value)) {
1270
            $length = count($value);
1271
        } elseif ($value instanceof File) {
1272
            $length = $value->getSize();
1273
        } else {
1274
            $length = mb_strlen((string) $value);
1275
        }
1276
1277
        return $length >= $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 after($value, $rule, $data)
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 before($value, $rule, $data)
1302
    {
1303
        return strtotime($value) <= strtotime($rule);
1304
    }
1305
1306
    /**
1307
     * 验证日期字段
1308
     * @access protected
1309
     * @param mixed     $value  字段值
1 ignored issue
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
1310
     * @param mixed     $rule  验证规则
1 ignored issue
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
1311
     * @param array     $data  数据
1 ignored issue
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
1312
     * @return bool
1313
     */
1314
    protected function afterWith($value, $rule, $data)
1315
    {
1316
        $rule = $this->getDataValue($data, $rule);
1317
        return !is_null($rule) && strtotime($value) >= strtotime($rule);
1318
    }
1319
1320
    /**
1321
     * 验证日期字段
1322
     * @access protected
1323
     * @param mixed     $value  字段值
1 ignored issue
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
1324
     * @param mixed     $rule  验证规则
1 ignored issue
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
1325
     * @param array     $data  数据
1 ignored issue
show
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
1326
     * @return bool
1327
     */
1328
    protected function beforeWith($value, $rule, $data)
1329
    {
1330
        $rule = $this->getDataValue($data, $rule);
1331
        return !is_null($rule) && strtotime($value) <= strtotime($rule);
1332
    }
1333
1334
    /**
1335
     * 验证有效期
1336
     * @access public
1337
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1338
     * @param  mixed     $rule  验证规则
1339
     * @return bool
1340
     */
1341
    public function expire($value, $rule)
1342
    {
1343
        if (is_string($rule)) {
1344
            $rule = explode(',', $rule);
1345
        }
1346
1347
        list($start, $end) = $rule;
1348
1349
        if (!is_numeric($start)) {
1350
            $start = strtotime($start);
1351
        }
1352
1353
        if (!is_numeric($end)) {
1354
            $end = strtotime($end);
1355
        }
1356
1357
        return $_SERVER['REQUEST_TIME'] >= $start && $_SERVER['REQUEST_TIME'] <= $end;
1358
    }
1359
1360
    /**
1361
     * 验证IP许可
1362
     * @access public
1363
     * @param  string    $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1364
     * @param  mixed     $rule  验证规则
1365
     * @return mixed
1366
     */
1367
    public function allowIp($value, $rule)
1368
    {
1369
        return in_array($value, is_array($rule) ? $rule : explode(',', $rule));
1370
    }
1371
1372
    /**
1373
     * 验证IP禁用
1374
     * @access public
1375
     * @param  string    $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 mixed
1378
     */
1379
    public function denyIp($value, $rule)
1380
    {
1381
        return !in_array($value, is_array($rule) ? $rule : explode(',', $rule));
1382
    }
1383
1384
    /**
1385
     * 使用正则验证数据
1386
     * @access public
1387
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1388
     * @param  mixed     $rule  验证规则 正则规则或者预定义正则名
1389
     * @return bool
1390
     */
1391
    public function regex($value, $rule)
1392
    {
1393
        if (isset($this->regex[$rule])) {
1394
            $rule = $this->regex[$rule];
1395
        } elseif (isset($this->defaultRegex[$rule])) {
1396
            $rule = $this->defaultRegex[$rule];
1397
        }
1398
1399
        if (0 !== strpos($rule, '/') && !preg_match('/\/[imsU]{0,4}$/', $rule)) {
1400
            // 不是正则表达式则两端补上/
1401
            $rule = '/^' . $rule . '$/';
1402
        }
1403
1404
        return is_scalar($value) && 1 === preg_match($rule, (string) $value);
1405
    }
1406
1407
    /**
1408
     * 验证表单令牌
1409
     * @access public
1410
     * @param  mixed     $value  字段值
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1411
     * @param  mixed     $rule  验证规则
1412
     * @param  array     $data  数据
1413
     * @return bool
1414
     */
1415
    public function token($value, $rule, $data)
1416
    {
1417
        $rule    = !empty($rule) ? $rule : '__token__';
1418
        $session = Container::get('session');
1419
1420
        if (!isset($data[$rule]) || !$session->has($rule)) {
1421
            // 令牌数据无效
1422
            return false;
1423
        }
1424
1425
        // 令牌验证
1426
        if (isset($data[$rule]) && $session->get($rule) === $data[$rule]) {
1427
            // 防止重复提交
1428
            $session->delete($rule); // 验证完成销毁session
1429
            return true;
1430
        }
1431
1432
        // 开启TOKEN重置
1433
        $session->delete($rule);
1434
1435
        return false;
1436
    }
1437
1438
    // 获取错误信息
1439
    public function getError()
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
1440
    {
1441
        return $this->error;
1442
    }
1443
1444
    /**
1445
     * 获取数据值
1446
     * @access protected
1447
     * @param  array     $data  数据
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1448
     * @param  string    $key  数据标识 支持多维
1449
     * @return mixed
1450
     */
1451
    protected function getDataValue($data, $key)
1452
    {
1453
        if (is_numeric($key)) {
1454
            $value = $key;
1455
        } elseif (strpos($key, '.')) {
1456
            // 支持多维数组验证
1457
            foreach (explode('.', $key) as $key) {
0 ignored issues
show
introduced by
$key is overwriting one of the parameters of this function.
Loading history...
1458
                if (!isset($data[$key])) {
1459
                    $value = null;
1460
                    break;
1461
                }
1462
                $value = $data = $data[$key];
1463
            }
1464
        } else {
1465
            $value = isset($data[$key]) ? $data[$key] : null;
1466
        }
1467
1468
        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...
1469
    }
1470
1471
    /**
1472
     * 获取验证规则的错误提示信息
1473
     * @access protected
1474
     * @param  string    $attribute  字段英文名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1475
     * @param  string    $title  字段描述名
0 ignored issues
show
Coding Style introduced by
Expected 5 spaces after parameter name; 2 found
Loading history...
1476
     * @param  string    $type  验证规则名称
0 ignored issues
show
Coding Style introduced by
Expected 6 spaces after parameter name; 2 found
Loading history...
1477
     * @param  mixed     $rule  验证规则数据
0 ignored issues
show
Coding Style introduced by
Expected 6 spaces after parameter name; 2 found
Loading history...
1478
     * @return string
1479
     */
1480
    protected function getRuleMsg($attribute, $title, $type, $rule)
1481
    {
1482
        $lang = Container::get('lang');
1483
1484
        if (isset($this->message[$attribute . '.' . $type])) {
1485
            $msg = $this->message[$attribute . '.' . $type];
1486
        } elseif (isset($this->message[$attribute][$type])) {
1487
            $msg = $this->message[$attribute][$type];
1488
        } elseif (isset($this->message[$attribute])) {
1489
            $msg = $this->message[$attribute];
1490
        } elseif (isset(self::$typeMsg[$type])) {
1491
            $msg = self::$typeMsg[$type];
1492
        } elseif (0 === strpos($type, 'require')) {
1493
            $msg = self::$typeMsg['require'];
1494
        } else {
1495
            $msg = $title . $lang->get('not conform to the rules');
1496
        }
1497
1498
        if (!is_string($msg)) {
1499
            return $msg;
1500
        }
1501
1502
        if (0 === strpos($msg, '{%')) {
1503
            $msg = $lang->get(substr($msg, 2, -1));
1504
        } elseif ($lang->has($msg)) {
1505
            $msg = $lang->get($msg);
1506
        }
1507
1508
        if (is_scalar($rule) && false !== strpos($msg, ':')) {
1509
            // 变量替换
1510
            if (is_string($rule) && strpos($rule, ',')) {
1511
                $array = array_pad(explode(',', $rule), 3, '');
1512
            } else {
1513
                $array = array_pad([], 3, '');
1514
            }
1515
            $msg = str_replace(
1516
                [':attribute', ':1', ':2', ':3'],
1517
                [$title, $array[0], $array[1], $array[2]],
1518
                $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...
1519
            if (strpos($msg, ':rule')) {
1520
                $msg = str_replace(':rule', (string) $rule, $msg);
1521
            }
1522
        }
1523
1524
        return $msg;
1525
    }
1526
1527
    /**
1528
     * 获取数据验证的场景
1529
     * @access protected
1530
     * @param  string $scene  验证场景
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1531
     * @return void
1532
     */
1533
    protected function getScene($scene = '')
1534
    {
1535
        if (empty($scene)) {
1536
            // 读取指定场景
1537
            $scene = $this->currentScene;
1538
        }
1539
1540
        if (empty($scene)) {
1541
            return;
1542
        }
1543
1544
        $this->only = $this->append = $this->remove = [];
1545
1546
        if (method_exists($this, 'scene' . $scene)) {
0 ignored issues
show
Bug introduced by
Are you sure $scene of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

1546
        if (method_exists($this, 'scene' . /** @scrutinizer ignore-type */ $scene)) {
Loading history...
1547
            call_user_func([$this, 'scene' . $scene]);
1548
        } elseif (isset($this->scene[$scene])) {
1549
            // 如果设置了验证适用场景
1550
            $scene = $this->scene[$scene];
1551
1552
            if (is_string($scene)) {
1553
                $scene = explode(',', $scene);
1554
            }
1555
1556
            $this->only = $scene;
1557
        }
1558
    }
1559
1560
    /**
1561
     * 动态方法 直接调用is方法进行验证
1562
     * @access public
1563
     * @param  string $method  方法名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
1564
     * @param  array $args  调用参数
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 2 found
Loading history...
1565
     * @return bool
1566
     */
1567
    public function __call($method, $args)
1568
    {
1569
        if ('is' == strtolower(substr($method, 0, 2))) {
1570
            $method = substr($method, 2);
1571
        }
1572
1573
        array_push($args, lcfirst($method));
1574
1575
        return call_user_func_array([$this, 'is'], $args);
1576
    }
1577
}
1578