Issues (910)

framework/validators/RangeValidator.php (1 issue)

1
<?php
2
/**
3
 * @link https://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license https://www.yiiframework.com/license/
6
 */
7
8
namespace yii\validators;
9
10
use Yii;
11
use yii\base\InvalidConfigException;
12
use yii\helpers\ArrayHelper;
13
use yii\helpers\Json;
14
15
/**
16
 * RangeValidator validates that the attribute value is among a list of values.
17
 *
18
 * The range can be specified via the [[range]] property.
19
 * If the [[not]] property is set true, the validator will ensure the attribute value
20
 * is NOT among the specified range.
21
 *
22
 * @author Qiang Xue <[email protected]>
23
 * @since 2.0
24
 */
25
class RangeValidator extends Validator
26
{
27
    /**
28
     * @var array|\Traversable|\Closure a list of valid values that the attribute value should be among or an anonymous function that returns
29
     * such a list. The signature of the anonymous function should be as follows,
30
     *
31
     * ```php
32
     * function($model, $attribute) {
33
     *     // compute range
34
     *     return $range;
35
     * }
36
     * ```
37
     */
38
    public $range;
39
    /**
40
     * @var bool whether the comparison is strict (both type and value must be the same)
41
     */
42
    public $strict = false;
43
    /**
44
     * @var bool whether to invert the validation logic. Defaults to false. If set to true,
45
     * the attribute value should NOT be among the list of values defined via [[range]].
46
     */
47
    public $not = false;
48
    /**
49
     * @var bool whether to allow array type attribute.
50
     */
51
    public $allowArray = false;
52
53
54
    /**
55
     * {@inheritdoc}
56
     */
57 10
    public function init()
58
    {
59 10
        parent::init();
60
        if (
61 10
            !is_array($this->range)
62 10
            && !($this->range instanceof \Closure)
63 10
            && !($this->range instanceof \Traversable)
0 ignored issues
show
$this->range is always a sub-type of Traversable.
Loading history...
64
        ) {
65 1
            throw new InvalidConfigException('The "range" property must be set.');
66
        }
67 9
        if ($this->message === null) {
68 9
            $this->message = Yii::t('yii', '{attribute} is invalid.');
69
        }
70
    }
71
72
    /**
73
     * {@inheritdoc}
74
     */
75 8
    protected function validateValue($value)
76
    {
77 8
        $in = false;
78
79
        if (
80 8
            $this->allowArray
81 8
            && ($value instanceof \Traversable || is_array($value))
82 8
            && ArrayHelper::isSubset($value, $this->range, $this->strict)
83
        ) {
84 3
            $in = true;
85
        }
86
87 8
        if (!$in && ArrayHelper::isIn($value, $this->range, $this->strict)) {
88 5
            $in = true;
89
        }
90
91 8
        return $this->not !== $in ? null : [$this->message, []];
92
    }
93
94
    /**
95
     * {@inheritdoc}
96
     */
97 1
    public function validateAttribute($model, $attribute)
98
    {
99 1
        if ($this->range instanceof \Closure) {
100
            $this->range = call_user_func($this->range, $model, $attribute);
101
        }
102 1
        parent::validateAttribute($model, $attribute);
103
    }
104
105
    /**
106
     * {@inheritdoc}
107
     */
108
    public function clientValidateAttribute($model, $attribute, $view)
109
    {
110
        if ($this->range instanceof \Closure) {
111
            $this->range = call_user_func($this->range, $model, $attribute);
112
        }
113
114
        ValidationAsset::register($view);
115
        $options = $this->getClientOptions($model, $attribute);
116
117
        return 'yii.validation.range(value, messages, ' . Json::htmlEncode($options) . ');';
118
    }
119
120
    /**
121
     * {@inheritdoc}
122
     */
123
    public function getClientOptions($model, $attribute)
124
    {
125
        $range = [];
126
        foreach ($this->range as $value) {
127
            $range[] = (string) $value;
128
        }
129
        $options = [
130
            'range' => $range,
131
            'not' => $this->not,
132
            'message' => $this->formatMessage($this->message, [
133
                'attribute' => $model->getAttributeLabel($attribute),
134
            ]),
135
        ];
136
        if ($this->skipOnEmpty) {
137
            $options['skipOnEmpty'] = 1;
138
        }
139
        if ($this->allowArray) {
140
            $options['allowArray'] = 1;
141
        }
142
143
        return $options;
144
    }
145
}
146