Completed
Push — 6.0 ( c6d21a...a43f83 )
by yun
15:10 queued 11:06
created

Validate::confirm()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

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

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