Validate::scene()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 4
nop 2
dl 0
loc 13
ccs 0
cts 11
cp 0
crap 12
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Created by rozbo at 2017/3/9 下午2:54
4
 */
5
6
namespace puck;
7
8
9
class Validate {
10
    // 实例
11
    protected static $instance;
12
13
    // 自定义的验证类型
14
    protected static $type=[];
15
16
    // 验证类型别名
17
    protected $alias=[
18
        '>' => 'gt', '>=' => 'egt', '<' => 'lt', '<=' => 'elt', '=' => 'eq', 'same' => 'eq',
19
    ];
20
21
    // 当前验证的规则
22
    protected $rule=[];
23
24
    // 验证提示信息
25
    protected $message=[];
26
    // 验证字段描述
27
    protected $field=[];
28
29
    // 验证规则默认提示信息
30
    protected static $typeMsg=[
31
        'require'     => ':attribute不能为空',
32
        'number'      => ':attribute必须是数字',
33
        'float'       => ':attribute必须是浮点数',
34
        'boolean'     => ':attribute必须是布尔值',
35
        'email'       => ':attribute格式不符',
36
        'array'       => ':attribute必须是数组',
37
        'accepted'    => ':attribute必须是yes、on或者1',
38
        'date'        => ':attribute格式不符合',
39
        'file'        => ':attribute不是有效的上传文件',
40
        'image'       => ':attribute不是有效的图像文件',
41
        'alpha'       => ':attribute只能是字母',
42
        'alphaNum'    => ':attribute只能是字母和数字',
43
        'alphaDash'   => ':attribute只能是字母、数字和下划线_及破折号-',
44
        'activeUrl'   => ':attribute不是有效的域名或者IP',
45
        'chs'         => ':attribute只能是汉字',
46
        'chsAlpha'    => ':attribute只能是汉字、字母',
47
        'chsAlphaNum' => ':attribute只能是汉字、字母和数字',
48
        'chsDash'     => ':attribute只能是汉字、字母、数字和下划线_及破折号-',
49
        'url'         => ':attribute不是有效的URL地址',
50
        'ip'          => ':attribute不是有效的IP地址',
51
        'dateFormat'  => ':attribute必须使用日期格式 :rule',
52
        'in'          => ':attribute必须在 :rule 范围内',
53
        'notIn'       => ':attribute不能在 :rule 范围内',
54
        'between'     => ':attribute只能在 :1 - :2 之间',
55
        'notBetween'  => ':attribute不能在 :1 - :2 之间',
56
        'length'      => ':attribute长度不符合要求 :rule',
57
        'max'         => ':attribute长度不能超过 :rule',
58
        'min'         => ':attribute长度不能小于 :rule',
59
        'after'       => ':attribute日期不能小于 :rule',
60
        'before'      => ':attribute日期不能超过 :rule',
61
        'expire'      => '不在有效期内 :rule',
62
        'allowIp'     => '不允许的IP访问',
63
        'denyIp'      => '禁止的IP访问',
64
        'confirm'     => ':attribute和确认字段:2不一致',
65
        'different'   => ':attribute和比较字段:2不能相同',
66
        'egt'         => ':attribute必须大于等于 :rule',
67
        'gt'          => ':attribute必须大于 :rule',
68
        'elt'         => ':attribute必须小于等于 :rule',
69
        'lt'          => ':attribute必须小于 :rule',
70
        'eq'          => ':attribute必须等于 :rule',
71
        'unique'      => ':attribute已存在',
72
        'regex'       => ':attribute不符合指定规则',
73
        'method'      => '无效的请求类型',
74
        'token'       => '令牌数据无效',
75
        'fileSize'    => '上传文件大小不符',
76
        'fileExt'     => '上传文件后缀不符',
77
        'fileMime'    => '上传文件类型不符',
78
79
    ];
80
81
    // 当前验证场景
82
    protected $currentScene=null;
83
84
    // 正则表达式 regex = ['zip'=>'\d{6}',...]
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
85
    protected $regex=[];
86
87
    // 验证场景 scene = ['edit'=>'name1,name2,...']
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
88
    protected $scene=[];
89
90
    // 验证失败错误信息
91
    protected $error=[];
92
93
    // 批量验证
94
    protected $batch=false;
95
96
    /**
97
     * 构造函数
98
     * @access public
99
     * @param array $rules 验证规则
100
     * @param array $message 验证提示信息
101
     * @param array $field 验证字段描述信息
102
     */
103
    public function __construct(array $rules=[], $message=[], $field=[])
104
    {
105
        $this->rule=array_merge($this->rule, $rules);
106
        $this->message=array_merge($this->message, $message);
107
        $this->field=array_merge($this->field, $field);
108
    }
109
110
    /**
111
     * 实例化验证
112
     * @access public
113
     * @param array     $rules 验证规则
114
     * @param array     $message 验证提示信息
115
     * @param array     $field 验证字段描述信息
116
     * @return Validate
117
     */
118
    public static function make($rules=[], $message=[], $field=[])
119
    {
120
        if (is_null(self::$instance)) {
121
            self::$instance=new self($rules, $message, $field);
122
        }
123
        return self::$instance;
124
    }
125
126
    /**
127
     * 添加字段验证规则
128
     * @access protected
129
     * @param string|array  $name  字段名称或者规则数组
130
     * @param mixed         $rule  验证规则
131
     * @return Validate
132
     */
133
    public function rule($name, $rule='')
134
    {
135
        if (is_array($name)) {
136
            $this->rule=array_merge($this->rule, $name);
137
        } else {
138
            $this->rule[$name]=$rule;
139
        }
140
        return $this;
141
    }
142
143
    /**
144
     * 注册验证(类型)规则
145
     * @access public
146
     * @param string    $type  验证规则类型
147
     * @param mixed     $callback callback方法(或闭包)
148
     * @return void
149
     */
150
    public static function extend($type, $callback=null)
151
    {
152
        if (is_array($type)) {
153
            self::$type=array_merge(self::$type, $type);
154
        } else {
155
            self::$type[$type]=$callback;
156
        }
157
    }
158
159
    /**
160
     * 获取验证规则的默认提示信息
161
     * @access protected
162
     * @param string|array  $type  验证规则类型名称或者数组
163
     * @param string        $msg  验证提示信息
164
     * @return void
165
     */
166
    public static function setTypeMsg($type, $msg=null)
167
    {
168
        if (is_array($type)) {
169
            self::$typeMsg=array_merge(self::$typeMsg, $type);
170
        } else {
171
            self::$typeMsg[$type]=$msg;
172
        }
173
    }
174
175
    /**
176
     * 设置提示信息
177
     * @access public
178
     * @param string|array  $name  字段名称
179
     * @param string        $message 提示信息
180
     * @return Validate
181
     */
182
    public function message($name, $message='')
183
    {
184
        if (is_array($name)) {
185
            $this->message=array_merge($this->message, $name);
186
        } else {
187
            $this->message[$name]=$message;
188
        }
189
        return $this;
190
    }
191
192
    /**
193
     * 设置验证场景
194
     * @access public
195
     * @param string|array  $name  场景名或者场景设置数组
196
     * @param mixed         $fields 要验证的字段
197
     * @return Validate
198
     */
199
    public function scene($name, $fields=null)
200
    {
201
        if (is_array($name)) {
202
            $this->scene=array_merge($this->scene, $name);
203
        }if (is_null($fields)) {
204
        // 设置当前场景
205
        $this->currentScene=$name;
206
    } else {
207
        // 设置验证场景
208
        $this->scene[$name]=$fields;
209
    }
210
        return $this;
211
    }
212
213
    /**
214
     * 判断是否存在某个验证场景
215
     * @access public
216
     * @param string $name 场景名
217
     * @return bool
218
     */
219
    public function hasScene($name)
220
    {
221
        return isset($this->scene[$name]);
222
    }
223
224
    /**
225
     * 设置批量验证
226
     * @access public
227
     * @param bool $batch  是否批量验证
228
     * @return Validate
229
     */
230
    public function batch($batch=true)
231
    {
232
        $this->batch=$batch;
233
        return $this;
234
    }
235
236
    /**
237
     * 数据自动验证
238
     * @access public
239
     * @param array     $data  数据
240
     * @param mixed     $rules  验证规则
241
     * @param string    $scene 验证场景
242
     * @return bool
243
     */
244
    public function check($data, $rules=[], $scene='')
245
    {
246
        $this->error=[];
247
248
        if (empty($rules)) {
249
            // 读取验证规则
250
            $rules=$this->rule;
251
        }
252
253
        // 分析验证规则
254
        $scene=$this->getScene($scene);
255
        if (is_array($scene)) {
256
            // 处理场景验证字段
257
            $change=[];
258
            $array=[];
259
            foreach ($scene as $k => $val) {
260
                if (is_numeric($k)) {
261
                    $array[]=$val;
262
                } else {
263
                    $array[]=$k;
264
                    $change[$k]=$val;
265
                }
266
            }
267
        }
268
269
        foreach ($rules as $key => $item) {
270
            // field => rule1|rule2... field=>['rule1','rule2',...]
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
271
            if (is_numeric($key)) {
272
                // [field,rule1|rule2,msg1|msg2]
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
273
                $key=$item[0];
274
                $rule=$item[1];
275
                if (isset($item[2])) {
276
                    $msg=is_string($item[2]) ? explode('|', $item[2]) : $item[2];
277
                } else {
278
                    $msg=[];
279
                }
280
            } else {
281
                $rule=$item;
282
                $msg=[];
283
            }
284
            if (strpos($key, '|')) {
285
                // 字段|描述 用于指定属性名称
286
                list($key, $title)=explode('|', $key);
287
            } else {
288
                $title=isset($this->field[$key]) ? $this->field[$key] : $key;
289
            }
290
291
            // 场景检测
292
            if (!empty($scene)) {
293
                if ($scene instanceof \Closure && !call_user_func_array($scene, [$key, $data])) {
294
                    continue;
295
                } elseif (is_array($scene)) {
296
                    if (!in_array($key, $array)) {
0 ignored issues
show
Bug introduced by
The variable $array does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
297
                        continue;
298
                    } elseif (isset($change[$key])) {
299
                        // 重载某个验证规则
300
                        $rule=$change[$key];
301
                    }
302
                }
303
            }
304
305
            // 获取数据 支持二维数组
306
            $value=$this->getDataValue($data, $key);
307
308
            // 字段验证
309
            if ($rule instanceof \Closure) {
310
                // 匿名函数验证 支持传入当前字段和所有字段两个数据
311
                $result=call_user_func_array($rule, [$value, $data]);
312
            } else {
313
                $result=$this->checkItem($key, $value, $rule, $data, $title, $msg);
314
            }
315
316
            if (true !== $result) {
317
                // 没有返回true 则表示验证失败
318
                if (!empty($this->batch)) {
319
                    // 批量验证
320
                    if (is_array($result)) {
321
                        $this->error=array_merge($this->error, $result);
322
                    } else {
323
                        $this->error[$key]=$result;
324
                    }
325
                } else {
326
                    $this->error=$result;
0 ignored issues
show
Documentation Bug introduced by
It seems like $result of type * is incompatible with the declared type array of property $error.

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...
327
                    return false;
328
                }
329
            }
330
        }
331
        return !empty($this->error) ? false : true;
332
    }
333
334
    /**
335
     * 验证单个字段规则
336
     * @access protected
337
     * @param string    $field  字段名
338
     * @param mixed     $value  字段值
339
     * @param mixed     $rules  验证规则
340
     * @param array     $data  数据
341
     * @param string    $title  字段描述
342
     * @param array     $msg  提示信息
343
     * @return mixed
344
     */
345
    protected function checkItem($field, $value, $rules, $data, $title='', $msg=[])
346
    {
347
        // 支持多规则验证 require|in:a,b,c|... 或者 ['require','in'=>'a,b,c',...]
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
348
        if (is_string($rules)) {
349
            $rules=explode('|', $rules);
350
        }
351
        $i=0;
352
        foreach ($rules as $key => $rule) {
0 ignored issues
show
Bug introduced by
The expression $rules of type object|integer|double|null|array|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
353
            if ($rule instanceof \Closure) {
354
                $result=call_user_func_array($rule, [$value, $data]);
355
                $info=is_numeric($key) ? '' : $key;
356
            } else {
357
                // 判断验证类型
358
                if (is_numeric($key)) {
359
                    if (strpos($rule, ':')) {
360
                        list($type, $rule)=explode(':', $rule, 2);
361
                        if (isset($this->alias[$type])) {
362
                            // 判断别名
363
                            $type=$this->alias[$type];
364
                        }
365
                        $info=$type;
366
                    } elseif (method_exists($this, $rule)) {
367
                        $type=$rule;
368
                        $info=$rule;
369
                        $rule='';
370
                    } else {
371
                        $type='is';
372
                        $info=$rule;
373
                    }
374
                } else {
375
                    $info=$type=$key;
376
                }
377
378
                // 如果不是require 有数据才会行验证
379
                if (0 === strpos($info, 'require') || (!is_null($value) && '' !== $value)) {
380
                    // 验证类型
381
                    $callback=isset(self::$type[$type]) ? self::$type[$type] : [$this, $type];
382
                    // 验证数据
383
                    $result=call_user_func_array($callback, [$value, $rule, $data, $field, $title]);
384
                } else {
385
                    $result=true;
386
                }
387
            }
388
389
            if (false === $result) {
390
                // 验证失败 返回错误信息
391
                if (isset($msg[$i])) {
392
                    $message=$msg[$i];
393
                    if (is_string($message) && strpos($message, '{%') === 0) {
394
                        $message=Lang::get(substr($message, 2, -1));
395
                    }
396
                } else {
397
                    $message=$this->getRuleMsg($field, $title, $info, $rule);
398
                }
399
                return $message;
400
            } elseif (true !== $result) {
401
                // 返回自定义错误信息
402
                if (is_string($result) && false !== strpos($result, ':')) {
403
                    $result=str_replace([':attribute', ':rule'], [$title, (string) $rule], $result);
404
                }
405
                return $result;
406
            }
407
            $i++;
408
        }
409
        return $result;
0 ignored issues
show
Bug introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
410
    }
411
412
    /**
413
     * 验证是否和某个字段的值一致
414
     * @access protected
415
     * @param mixed     $value 字段值
416
     * @param mixed     $rule  验证规则
417
     * @param array     $data  数据
418
     * @param string    $field 字段名
419
     * @return bool
420
     */
421
    protected function confirm($value, $rule, $data, $field='')
422
    {
423
        if ('' == $rule) {
424
            if (strpos($field, '_confirm')) {
425
                $rule=strstr($field, '_confirm', true);
426
            } else {
427
                $rule=$field.'_confirm';
428
            }
429
        }
430
        return $this->getDataValue($data, $rule) === $value;
431
    }
432
433
    /**
434
     * 验证是否和某个字段的值是否不同
435
     * @access protected
436
     * @param mixed $value 字段值
437
     * @param mixed $rule  验证规则
438
     * @param array $data  数据
439
     * @return bool
440
     */
441
    protected function different($value, $rule, $data)
442
    {
443
        return $this->getDataValue($data, $rule) != $value;
444
    }
445
446
    /**
447
     * 验证是否大于等于某个值
448
     * @access protected
449
     * @param mixed     $value  字段值
450
     * @param mixed     $rule  验证规则
451
     * @return bool
452
     */
453
    protected function egt($value, $rule)
454
    {
455
        return $value >= $rule;
456
    }
457
458
    /**
459
     * 验证是否大于某个值
460
     * @access protected
461
     * @param mixed     $value  字段值
462
     * @param mixed     $rule  验证规则
463
     * @return bool
464
     */
465
    protected function gt($value, $rule)
466
    {
467
        return $value > $rule;
468
    }
469
470
    /**
471
     * 验证是否小于等于某个值
472
     * @access protected
473
     * @param mixed     $value  字段值
474
     * @param mixed     $rule  验证规则
475
     * @return bool
476
     */
477
    protected function elt($value, $rule)
478
    {
479
        return $value <= $rule;
480
    }
481
482
    /**
483
     * 验证是否小于某个值
484
     * @access protected
485
     * @param mixed     $value  字段值
486
     * @param mixed     $rule  验证规则
487
     * @return bool
488
     */
489
    protected function lt($value, $rule)
490
    {
491
        return $value < $rule;
492
    }
493
494
    /**
495
     * 验证是否等于某个值
496
     * @access protected
497
     * @param mixed     $value  字段值
498
     * @param mixed     $rule  验证规则
499
     * @return bool
500
     */
501
    protected function eq($value, $rule)
502
    {
503
        return $value == $rule;
504
    }
505
506
    /**
507
     * 验证字段值是否为有效格式
508
     * @access protected
509
     * @param mixed     $value  字段值
510
     * @param string    $rule  验证规则
511
     * @param array     $data  验证数据
512
     * @return bool
513
     */
514
    protected function is($value, $rule, $data=[])
515
    {
516
        switch ($rule) {
517
            case 'require':
518
                // 必须
519
                $result=!empty($value) || '0' == $value;
520
                break;
521
            case 'accepted':
522
                // 接受
523
                $result=in_array($value, ['1', 'on', 'yes']);
524
                break;
525
            case 'date':
526
                // 是否是一个有效日期
527
                $result=false !== strtotime($value);
528
                break;
529
            case 'alpha':
530
                // 只允许字母
531
                $result=$this->regex($value, '/^[A-Za-z]+$/');
532
                break;
533
            case 'alphaNum':
534
                // 只允许字母和数字
535
                $result=$this->regex($value, '/^[A-Za-z0-9]+$/');
536
                break;
537
            case 'alphaDash':
538
                // 只允许字母、数字和下划线 破折号
539
                $result=$this->regex($value, '/^[A-Za-z0-9\-\_]+$/');
540
                break;
541
            case 'chs':
542
                // 只允许汉字
543
                $result=$this->regex($value, '/^[\x{4e00}-\x{9fa5}]+$/u');
544
                break;
545
            case 'chsAlpha':
546
                // 只允许汉字、字母
547
                $result=$this->regex($value, '/^[\x{4e00}-\x{9fa5}a-zA-Z]+$/u');
548
                break;
549
            case 'chsAlphaNum':
550
                // 只允许汉字、字母和数字
551
                $result=$this->regex($value, '/^[\x{4e00}-\x{9fa5}a-zA-Z0-9]+$/u');
552
                break;
553
            case 'chsDash':
554
                // 只允许汉字、字母、数字和下划线_及破折号-
555
                $result=$this->regex($value, '/^[\x{4e00}-\x{9fa5}a-zA-Z0-9\_\-]+$/u');
556
                break;
557
            case 'activeUrl':
558
                // 是否为有效的网址
559
                $result=checkdnsrr($value);
560
                break;
561
            case 'ip':
562
                // 是否为IP地址
563
                $result=$this->filter($value, [FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6]);
564
                break;
565
            case 'url':
566
                // 是否为一个URL地址
567
                $result=$this->filter($value, FILTER_VALIDATE_URL);
568
                break;
569
            case 'float':
570
                // 是否为float
571
                $result=$this->filter($value, FILTER_VALIDATE_FLOAT);
572
                break;
573
            case 'number':
574
                $result=is_numeric($value);
575
                break;
576
            case 'integer':
577
                // 是否为整型
578
                $result=$this->filter($value, FILTER_VALIDATE_INT);
579
                break;
580
            case 'email':
581
                // 是否为邮箱地址
582
                $result=$this->filter($value, FILTER_VALIDATE_EMAIL);
583
                break;
584
            case 'boolean':
585
                // 是否为布尔值
586
                $result=in_array($value, [true, false, 0, 1, '0', '1'], true);
587
                break;
588
            case 'array':
589
                // 是否为数组
590
                $result=is_array($value);
591
                break;
592
            case 'file':
593
                $result=$value instanceof File;
0 ignored issues
show
Bug introduced by
The class puck\File does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
594
                break;
595
            case 'image':
596
                $result=$value instanceof File && in_array($this->getImageType($value->getRealPath()), [1, 2, 3, 6]);
0 ignored issues
show
Bug introduced by
The class puck\File does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
597
                break;
598
            case 'token':
599
                $result=$this->token($value, '__token__', $data);
600
                break;
601
            default:
602
                if (isset(self::$type[$rule])) {
603
                    // 注册的验证规则
604
                    $result=call_user_func_array(self::$type[$rule], [$value]);
605
                } else {
606
                    // 正则验证
607
                    $result=$this->regex($value, $rule);
608
                }
609
        }
610
        return $result;
611
    }
612
613
    // 判断图像类型
614
    protected function getImageType($image)
615
    {
616
        if (function_exists('exif_imagetype')) {
617
            return exif_imagetype($image);
618
        } else {
619
            $info=getimagesize($image);
620
            return $info[2];
621
        }
622
    }
623
624
    /**
625
     * 验证是否为合格的域名或者IP 支持A,MX,NS,SOA,PTR,CNAME,AAAA,A6, SRV,NAPTR,TXT 或者 ANY类型
626
     * @access protected
627
     * @param mixed     $value  字段值
628
     * @param mixed     $rule  验证规则
629
     * @return bool
630
     */
631
    protected function activeUrl($value, $rule)
632
    {
633
        if (!in_array($rule, ['A', 'MX', 'NS', 'SOA', 'PTR', 'CNAME', 'AAAA', 'A6', 'SRV', 'NAPTR', 'TXT', 'ANY'])) {
634
            $rule='MX';
635
        }
636
        return checkdnsrr($value, $rule);
637
    }
638
639
    /**
640
     * 验证是否有效IP
641
     * @access protected
642
     * @param mixed     $value  字段值
643
     * @param mixed     $rule  验证规则 ipv4 ipv6
644
     * @return bool
645
     */
646
    protected function ip($value, $rule)
647
    {
648
        if (!in_array($rule, ['ipv4', 'ipv6'])) {
649
            $rule='ipv4';
650
        }
651
        return $this->filter($value, [FILTER_VALIDATE_IP, 'ipv6' == $rule ? FILTER_FLAG_IPV6 : FILTER_FLAG_IPV4]);
652
    }
653
654
    /**
655
     * 验证上传文件后缀
656
     * @access protected
657
     * @param mixed     $file  上传文件
658
     * @param mixed     $rule  验证规则
659
     * @return bool
660
     */
661
    protected function fileExt($file, $rule)
662
    {
663
        if (!($file instanceof File)) {
0 ignored issues
show
Bug introduced by
The class puck\File does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
664
            return false;
665
        }
666
        if (is_string($rule)) {
667
            $rule=explode(',', $rule);
668
        }
669
        if (is_array($file)) {
670
            foreach ($file as $item) {
671
                if (!$item->checkExt($rule)) {
672
                    return false;
673
                }
674
            }
675
            return true;
676
        } else {
677
            return $file->checkExt($rule);
678
        }
679
    }
680
681
    /**
682
     * 验证上传文件类型
683
     * @access protected
684
     * @param mixed     $file  上传文件
685
     * @param mixed     $rule  验证规则
686
     * @return bool
687
     */
688
    protected function fileMime($file, $rule)
689
    {
690
        if (!($file instanceof File)) {
0 ignored issues
show
Bug introduced by
The class puck\File does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
691
            return false;
692
        }
693
        if (is_string($rule)) {
694
            $rule=explode(',', $rule);
695
        }
696
        if (is_array($file)) {
697
            foreach ($file as $item) {
698
                if (!$item->checkMime($rule)) {
699
                    return false;
700
                }
701
            }
702
            return true;
703
        } else {
704
            return $file->checkMime($rule);
705
        }
706
    }
707
708
    /**
709
     * 验证上传文件大小
710
     * @access protected
711
     * @param mixed     $file  上传文件
712
     * @param mixed     $rule  验证规则
713
     * @return bool
714
     */
715
    protected function fileSize($file, $rule)
716
    {
717
        if (!($file instanceof File)) {
0 ignored issues
show
Bug introduced by
The class puck\File does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
718
            return false;
719
        }
720
        if (is_array($file)) {
721
            foreach ($file as $item) {
722
                if (!$item->checkSize($rule)) {
723
                    return false;
724
                }
725
            }
726
            return true;
727
        } else {
728
            return $file->checkSize($rule);
729
        }
730
    }
731
732
    /**
733
     * 验证图片的宽高及类型
734
     * @access protected
735
     * @param mixed     $file  上传文件
736
     * @param mixed     $rule  验证规则
737
     * @return bool
738
     */
739
    protected function image($file, $rule)
740
    {
741
        if (!($file instanceof File)) {
0 ignored issues
show
Bug introduced by
The class puck\File does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
742
            return false;
743
        }
744
        if ($rule) {
745
            $rule=explode(',', $rule);
746
            list($width, $height, $type)=getimagesize($file->getRealPath());
747
            if (isset($rule[2])) {
748
                $imageType=strtolower($rule[2]);
749
                if ('jpeg' == $imageType) {
750
                    $imageType='jpg';
751
                }
752
                if (image_type_to_extension($type, false) != $imageType) {
753
                    return false;
754
                }
755
            }
756
757
            list($w, $h)=$rule;
758
            return $w == $width && $h == $height;
759
        } else {
760
            return in_array($this->getImageType($file->getRealPath()), [1, 2, 3, 6]);
761
        }
762
    }
763
764
    /**
765
     * 验证请求类型
766
     * @access protected
767
     * @param mixed     $value  字段值
768
     * @param mixed     $rule  验证规则
769
     * @return bool
770
     */
771
    protected function method($value, $rule)
0 ignored issues
show
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
772
    {
773
        $method=Request::instance()->method();
0 ignored issues
show
Bug introduced by
The method instance() does not seem to exist on object<puck\Request>.

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

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

Loading history...
774
        return strtoupper($rule) == $method;
775
    }
776
777
    /**
778
     * 验证时间和日期是否符合指定格式
779
     * @access protected
780
     * @param mixed     $value  字段值
781
     * @param mixed     $rule  验证规则
782
     * @return bool
783
     */
784
    protected function dateFormat($value, $rule)
785
    {
786
        $info=date_parse_from_format($rule, $value);
787
        return 0 == $info['warning_count'] && 0 == $info['error_count'];
788
    }
789
790
    /**
791
     * 验证是否唯一
792
     * @access protected
793
     * @param mixed     $value  字段值
794
     * @param mixed     $rule  验证规则 格式:数据表,字段名,排除ID,主键名
795
     * @param array     $data  数据
796
     * @param string    $field  验证字段名
797
     * @return bool
798
     */
799
    protected function unique($value, $rule, $data, $field)
0 ignored issues
show
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
800
    {
801
        if (is_string($rule)) {
802
            $rule=explode(',', $rule);
803
        }
804
        if (false !== strpos($rule[0], '\\')) {
805
            // 指定模型类
806
            $db=new $rule[0];
807
        } else {
808
            try {
809
                $db=Loader::model($rule[0]);
810
            } catch (ClassNotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class puck\ClassNotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
811
                $db=Db::name($rule[0]);
0 ignored issues
show
Bug introduced by
The method name() does not seem to exist on object<puck\Db>.

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

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

Loading history...
812
            }
813
        }
814
        $key=isset($rule[1]) ? $rule[1] : $field;
815
816
        if (strpos($key, '^')) {
817
            // 支持多个字段验证
818
            $fields=explode('^', $key);
819
            foreach ($fields as $key) {
820
                $map[$key]=$data[$key];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$map was never initialized. Although not strictly required by PHP, it is generally a good practice to add $map = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
821
            }
822
        } elseif (strpos($key, '=')) {
823
            parse_str($key, $map);
824
        } else {
825
            $map[$key]=$data[$field];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$map was never initialized. Although not strictly required by PHP, it is generally a good practice to add $map = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
826
        }
827
828
        $pk=strval(isset($rule[3]) ? $rule[3] : $db->getPk());
829
        if (isset($rule[2])) {
830
            $map[$pk]=['neq', $rule[2]];
0 ignored issues
show
Bug introduced by
The variable $map does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
831
        } elseif (isset($data[$pk])) {
832
            $map[$pk]=['neq', $data[$pk]];
833
        }
834
835
        if ($db->where($map)->field($pk)->find()) {
836
            return false;
837
        }
838
        return true;
839
    }
840
841
    /**
842
     * 使用行为类验证
843
     * @access protected
844
     * @param mixed     $value  字段值
845
     * @param mixed     $rule  验证规则
846
     * @param array     $data  数据
847
     * @return mixed
848
     */
849
    protected function behavior($value, $rule, $data)
0 ignored issues
show
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
850
    {
851
        return Hook::exec($rule, '', $data);
852
    }
853
854
    /**
855
     * 使用filter_var方式验证
856
     * @access protected
857
     * @param mixed     $value  字段值
858
     * @param mixed     $rule  验证规则
859
     * @return bool
860
     */
861
    protected function filter($value, $rule)
862
    {
863
        if (is_string($rule) && strpos($rule, ',')) {
864
            list($rule, $param)=explode(',', $rule);
865
        } elseif (is_array($rule)) {
866
            $param=isset($rule[1]) ? $rule[1] : null;
867
            $rule=$rule[0];
868
        } else {
869
            $param=null;
870
        }
871
        return false !== filter_var($value, is_int($rule) ? $rule : filter_id($rule), $param);
872
    }
873
874
    /**
875
     * 验证某个字段等于某个值的时候必须
876
     * @access protected
877
     * @param mixed     $value  字段值
878
     * @param mixed     $rule  验证规则
879
     * @param array     $data  数据
880
     * @return bool
881
     */
882
    protected function requireIf($value, $rule, $data)
883
    {
884
        list($field, $val)=explode(',', $rule);
885
        if ($this->getDataValue($data, $field) == $val) {
886
            return !empty($value);
887
        } else {
888
            return true;
889
        }
890
    }
891
892
    /**
893
     * 通过回调方法验证某个字段是否必须
894
     * @access protected
895
     * @param mixed     $value  字段值
896
     * @param mixed     $rule  验证规则
897
     * @param array     $data  数据
898
     * @return bool
899
     */
900
    protected function requireCallback($value, $rule, $data)
901
    {
902
        $result=call_user_func_array($rule, [$value, $data]);
903
        if ($result) {
904
            return !empty($value);
905
        } else {
906
            return true;
907
        }
908
    }
909
910
    /**
911
     * 验证某个字段有值的情况下必须
912
     * @access protected
913
     * @param mixed     $value  字段值
914
     * @param mixed     $rule  验证规则
915
     * @param array     $data  数据
916
     * @return bool
917
     */
918
    protected function requireWith($value, $rule, $data)
919
    {
920
        $val=$this->getDataValue($data, $rule);
921
        if (!empty($val)) {
922
            return !empty($value);
923
        } else {
924
            return true;
925
        }
926
    }
927
928
    /**
929
     * 验证是否在范围内
930
     * @access protected
931
     * @param mixed     $value  字段值
932
     * @param mixed     $rule  验证规则
933
     * @return bool
934
     */
935
    protected function in($value, $rule)
936
    {
937
        return in_array($value, is_array($rule) ? $rule : explode(',', $rule));
938
    }
939
940
    /**
941
     * 验证是否不在某个范围
942
     * @access protected
943
     * @param mixed     $value  字段值
944
     * @param mixed     $rule  验证规则
945
     * @return bool
946
     */
947
    protected function notIn($value, $rule)
948
    {
949
        return !in_array($value, is_array($rule) ? $rule : explode(',', $rule));
950
    }
951
952
    /**
953
     * between验证数据
954
     * @access protected
955
     * @param mixed     $value  字段值
956
     * @param mixed     $rule  验证规则
957
     * @return bool
958
     */
959
    protected function between($value, $rule)
960
    {
961
        if (is_string($rule)) {
962
            $rule=explode(',', $rule);
963
        }
964
        list($min, $max)=$rule;
965
        return $value >= $min && $value <= $max;
966
    }
967
968
    /**
969
     * 使用notbetween验证数据
970
     * @access protected
971
     * @param mixed     $value  字段值
972
     * @param mixed     $rule  验证规则
973
     * @return bool
974
     */
975
    protected function notBetween($value, $rule)
976
    {
977
        if (is_string($rule)) {
978
            $rule=explode(',', $rule);
979
        }
980
        list($min, $max)=$rule;
981
        return $value < $min || $value > $max;
982
    }
983
984
    /**
985
     * 验证数据长度
986
     * @access protected
987
     * @param mixed     $value  字段值
988
     * @param mixed     $rule  验证规则
989
     * @return bool
990
     */
991
    protected function length($value, $rule)
992
    {
993
        if (is_array($value)) {
994
            $length=count($value);
995
        } elseif ($value instanceof File) {
0 ignored issues
show
Bug introduced by
The class puck\File does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
996
            $length=$value->getSize();
997
        } else {
998
            $length=mb_strlen((string) $value);
999
        }
1000
1001
        if (strpos($rule, ',')) {
1002
            // 长度区间
1003
            list($min, $max)=explode(',', $rule);
1004
            return $length >= $min && $length <= $max;
1005
        } else {
1006
            // 指定长度
1007
            return $length == $rule;
1008
        }
1009
    }
1010
1011
    /**
1012
     * 验证数据最大长度
1013
     * @access protected
1014
     * @param mixed     $value  字段值
1015
     * @param mixed     $rule  验证规则
1016
     * @return bool
1017
     */
1018
    protected function max($value, $rule)
1019
    {
1020
        if (is_array($value)) {
1021
            $length=count($value);
1022
        } elseif ($value instanceof File) {
0 ignored issues
show
Bug introduced by
The class puck\File does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
1023
            $length=$value->getSize();
1024
        } else {
1025
            $length=mb_strlen((string) $value);
1026
        }
1027
        return $length <= $rule;
1028
    }
1029
1030
    /**
1031
     * 验证数据最小长度
1032
     * @access protected
1033
     * @param mixed     $value  字段值
1034
     * @param mixed     $rule  验证规则
1035
     * @return bool
1036
     */
1037
    protected function min($value, $rule)
1038
    {
1039
        if (is_array($value)) {
1040
            $length=count($value);
1041
        } elseif ($value instanceof File) {
0 ignored issues
show
Bug introduced by
The class puck\File does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
1042
            $length=$value->getSize();
1043
        } else {
1044
            $length=mb_strlen((string) $value);
1045
        }
1046
        return $length >= $rule;
1047
    }
1048
1049
    /**
1050
     * 验证日期
1051
     * @access protected
1052
     * @param mixed     $value  字段值
1053
     * @param mixed     $rule  验证规则
1054
     * @return bool
1055
     */
1056
    protected function after($value, $rule)
1057
    {
1058
        return strtotime($value) >= strtotime($rule);
1059
    }
1060
1061
    /**
1062
     * 验证日期
1063
     * @access protected
1064
     * @param mixed     $value  字段值
1065
     * @param mixed     $rule  验证规则
1066
     * @return bool
1067
     */
1068
    protected function before($value, $rule)
1069
    {
1070
        return strtotime($value) <= strtotime($rule);
1071
    }
1072
1073
    /**
1074
     * 验证有效期
1075
     * @access protected
1076
     * @param mixed     $value  字段值
1077
     * @param mixed     $rule  验证规则
1078
     * @return bool
1079
     */
1080
    protected function expire($value, $rule)
0 ignored issues
show
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Coding Style introduced by
expire uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
1081
    {
1082
        if (is_string($rule)) {
1083
            $rule=explode(',', $rule);
1084
        }
1085
        list($start, $end)=$rule;
1086
        if (!is_numeric($start)) {
1087
            $start=strtotime($start);
1088
        }
1089
1090
        if (!is_numeric($end)) {
1091
            $end=strtotime($end);
1092
        }
1093
        return $_SERVER['REQUEST_TIME'] >= $start && $_SERVER['REQUEST_TIME'] <= $end;
1094
    }
1095
1096
    /**
1097
     * 验证IP许可
1098
     * @access protected
1099
     * @param string    $value  字段值
1100
     * @param mixed     $rule  验证规则
1101
     * @return boolean
1102
     */
1103
    protected function allowIp($value, $rule)
0 ignored issues
show
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Coding Style introduced by
allowIp uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
1104
    {
1105
        return in_array($_SERVER['REMOTE_ADDR'], is_array($rule) ? $rule : explode(',', $rule));
1106
    }
1107
1108
    /**
1109
     * 验证IP禁用
1110
     * @access protected
1111
     * @param string    $value  字段值
1112
     * @param mixed     $rule  验证规则
1113
     * @return boolean
1114
     */
1115
    protected function denyIp($value, $rule)
0 ignored issues
show
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Coding Style introduced by
denyIp uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
1116
    {
1117
        return !in_array($_SERVER['REMOTE_ADDR'], is_array($rule) ? $rule : explode(',', $rule));
1118
    }
1119
1120
    /**
1121
     * 使用正则验证数据
1122
     * @access protected
1123
     * @param mixed     $value  字段值
1124
     * @param string     $rule  验证规则 正则规则或者预定义正则名
1125
     * @return boolean
1126
     */
1127
    protected function regex($value, $rule)
1128
    {
1129
        if (isset($this->regex[$rule])) {
1130
            $rule=$this->regex[$rule];
1131
        }
1132
        if (0 !== strpos($rule, '/') && !preg_match('/\/[imsU]{0,4}$/', $rule)) {
1133
            // 不是正则表达式则两端补上/
1134
            $rule='/^'.$rule.'$/';
1135
        }
1136
        return 1 === preg_match($rule, (string) $value);
1137
    }
1138
1139
    /**
1140
     * 验证表单令牌
1141
     * @access protected
1142
     * @param mixed     $value  字段值
1143
     * @param string     $rule  验证规则
1144
     * @param array     $data  数据
1145
     * @return bool
1146
     */
1147
    protected function token($value, $rule, $data)
0 ignored issues
show
Unused Code introduced by
The parameter $value is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1148
    {
1149
        $rule=!empty($rule) ? $rule : '__token__';
1150
        if (!isset($data[$rule]) || !Session::has($rule)) {
1151
            // 令牌数据无效
1152
            return false;
1153
        }
1154
1155
        // 令牌验证
1156
        if (isset($data[$rule]) && Session::get($rule) === $data[$rule]) {
1157
            // 防止重复提交
1158
            Session::delete($rule); // 验证完成销毁session
1159
            return true;
1160
        }
1161
        // 开启TOKEN重置
1162
        Session::delete($rule);
1163
        return false;
1164
    }
1165
1166
    // 获取错误信息
1167
    public function getError()
1168
    {
1169
        return $this->error;
1170
    }
1171
1172
    /**
1173
     * 获取数据值
1174
     * @access protected
1175
     * @param array     $data  数据
1176
     * @param string    $key  数据标识 支持二维
1177
     * @return mixed
1178
     */
1179
    protected function getDataValue($data, $key)
1180
    {
1181
        if (strpos($key, '.')) {
1182
            // 支持二维数组验证
1183
            list($name1, $name2)=explode('.', $key);
1184
            $value=isset($data[$name1][$name2]) ? $data[$name1][$name2] : null;
1185
        } else {
1186
            $value=isset($data[$key]) ? $data[$key] : null;
1187
        }
1188
        return $value;
1189
    }
1190
1191
    /**
1192
     * 获取验证规则的错误提示信息
1193
     * @access protected
1194
     * @param string    $attribute  字段英文名
1195
     * @param string    $title  字段描述名
1196
     * @param string    $type  验证规则名称
1197
     * @param mixed     $rule  验证规则数据
1198
     * @return string
1199
     */
1200
    protected function getRuleMsg($attribute, $title, $type, $rule)
1201
    {
1202
        if (isset($this->message[$attribute.'.'.$type])) {
1203
            $msg=$this->message[$attribute.'.'.$type];
1204
        } elseif (isset($this->message[$attribute][$type])) {
1205
            $msg=$this->message[$attribute][$type];
1206
        } elseif (isset($this->message[$attribute])) {
1207
            $msg=$this->message[$attribute];
1208
        } elseif (isset(self::$typeMsg[$type])) {
1209
            $msg=self::$typeMsg[$type];
1210
        } else {
1211
            $msg=$title.'规则错误';
1212
        }
1213
1214
        if (is_string($msg) && 0 === strpos($msg, '{%')) {
1215
            $msg=Lang::get(substr($msg, 2, -1));
1216
        }
1217
1218
        if (is_string($msg) && is_scalar($rule) && false !== strpos($msg, ':')) {
1219
            // 变量替换
1220
            if (is_string($rule) && strpos($rule, ',')) {
1221
                $array=array_pad(explode(',', $rule), 3, '');
1222
            } else {
1223
                $array=array_pad([], 3, '');
1224
            }
1225
            $msg=str_replace(
1226
                [':attribute', ':rule', ':1', ':2', ':3'],
1227
                [$title, (string) $rule, $array[0], $array[1], $array[2]],
1228
                $msg);
1229
        }
1230
        return $msg;
1231
    }
1232
1233
    /**
1234
     * 获取数据验证的场景
1235
     * @access protected
1236
     * @param string $scene  验证场景
1237
     * @return array
1238
     */
1239
    protected function getScene($scene='')
1240
    {
1241
        if (empty($scene)) {
1242
            // 读取指定场景
1243
            $scene=$this->currentScene;
1244
        }
1245
1246
        if (!empty($scene) && isset($this->scene[$scene])) {
1247
            // 如果设置了验证适用场景
1248
            $scene=$this->scene[$scene];
1249
            if (is_string($scene)) {
1250
                $scene=explode(',', $scene);
1251
            }
1252
        } else {
1253
            $scene=[];
1254
        }
1255
        return $scene;
1256
    }
1257
1258
    public static function __callStatic($method, $params)
1259
    {
1260
        $class=self::make();
1261
        if (method_exists($class, $method)) {
1262
            return call_user_func_array([$class, $method], $params);
1263
        } else {
1264
            throw new \Exception('method not exists:'.__CLASS__.'->'.$method);
1265
        }
1266
    }
1267
}