init
This commit is contained in:
105
vendor/yiisoft/yii2/validators/BooleanValidator.php
vendored
Normal file
105
vendor/yiisoft/yii2/validators/BooleanValidator.php
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use Yii;
|
||||
|
||||
/**
|
||||
* BooleanValidator checks if the attribute value is a boolean value.
|
||||
*
|
||||
* Possible boolean values can be configured via the [[trueValue]] and [[falseValue]] properties.
|
||||
* And the comparison can be either [[strict]] or not.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class BooleanValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* @var mixed the value representing true status. Defaults to '1'.
|
||||
*/
|
||||
public $trueValue = '1';
|
||||
/**
|
||||
* @var mixed the value representing false status. Defaults to '0'.
|
||||
*/
|
||||
public $falseValue = '0';
|
||||
/**
|
||||
* @var bool whether the comparison to [[trueValue]] and [[falseValue]] is strict.
|
||||
* When this is true, the attribute value and type must both match those of [[trueValue]] or [[falseValue]].
|
||||
* Defaults to false, meaning only the value needs to be matched.
|
||||
*/
|
||||
public $strict = false;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if ($this->message === null) {
|
||||
$this->message = Yii::t('yii', '{attribute} must be either "{true}" or "{false}".');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function validateValue($value)
|
||||
{
|
||||
if ($this->strict) {
|
||||
$valid = $value === $this->trueValue || $value === $this->falseValue;
|
||||
} else {
|
||||
$valid = $value == $this->trueValue || $value == $this->falseValue;
|
||||
}
|
||||
|
||||
if (!$valid) {
|
||||
return [$this->message, [
|
||||
'true' => $this->trueValue === true ? 'true' : $this->trueValue,
|
||||
'false' => $this->falseValue === false ? 'false' : $this->falseValue,
|
||||
]];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clientValidateAttribute($model, $attribute, $view)
|
||||
{
|
||||
ValidationAsset::register($view);
|
||||
$options = $this->getClientOptions($model, $attribute);
|
||||
|
||||
return 'yii.validation.boolean(value, messages, ' . json_encode($options, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . ');';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClientOptions($model, $attribute)
|
||||
{
|
||||
$options = [
|
||||
'trueValue' => $this->trueValue,
|
||||
'falseValue' => $this->falseValue,
|
||||
'message' => $this->formatMessage($this->message, [
|
||||
'attribute' => $model->getAttributeLabel($attribute),
|
||||
'true' => $this->trueValue === true ? 'true' : $this->trueValue,
|
||||
'false' => $this->falseValue === false ? 'false' : $this->falseValue,
|
||||
]),
|
||||
];
|
||||
if ($this->skipOnEmpty) {
|
||||
$options['skipOnEmpty'] = 1;
|
||||
}
|
||||
if ($this->strict) {
|
||||
$options['strict'] = 1;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
267
vendor/yiisoft/yii2/validators/CompareValidator.php
vendored
Normal file
267
vendor/yiisoft/yii2/validators/CompareValidator.php
vendored
Normal file
@@ -0,0 +1,267 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\helpers\Html;
|
||||
|
||||
/**
|
||||
* CompareValidator compares the specified attribute value with another value.
|
||||
*
|
||||
* The value being compared with can be another attribute value
|
||||
* (specified via [[compareAttribute]]) or a constant (specified via
|
||||
* [[compareValue]]. When both are specified, the latter takes
|
||||
* precedence. If neither is specified, the attribute will be compared
|
||||
* with another attribute whose name is by appending "_repeat" to the source
|
||||
* attribute name.
|
||||
*
|
||||
* CompareValidator supports different comparison operators, specified
|
||||
* via the [[operator]] property.
|
||||
*
|
||||
* The default comparison function is based on string values, which means the values
|
||||
* are compared byte by byte. When comparing numbers, make sure to set the [[$type]]
|
||||
* to [[TYPE_NUMBER]] to enable numeric comparison.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class CompareValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* Constant for specifying the comparison [[type]] by numeric values.
|
||||
* @since 2.0.11
|
||||
* @see type
|
||||
*/
|
||||
const TYPE_STRING = 'string';
|
||||
/**
|
||||
* Constant for specifying the comparison [[type]] by numeric values.
|
||||
* @since 2.0.11
|
||||
* @see type
|
||||
*/
|
||||
const TYPE_NUMBER = 'number';
|
||||
|
||||
/**
|
||||
* @var string the name of the attribute to be compared with. When both this property
|
||||
* and [[compareValue]] are set, the latter takes precedence. If neither is set,
|
||||
* it assumes the comparison is against another attribute whose name is formed by
|
||||
* appending '_repeat' to the attribute being validated. For example, if 'password' is
|
||||
* being validated, then the attribute to be compared would be 'password_repeat'.
|
||||
* @see compareValue
|
||||
*/
|
||||
public $compareAttribute;
|
||||
/**
|
||||
* @var mixed the constant value to be compared with. When both this property
|
||||
* and [[compareAttribute]] are set, this property takes precedence.
|
||||
* @see compareAttribute
|
||||
*/
|
||||
public $compareValue;
|
||||
/**
|
||||
* @var string the type of the values being compared. The follow types are supported:
|
||||
*
|
||||
* - [[TYPE_STRING|string]]: the values are being compared as strings. No conversion will be done before comparison.
|
||||
* - [[TYPE_NUMBER|number]]: the values are being compared as numbers. String values will be converted into numbers before comparison.
|
||||
*/
|
||||
public $type = self::TYPE_STRING;
|
||||
/**
|
||||
* @var string the operator for comparison. The following operators are supported:
|
||||
*
|
||||
* - `==`: check if two values are equal. The comparison is done is non-strict mode.
|
||||
* - `===`: check if two values are equal. The comparison is done is strict mode.
|
||||
* - `!=`: check if two values are NOT equal. The comparison is done is non-strict mode.
|
||||
* - `!==`: check if two values are NOT equal. The comparison is done is strict mode.
|
||||
* - `>`: check if value being validated is greater than the value being compared with.
|
||||
* - `>=`: check if value being validated is greater than or equal to the value being compared with.
|
||||
* - `<`: check if value being validated is less than the value being compared with.
|
||||
* - `<=`: check if value being validated is less than or equal to the value being compared with.
|
||||
*
|
||||
* When you want to compare numbers, make sure to also set [[type]] to `number`.
|
||||
*/
|
||||
public $operator = '==';
|
||||
/**
|
||||
* @var string the user-defined error message. It may contain the following placeholders which
|
||||
* will be replaced accordingly by the validator:
|
||||
*
|
||||
* - `{attribute}`: the label of the attribute being validated
|
||||
* - `{value}`: the value of the attribute being validated
|
||||
* - `{compareValue}`: the value or the attribute label to be compared with
|
||||
* - `{compareAttribute}`: the label of the attribute to be compared with
|
||||
* - `{compareValueOrAttribute}`: the value or the attribute label to be compared with
|
||||
*/
|
||||
public $message;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if ($this->message === null) {
|
||||
switch ($this->operator) {
|
||||
case '==':
|
||||
$this->message = Yii::t('yii', '{attribute} must be equal to "{compareValueOrAttribute}".');
|
||||
break;
|
||||
case '===':
|
||||
$this->message = Yii::t('yii', '{attribute} must be equal to "{compareValueOrAttribute}".');
|
||||
break;
|
||||
case '!=':
|
||||
$this->message = Yii::t('yii', '{attribute} must not be equal to "{compareValueOrAttribute}".');
|
||||
break;
|
||||
case '!==':
|
||||
$this->message = Yii::t('yii', '{attribute} must not be equal to "{compareValueOrAttribute}".');
|
||||
break;
|
||||
case '>':
|
||||
$this->message = Yii::t('yii', '{attribute} must be greater than "{compareValueOrAttribute}".');
|
||||
break;
|
||||
case '>=':
|
||||
$this->message = Yii::t('yii', '{attribute} must be greater than or equal to "{compareValueOrAttribute}".');
|
||||
break;
|
||||
case '<':
|
||||
$this->message = Yii::t('yii', '{attribute} must be less than "{compareValueOrAttribute}".');
|
||||
break;
|
||||
case '<=':
|
||||
$this->message = Yii::t('yii', '{attribute} must be less than or equal to "{compareValueOrAttribute}".');
|
||||
break;
|
||||
default:
|
||||
throw new InvalidConfigException("Unknown operator: {$this->operator}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAttribute($model, $attribute)
|
||||
{
|
||||
$value = $model->$attribute;
|
||||
if (is_array($value)) {
|
||||
$this->addError($model, $attribute, Yii::t('yii', '{attribute} is invalid.'));
|
||||
|
||||
return;
|
||||
}
|
||||
if ($this->compareValue !== null) {
|
||||
$compareLabel = $compareValue = $compareValueOrAttribute = $this->compareValue;
|
||||
} else {
|
||||
$compareAttribute = $this->compareAttribute === null ? $attribute . '_repeat' : $this->compareAttribute;
|
||||
$compareValue = $model->$compareAttribute;
|
||||
$compareLabel = $compareValueOrAttribute = $model->getAttributeLabel($compareAttribute);
|
||||
}
|
||||
|
||||
if (!$this->compareValues($this->operator, $this->type, $value, $compareValue)) {
|
||||
$this->addError($model, $attribute, $this->message, [
|
||||
'compareAttribute' => $compareLabel,
|
||||
'compareValue' => $compareValue,
|
||||
'compareValueOrAttribute' => $compareValueOrAttribute,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function validateValue($value)
|
||||
{
|
||||
if ($this->compareValue === null) {
|
||||
throw new InvalidConfigException('CompareValidator::compareValue must be set.');
|
||||
}
|
||||
if (!$this->compareValues($this->operator, $this->type, $value, $this->compareValue)) {
|
||||
return [$this->message, [
|
||||
'compareAttribute' => $this->compareValue,
|
||||
'compareValue' => $this->compareValue,
|
||||
'compareValueOrAttribute' => $this->compareValue,
|
||||
]];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two values with the specified operator.
|
||||
* @param string $operator the comparison operator
|
||||
* @param string $type the type of the values being compared
|
||||
* @param mixed $value the value being compared
|
||||
* @param mixed $compareValue another value being compared
|
||||
* @return bool whether the comparison using the specified operator is true.
|
||||
*/
|
||||
protected function compareValues($operator, $type, $value, $compareValue)
|
||||
{
|
||||
if ($type === self::TYPE_NUMBER) {
|
||||
$value = (float) $value;
|
||||
$compareValue = (float) $compareValue;
|
||||
} else {
|
||||
$value = (string) $value;
|
||||
$compareValue = (string) $compareValue;
|
||||
}
|
||||
switch ($operator) {
|
||||
case '==':
|
||||
return $value == $compareValue;
|
||||
case '===':
|
||||
return $value === $compareValue;
|
||||
case '!=':
|
||||
return $value != $compareValue;
|
||||
case '!==':
|
||||
return $value !== $compareValue;
|
||||
case '>':
|
||||
return $value > $compareValue;
|
||||
case '>=':
|
||||
return $value >= $compareValue;
|
||||
case '<':
|
||||
return $value < $compareValue;
|
||||
case '<=':
|
||||
return $value <= $compareValue;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clientValidateAttribute($model, $attribute, $view)
|
||||
{
|
||||
ValidationAsset::register($view);
|
||||
$options = $this->getClientOptions($model, $attribute);
|
||||
|
||||
return 'yii.validation.compare(value, messages, ' . json_encode($options, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . ', $form);';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClientOptions($model, $attribute)
|
||||
{
|
||||
$options = [
|
||||
'operator' => $this->operator,
|
||||
'type' => $this->type,
|
||||
];
|
||||
|
||||
if ($this->compareValue !== null) {
|
||||
$options['compareValue'] = $this->compareValue;
|
||||
$compareLabel = $compareValue = $compareValueOrAttribute = $this->compareValue;
|
||||
} else {
|
||||
$compareAttribute = $this->compareAttribute === null ? $attribute . '_repeat' : $this->compareAttribute;
|
||||
$compareValue = $model->getAttributeLabel($compareAttribute);
|
||||
$options['compareAttribute'] = Html::getInputId($model, $compareAttribute);
|
||||
$compareLabel = $compareValueOrAttribute = $model->getAttributeLabel($compareAttribute);
|
||||
}
|
||||
|
||||
if ($this->skipOnEmpty) {
|
||||
$options['skipOnEmpty'] = 1;
|
||||
}
|
||||
|
||||
$options['message'] = $this->formatMessage($this->message, [
|
||||
'attribute' => $model->getAttributeLabel($attribute),
|
||||
'compareAttribute' => $compareLabel,
|
||||
'compareValue' => $compareValue,
|
||||
'compareValueOrAttribute' => $compareValueOrAttribute,
|
||||
]);
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
439
vendor/yiisoft/yii2/validators/DateValidator.php
vendored
Normal file
439
vendor/yiisoft/yii2/validators/DateValidator.php
vendored
Normal file
@@ -0,0 +1,439 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use DateTime;
|
||||
use IntlDateFormatter;
|
||||
use Yii;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\helpers\FormatConverter;
|
||||
|
||||
/**
|
||||
* DateValidator verifies if the attribute represents a date, time or datetime in a proper [[format]].
|
||||
*
|
||||
* It can also parse internationalized dates in a specific [[locale]] like e.g. `12 мая 2014` when [[format]]
|
||||
* is configured to use a time pattern in ICU format.
|
||||
*
|
||||
* It is further possible to limit the date within a certain range using [[min]] and [[max]].
|
||||
*
|
||||
* Additional to validating the date it can also export the parsed timestamp as a machine readable format
|
||||
* which can be configured using [[timestampAttribute]]. For values that include time information (not date-only values)
|
||||
* also the time zone will be adjusted. The time zone of the input value is assumed to be the one specified by the [[timeZone]]
|
||||
* property and the target timeZone will be UTC when [[timestampAttributeFormat]] is `null` (exporting as UNIX timestamp)
|
||||
* or [[timestampAttributeTimeZone]] otherwise. If you want to avoid the time zone conversion, make sure that [[timeZone]] and
|
||||
* [[timestampAttributeTimeZone]] are the same.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @author Carsten Brandt <mail@cebe.cc>
|
||||
* @since 2.0
|
||||
*/
|
||||
class DateValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* Constant for specifying the validation [[type]] as a date value, used for validation with intl short format.
|
||||
* @since 2.0.8
|
||||
* @see type
|
||||
*/
|
||||
const TYPE_DATE = 'date';
|
||||
/**
|
||||
* Constant for specifying the validation [[type]] as a datetime value, used for validation with intl short format.
|
||||
* @since 2.0.8
|
||||
* @see type
|
||||
*/
|
||||
const TYPE_DATETIME = 'datetime';
|
||||
/**
|
||||
* Constant for specifying the validation [[type]] as a time value, used for validation with intl short format.
|
||||
* @since 2.0.8
|
||||
* @see type
|
||||
*/
|
||||
const TYPE_TIME = 'time';
|
||||
|
||||
/**
|
||||
* @var string the type of the validator. Indicates, whether a date, time or datetime value should be validated.
|
||||
* This property influences the default value of [[format]] and also sets the correct behavior when [[format]] is one of the intl
|
||||
* short formats, `short`, `medium`, `long`, or `full`.
|
||||
*
|
||||
* This is only effective when the [PHP intl extension](http://php.net/manual/en/book.intl.php) is installed.
|
||||
*
|
||||
* This property can be set to the following values:
|
||||
*
|
||||
* - [[TYPE_DATE]] - (default) for validating date values only, that means only values that do not include a time range are valid.
|
||||
* - [[TYPE_DATETIME]] - for validating datetime values, that contain a date part as well as a time part.
|
||||
* - [[TYPE_TIME]] - for validating time values, that contain no date information.
|
||||
*
|
||||
* @since 2.0.8
|
||||
*/
|
||||
public $type = self::TYPE_DATE;
|
||||
/**
|
||||
* @var string the date format that the value being validated should follow.
|
||||
* This can be a date time pattern as described in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax).
|
||||
*
|
||||
* Alternatively this can be a string prefixed with `php:` representing a format that can be recognized by the PHP Datetime class.
|
||||
* Please refer to <http://php.net/manual/en/datetime.createfromformat.php> on supported formats.
|
||||
*
|
||||
* If this property is not set, the default value will be obtained from `Yii::$app->formatter->dateFormat`, see [[\yii\i18n\Formatter::dateFormat]] for details.
|
||||
* Since version 2.0.8 the default value will be determined from different formats of the formatter class,
|
||||
* dependent on the value of [[type]]:
|
||||
*
|
||||
* - if type is [[TYPE_DATE]], the default value will be taken from [[\yii\i18n\Formatter::dateFormat]],
|
||||
* - if type is [[TYPE_DATETIME]], it will be taken from [[\yii\i18n\Formatter::datetimeFormat]],
|
||||
* - and if type is [[TYPE_TIME]], it will be [[\yii\i18n\Formatter::timeFormat]].
|
||||
*
|
||||
* Here are some example values:
|
||||
*
|
||||
* ```php
|
||||
* 'MM/dd/yyyy' // date in ICU format
|
||||
* 'php:m/d/Y' // the same date in PHP format
|
||||
* 'MM/dd/yyyy HH:mm' // not only dates but also times can be validated
|
||||
* ```
|
||||
*
|
||||
* **Note:** the underlying date parsers being used vary dependent on the format. If you use the ICU format and
|
||||
* the [PHP intl extension](http://php.net/manual/en/book.intl.php) is installed, the [IntlDateFormatter](http://php.net/manual/en/intldateformatter.parse.php)
|
||||
* is used to parse the input value. In all other cases the PHP [DateTime](http://php.net/manual/en/datetime.createfromformat.php) class
|
||||
* is used. The IntlDateFormatter has the advantage that it can parse international dates like `12. Mai 2015` or `12 мая 2014`, while the
|
||||
* PHP parser is limited to English only. The PHP parser however is more strict about the input format as it will not accept
|
||||
* `12.05.05` for the format `php:d.m.Y`, but the IntlDateFormatter will accept it for the format `dd.MM.yyyy`.
|
||||
* If you need to use the IntlDateFormatter you can avoid this problem by specifying a [[min|minimum date]].
|
||||
*/
|
||||
public $format;
|
||||
/**
|
||||
* @var string the locale ID that is used to localize the date parsing.
|
||||
* This is only effective when the [PHP intl extension](http://php.net/manual/en/book.intl.php) is installed.
|
||||
* If not set, the locale of the [[\yii\base\Application::formatter|formatter]] will be used.
|
||||
* See also [[\yii\i18n\Formatter::locale]].
|
||||
*/
|
||||
public $locale;
|
||||
/**
|
||||
* @var string the timezone to use for parsing date and time values.
|
||||
* This can be any value that may be passed to [date_default_timezone_set()](http://www.php.net/manual/en/function.date-default-timezone-set.php)
|
||||
* e.g. `UTC`, `Europe/Berlin` or `America/Chicago`.
|
||||
* Refer to the [php manual](http://www.php.net/manual/en/timezones.php) for available timezones.
|
||||
* If this property is not set, [[\yii\base\Application::timeZone]] will be used.
|
||||
*/
|
||||
public $timeZone;
|
||||
/**
|
||||
* @var string the name of the attribute to receive the parsing result.
|
||||
* When this property is not null and the validation is successful, the named attribute will
|
||||
* receive the parsing result.
|
||||
*
|
||||
* This can be the same attribute as the one being validated. If this is the case,
|
||||
* the original value will be overwritten with the timestamp value after successful validation.
|
||||
*
|
||||
* Note, that when using this property, the input value will be converted to a unix timestamp,
|
||||
* which by definition is in UTC, so a conversion from the [[$timeZone|input time zone]] to UTC
|
||||
* will be performed. When defining [[$timestampAttributeFormat]] you can control the conversion by
|
||||
* setting [[$timestampAttributeTimeZone]] to a different value than `'UTC'`.
|
||||
*
|
||||
* @see timestampAttributeFormat
|
||||
* @see timestampAttributeTimeZone
|
||||
*/
|
||||
public $timestampAttribute;
|
||||
/**
|
||||
* @var string the format to use when populating the [[timestampAttribute]].
|
||||
* The format can be specified in the same way as for [[format]].
|
||||
*
|
||||
* If not set, [[timestampAttribute]] will receive a UNIX timestamp.
|
||||
* If [[timestampAttribute]] is not set, this property will be ignored.
|
||||
* @see format
|
||||
* @see timestampAttribute
|
||||
* @since 2.0.4
|
||||
*/
|
||||
public $timestampAttributeFormat;
|
||||
/**
|
||||
* @var string the timezone to use when populating the [[timestampAttribute]]. Defaults to `UTC`.
|
||||
*
|
||||
* This can be any value that may be passed to [date_default_timezone_set()](http://www.php.net/manual/en/function.date-default-timezone-set.php)
|
||||
* e.g. `UTC`, `Europe/Berlin` or `America/Chicago`.
|
||||
* Refer to the [php manual](http://www.php.net/manual/en/timezones.php) for available timezones.
|
||||
*
|
||||
* If [[timestampAttributeFormat]] is not set, this property will be ignored.
|
||||
* @see timestampAttributeFormat
|
||||
* @since 2.0.4
|
||||
*/
|
||||
public $timestampAttributeTimeZone = 'UTC';
|
||||
/**
|
||||
* @var int|string upper limit of the date. Defaults to null, meaning no upper limit.
|
||||
* This can be a unix timestamp or a string representing a date time value.
|
||||
* If this property is a string, [[format]] will be used to parse it.
|
||||
* @see tooBig for the customized message used when the date is too big.
|
||||
* @since 2.0.4
|
||||
*/
|
||||
public $max;
|
||||
/**
|
||||
* @var int|string lower limit of the date. Defaults to null, meaning no lower limit.
|
||||
* This can be a unix timestamp or a string representing a date time value.
|
||||
* If this property is a string, [[format]] will be used to parse it.
|
||||
* @see tooSmall for the customized message used when the date is too small.
|
||||
* @since 2.0.4
|
||||
*/
|
||||
public $min;
|
||||
/**
|
||||
* @var string user-defined error message used when the value is bigger than [[max]].
|
||||
* @since 2.0.4
|
||||
*/
|
||||
public $tooBig;
|
||||
/**
|
||||
* @var string user-defined error message used when the value is smaller than [[min]].
|
||||
* @since 2.0.4
|
||||
*/
|
||||
public $tooSmall;
|
||||
/**
|
||||
* @var string user friendly value of upper limit to display in the error message.
|
||||
* If this property is null, the value of [[max]] will be used (before parsing).
|
||||
* @since 2.0.4
|
||||
*/
|
||||
public $maxString;
|
||||
/**
|
||||
* @var string user friendly value of lower limit to display in the error message.
|
||||
* If this property is null, the value of [[min]] will be used (before parsing).
|
||||
* @since 2.0.4
|
||||
*/
|
||||
public $minString;
|
||||
|
||||
/**
|
||||
* @var array map of short format names to IntlDateFormatter constant values.
|
||||
*/
|
||||
private $_dateFormats = [
|
||||
'short' => 3, // IntlDateFormatter::SHORT,
|
||||
'medium' => 2, // IntlDateFormatter::MEDIUM,
|
||||
'long' => 1, // IntlDateFormatter::LONG,
|
||||
'full' => 0, // IntlDateFormatter::FULL,
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if ($this->message === null) {
|
||||
$this->message = Yii::t('yii', 'The format of {attribute} is invalid.');
|
||||
}
|
||||
if ($this->format === null) {
|
||||
if ($this->type === self::TYPE_DATE) {
|
||||
$this->format = Yii::$app->formatter->dateFormat;
|
||||
} elseif ($this->type === self::TYPE_DATETIME) {
|
||||
$this->format = Yii::$app->formatter->datetimeFormat;
|
||||
} elseif ($this->type === self::TYPE_TIME) {
|
||||
$this->format = Yii::$app->formatter->timeFormat;
|
||||
} else {
|
||||
throw new InvalidConfigException('Unknown validation type set for DateValidator::$type: ' . $this->type);
|
||||
}
|
||||
}
|
||||
if ($this->locale === null) {
|
||||
$this->locale = Yii::$app->language;
|
||||
}
|
||||
if ($this->timeZone === null) {
|
||||
$this->timeZone = Yii::$app->timeZone;
|
||||
}
|
||||
if ($this->min !== null && $this->tooSmall === null) {
|
||||
$this->tooSmall = Yii::t('yii', '{attribute} must be no less than {min}.');
|
||||
}
|
||||
if ($this->max !== null && $this->tooBig === null) {
|
||||
$this->tooBig = Yii::t('yii', '{attribute} must be no greater than {max}.');
|
||||
}
|
||||
if ($this->maxString === null) {
|
||||
$this->maxString = (string) $this->max;
|
||||
}
|
||||
if ($this->minString === null) {
|
||||
$this->minString = (string) $this->min;
|
||||
}
|
||||
if ($this->max !== null && is_string($this->max)) {
|
||||
$timestamp = $this->parseDateValue($this->max);
|
||||
if ($timestamp === false) {
|
||||
throw new InvalidConfigException("Invalid max date value: {$this->max}");
|
||||
}
|
||||
$this->max = $timestamp;
|
||||
}
|
||||
if ($this->min !== null && is_string($this->min)) {
|
||||
$timestamp = $this->parseDateValue($this->min);
|
||||
if ($timestamp === false) {
|
||||
throw new InvalidConfigException("Invalid min date value: {$this->min}");
|
||||
}
|
||||
$this->min = $timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAttribute($model, $attribute)
|
||||
{
|
||||
$value = $model->$attribute;
|
||||
if ($this->isEmpty($value)) {
|
||||
if ($this->timestampAttribute !== null) {
|
||||
$model->{$this->timestampAttribute} = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$timestamp = $this->parseDateValue($value);
|
||||
if ($timestamp === false) {
|
||||
if ($this->timestampAttribute === $attribute) {
|
||||
if ($this->timestampAttributeFormat === null) {
|
||||
if (is_int($value)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if ($this->parseDateValueFormat($value, $this->timestampAttributeFormat) !== false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->addError($model, $attribute, $this->message, []);
|
||||
} elseif ($this->min !== null && $timestamp < $this->min) {
|
||||
$this->addError($model, $attribute, $this->tooSmall, ['min' => $this->minString]);
|
||||
} elseif ($this->max !== null && $timestamp > $this->max) {
|
||||
$this->addError($model, $attribute, $this->tooBig, ['max' => $this->maxString]);
|
||||
} elseif ($this->timestampAttribute !== null) {
|
||||
if ($this->timestampAttributeFormat === null) {
|
||||
$model->{$this->timestampAttribute} = $timestamp;
|
||||
} else {
|
||||
$model->{$this->timestampAttribute} = $this->formatTimestamp($timestamp, $this->timestampAttributeFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function validateValue($value)
|
||||
{
|
||||
$timestamp = $this->parseDateValue($value);
|
||||
if ($timestamp === false) {
|
||||
return [$this->message, []];
|
||||
} elseif ($this->min !== null && $timestamp < $this->min) {
|
||||
return [$this->tooSmall, ['min' => $this->minString]];
|
||||
} elseif ($this->max !== null && $timestamp > $this->max) {
|
||||
return [$this->tooBig, ['max' => $this->maxString]];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses date string into UNIX timestamp.
|
||||
*
|
||||
* @param string $value string representing date
|
||||
* @return int|false a UNIX timestamp or `false` on failure.
|
||||
*/
|
||||
protected function parseDateValue($value)
|
||||
{
|
||||
// TODO consider merging these methods into single one at 2.1
|
||||
return $this->parseDateValueFormat($value, $this->format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses date string into UNIX timestamp.
|
||||
*
|
||||
* @param string $value string representing date
|
||||
* @param string $format expected date format
|
||||
* @return int|false a UNIX timestamp or `false` on failure.
|
||||
*/
|
||||
private function parseDateValueFormat($value, $format)
|
||||
{
|
||||
if (is_array($value)) {
|
||||
return false;
|
||||
}
|
||||
if (strncmp($format, 'php:', 4) === 0) {
|
||||
$format = substr($format, 4);
|
||||
} else {
|
||||
if (extension_loaded('intl')) {
|
||||
return $this->parseDateValueIntl($value, $format);
|
||||
}
|
||||
|
||||
// fallback to PHP if intl is not installed
|
||||
$format = FormatConverter::convertDateIcuToPhp($format, 'date');
|
||||
}
|
||||
|
||||
return $this->parseDateValuePHP($value, $format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a date value using the IntlDateFormatter::parse().
|
||||
* @param string $value string representing date
|
||||
* @param string $format the expected date format
|
||||
* @return int|bool a UNIX timestamp or `false` on failure.
|
||||
* @throws InvalidConfigException
|
||||
*/
|
||||
private function parseDateValueIntl($value, $format)
|
||||
{
|
||||
if (isset($this->_dateFormats[$format])) {
|
||||
if ($this->type === self::TYPE_DATE) {
|
||||
$formatter = new IntlDateFormatter($this->locale, $this->_dateFormats[$format], IntlDateFormatter::NONE, 'UTC');
|
||||
} elseif ($this->type === self::TYPE_DATETIME) {
|
||||
$formatter = new IntlDateFormatter($this->locale, $this->_dateFormats[$format], $this->_dateFormats[$format], $this->timeZone);
|
||||
} elseif ($this->type === self::TYPE_TIME) {
|
||||
$formatter = new IntlDateFormatter($this->locale, IntlDateFormatter::NONE, $this->_dateFormats[$format], $this->timeZone);
|
||||
} else {
|
||||
throw new InvalidConfigException('Unknown validation type set for DateValidator::$type: ' . $this->type);
|
||||
}
|
||||
} else {
|
||||
// if no time was provided in the format string set time to 0 to get a simple date timestamp
|
||||
$hasTimeInfo = (strpbrk($format, 'ahHkKmsSA') !== false);
|
||||
$formatter = new IntlDateFormatter($this->locale, IntlDateFormatter::NONE, IntlDateFormatter::NONE, $hasTimeInfo ? $this->timeZone : 'UTC', null, $format);
|
||||
}
|
||||
// enable strict parsing to avoid getting invalid date values
|
||||
$formatter->setLenient(false);
|
||||
|
||||
// There should not be a warning thrown by parse() but this seems to be the case on windows so we suppress it here
|
||||
// See https://github.com/yiisoft/yii2/issues/5962 and https://bugs.php.net/bug.php?id=68528
|
||||
$parsePos = 0;
|
||||
$parsedDate = @$formatter->parse($value, $parsePos);
|
||||
if ($parsedDate === false || $parsePos !== mb_strlen($value, Yii::$app ? Yii::$app->charset : 'UTF-8')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $parsedDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a date value using the DateTime::createFromFormat().
|
||||
* @param string $value string representing date
|
||||
* @param string $format the expected date format
|
||||
* @return int|bool a UNIX timestamp or `false` on failure.
|
||||
*/
|
||||
private function parseDateValuePHP($value, $format)
|
||||
{
|
||||
// if no time was provided in the format string set time to 0 to get a simple date timestamp
|
||||
$hasTimeInfo = (strpbrk($format, 'HhGgisU') !== false);
|
||||
|
||||
$date = DateTime::createFromFormat($format, $value, new \DateTimeZone($hasTimeInfo ? $this->timeZone : 'UTC'));
|
||||
$errors = DateTime::getLastErrors();
|
||||
if ($date === false || $errors['error_count'] || $errors['warning_count']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$hasTimeInfo) {
|
||||
$date->setTime(0, 0, 0);
|
||||
}
|
||||
|
||||
return $date->getTimestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a timestamp using the specified format.
|
||||
* @param int $timestamp
|
||||
* @param string $format
|
||||
* @return string
|
||||
*/
|
||||
private function formatTimestamp($timestamp, $format)
|
||||
{
|
||||
if (strncmp($format, 'php:', 4) === 0) {
|
||||
$format = substr($format, 4);
|
||||
} else {
|
||||
$format = FormatConverter::convertDateIcuToPhp($format, 'date');
|
||||
}
|
||||
|
||||
$date = new DateTime();
|
||||
$date->setTimestamp($timestamp);
|
||||
$date->setTimezone(new \DateTimeZone($this->timestampAttributeTimeZone));
|
||||
return $date->format($format);
|
||||
}
|
||||
}
|
||||
54
vendor/yiisoft/yii2/validators/DefaultValueValidator.php
vendored
Normal file
54
vendor/yiisoft/yii2/validators/DefaultValueValidator.php
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
/**
|
||||
* DefaultValueValidator sets the attribute to be the specified default value.
|
||||
*
|
||||
* DefaultValueValidator is not really a validator. It is provided mainly to allow
|
||||
* specifying attribute default values when they are empty.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class DefaultValueValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* @var mixed the default value or an anonymous function that returns the default value which will
|
||||
* be assigned to the attributes being validated if they are empty. The signature of the anonymous function
|
||||
* should be as follows,
|
||||
*
|
||||
* ```php
|
||||
* function($model, $attribute) {
|
||||
* // compute value
|
||||
* return $value;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
public $value;
|
||||
/**
|
||||
* @var bool this property is overwritten to be false so that this validator will
|
||||
* be applied when the value being validated is empty.
|
||||
*/
|
||||
public $skipOnEmpty = false;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAttribute($model, $attribute)
|
||||
{
|
||||
if ($this->isEmpty($model->$attribute)) {
|
||||
if ($this->value instanceof \Closure) {
|
||||
$model->$attribute = call_user_func($this->value, $model, $attribute);
|
||||
} else {
|
||||
$model->$attribute = $this->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
197
vendor/yiisoft/yii2/validators/EachValidator.php
vendored
Normal file
197
vendor/yiisoft/yii2/validators/EachValidator.php
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\base\Model;
|
||||
|
||||
/**
|
||||
* EachValidator validates an array by checking each of its elements against an embedded validation rule.
|
||||
*
|
||||
* ```php
|
||||
* class MyModel extends Model
|
||||
* {
|
||||
* public $categoryIDs = [];
|
||||
*
|
||||
* public function rules()
|
||||
* {
|
||||
* return [
|
||||
* // checks if every category ID is an integer
|
||||
* ['categoryIDs', 'each', 'rule' => ['integer']],
|
||||
* ]
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* > Note: This validator will not work with inline validation rules in case of usage outside the model scope,
|
||||
* e.g. via [[validate()]] method.
|
||||
*
|
||||
* > Note: EachValidator is meant to be used only in basic cases, you should consider usage of tabular input,
|
||||
* using several models for the more complex case.
|
||||
*
|
||||
* @author Paul Klimov <klimov.paul@gmail.com>
|
||||
* @since 2.0.4
|
||||
*/
|
||||
class EachValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* @var array|Validator definition of the validation rule, which should be used on array values.
|
||||
* It should be specified in the same format as at [[\yii\base\Model::rules()]], except it should not
|
||||
* contain attribute list as the first element.
|
||||
* For example:
|
||||
*
|
||||
* ```php
|
||||
* ['integer']
|
||||
* ['match', 'pattern' => '/[a-z]/is']
|
||||
* ```
|
||||
*
|
||||
* Please refer to [[\yii\base\Model::rules()]] for more details.
|
||||
*/
|
||||
public $rule;
|
||||
/**
|
||||
* @var bool whether to use error message composed by validator declared via [[rule]] if its validation fails.
|
||||
* If enabled, error message specified for this validator itself will appear only if attribute value is not an array.
|
||||
* If disabled, own error message value will be used always.
|
||||
*/
|
||||
public $allowMessageFromRule = true;
|
||||
/**
|
||||
* @var bool whether to stop validation once first error among attribute value elements is detected.
|
||||
* When enabled validation will produce single error message on attribute, when disabled - multiple
|
||||
* error messages mya appear: one per each invalid value.
|
||||
* Note that this option will affect only [[validateAttribute()]] value, while [[validateValue()]] will
|
||||
* not be affected.
|
||||
* @since 2.0.11
|
||||
*/
|
||||
public $stopOnFirstError = true;
|
||||
|
||||
/**
|
||||
* @var Validator validator instance.
|
||||
*/
|
||||
private $_validator;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if ($this->message === null) {
|
||||
$this->message = Yii::t('yii', '{attribute} is invalid.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the validator declared in [[rule]].
|
||||
* @param Model|null $model model in which context validator should be created.
|
||||
* @return Validator the declared validator.
|
||||
*/
|
||||
private function getValidator($model = null)
|
||||
{
|
||||
if ($this->_validator === null) {
|
||||
$this->_validator = $this->createEmbeddedValidator($model);
|
||||
}
|
||||
|
||||
return $this->_validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates validator object based on the validation rule specified in [[rule]].
|
||||
* @param Model|null $model model in which context validator should be created.
|
||||
* @throws \yii\base\InvalidConfigException
|
||||
* @return Validator validator instance
|
||||
*/
|
||||
private function createEmbeddedValidator($model)
|
||||
{
|
||||
$rule = $this->rule;
|
||||
if ($rule instanceof Validator) {
|
||||
return $rule;
|
||||
} elseif (is_array($rule) && isset($rule[0])) { // validator type
|
||||
if (!is_object($model)) {
|
||||
$model = new Model(); // mock up context model
|
||||
}
|
||||
|
||||
return Validator::createValidator($rule[0], $model, $this->attributes, array_slice($rule, 1));
|
||||
}
|
||||
|
||||
throw new InvalidConfigException('Invalid validation rule: a rule must be an array specifying validator type.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAttribute($model, $attribute)
|
||||
{
|
||||
$value = $model->$attribute;
|
||||
if (!is_array($value) && !$value instanceof \ArrayAccess) {
|
||||
$this->addError($model, $attribute, $this->message, []);
|
||||
return;
|
||||
}
|
||||
|
||||
$validator = $this->getValidator($model); // ensure model context while validator creation
|
||||
|
||||
$detectedErrors = $model->getErrors($attribute);
|
||||
$filteredValue = $model->$attribute;
|
||||
foreach ($value as $k => $v) {
|
||||
$model->clearErrors($attribute);
|
||||
$model->$attribute = $v;
|
||||
if (!$validator->skipOnEmpty || !$validator->isEmpty($v)) {
|
||||
$validator->validateAttribute($model, $attribute);
|
||||
}
|
||||
$filteredValue[$k] = $model->$attribute;
|
||||
if ($model->hasErrors($attribute)) {
|
||||
if ($this->allowMessageFromRule) {
|
||||
$validationErrors = $model->getErrors($attribute);
|
||||
$detectedErrors = array_merge($detectedErrors, $validationErrors);
|
||||
} else {
|
||||
$model->clearErrors($attribute);
|
||||
$this->addError($model, $attribute, $this->message, ['value' => $v]);
|
||||
$detectedErrors[] = $model->getFirstError($attribute);
|
||||
}
|
||||
$model->$attribute = $value;
|
||||
|
||||
if ($this->stopOnFirstError) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$model->$attribute = $filteredValue;
|
||||
$model->clearErrors($attribute);
|
||||
$model->addErrors([$attribute => $detectedErrors]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function validateValue($value)
|
||||
{
|
||||
if (!is_array($value) && !$value instanceof \ArrayAccess) {
|
||||
return [$this->message, []];
|
||||
}
|
||||
|
||||
$validator = $this->getValidator();
|
||||
foreach ($value as $v) {
|
||||
if ($validator->skipOnEmpty && $validator->isEmpty($v)) {
|
||||
continue;
|
||||
}
|
||||
$result = $validator->validateValue($v);
|
||||
if ($result !== null) {
|
||||
if ($this->allowMessageFromRule) {
|
||||
$result[1]['value'] = $v;
|
||||
return $result;
|
||||
}
|
||||
|
||||
return [$this->message, ['value' => $v]];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
152
vendor/yiisoft/yii2/validators/EmailValidator.php
vendored
Normal file
152
vendor/yiisoft/yii2/validators/EmailValidator.php
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\helpers\Json;
|
||||
use yii\web\JsExpression;
|
||||
|
||||
/**
|
||||
* EmailValidator validates that the attribute value is a valid email address.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class EmailValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* @var string the regular expression used to validate the attribute value.
|
||||
* @see http://www.regular-expressions.info/email.html
|
||||
*/
|
||||
public $pattern = '/^[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/';
|
||||
/**
|
||||
* @var string the regular expression used to validate email addresses with the name part.
|
||||
* This property is used only when [[allowName]] is true.
|
||||
* @see allowName
|
||||
*/
|
||||
public $fullPattern = '/^[^@]*<[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&\'*+\\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?>$/';
|
||||
/**
|
||||
* @var bool whether to allow name in the email address (e.g. "John Smith <john.smith@example.com>"). Defaults to false.
|
||||
* @see fullPattern
|
||||
*/
|
||||
public $allowName = false;
|
||||
/**
|
||||
* @var bool whether to check whether the email's domain exists and has either an A or MX record.
|
||||
* Be aware that this check can fail due to temporary DNS problems even if the email address is
|
||||
* valid and an email would be deliverable. Defaults to false.
|
||||
*/
|
||||
public $checkDNS = false;
|
||||
/**
|
||||
* @var bool whether validation process should take into account IDN (internationalized domain
|
||||
* names). Defaults to false meaning that validation of emails containing IDN will always fail.
|
||||
* Note that in order to use IDN validation you have to install and enable `intl` PHP extension,
|
||||
* otherwise an exception would be thrown.
|
||||
*/
|
||||
public $enableIDN = false;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if ($this->enableIDN && !function_exists('idn_to_ascii')) {
|
||||
throw new InvalidConfigException('In order to use IDN validation intl extension must be installed and enabled.');
|
||||
}
|
||||
if ($this->message === null) {
|
||||
$this->message = Yii::t('yii', '{attribute} is not a valid email address.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function validateValue($value)
|
||||
{
|
||||
if (!is_string($value)) {
|
||||
$valid = false;
|
||||
} elseif (!preg_match('/^(?P<name>(?:"?([^"]*)"?\s)?)(?:\s+)?(?:(?P<open><?)((?P<local>.+)@(?P<domain>[^>]+))(?P<close>>?))$/i', $value, $matches)) {
|
||||
$valid = false;
|
||||
} else {
|
||||
if ($this->enableIDN) {
|
||||
$matches['local'] = $this->idnToAscii($matches['local']);
|
||||
$matches['domain'] = $this->idnToAscii($matches['domain']);
|
||||
$value = $matches['name'] . $matches['open'] . $matches['local'] . '@' . $matches['domain'] . $matches['close'];
|
||||
}
|
||||
|
||||
if (strlen($matches['local']) > 64) {
|
||||
// The maximum total length of a user name or other local-part is 64 octets. RFC 5322 section 4.5.3.1.1
|
||||
// http://tools.ietf.org/html/rfc5321#section-4.5.3.1.1
|
||||
$valid = false;
|
||||
} elseif (strlen($matches['local'] . '@' . $matches['domain']) > 254) {
|
||||
// There is a restriction in RFC 2821 on the length of an address in MAIL and RCPT commands
|
||||
// of 254 characters. Since addresses that do not fit in those fields are not normally useful, the
|
||||
// upper limit on address lengths should normally be considered to be 254.
|
||||
//
|
||||
// Dominic Sayers, RFC 3696 erratum 1690
|
||||
// http://www.rfc-editor.org/errata_search.php?eid=1690
|
||||
$valid = false;
|
||||
} else {
|
||||
$valid = preg_match($this->pattern, $value) || $this->allowName && preg_match($this->fullPattern, $value);
|
||||
if ($valid && $this->checkDNS) {
|
||||
$valid = checkdnsrr($matches['domain'] . '.', 'MX') || checkdnsrr($matches['domain'] . '.', 'A');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $valid ? null : [$this->message, []];
|
||||
}
|
||||
|
||||
|
||||
private function idnToAscii($idn)
|
||||
{
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
// TODO: drop old PHP versions support
|
||||
return idn_to_ascii($idn);
|
||||
}
|
||||
|
||||
return idn_to_ascii($idn, 0, INTL_IDNA_VARIANT_UTS46);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clientValidateAttribute($model, $attribute, $view)
|
||||
{
|
||||
ValidationAsset::register($view);
|
||||
if ($this->enableIDN) {
|
||||
PunycodeAsset::register($view);
|
||||
}
|
||||
$options = $this->getClientOptions($model, $attribute);
|
||||
|
||||
return 'yii.validation.email(value, messages, ' . Json::htmlEncode($options) . ');';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClientOptions($model, $attribute)
|
||||
{
|
||||
$options = [
|
||||
'pattern' => new JsExpression($this->pattern),
|
||||
'fullPattern' => new JsExpression($this->fullPattern),
|
||||
'allowName' => $this->allowName,
|
||||
'message' => $this->formatMessage($this->message, [
|
||||
'attribute' => $model->getAttributeLabel($attribute),
|
||||
]),
|
||||
'enableIDN' => (bool) $this->enableIDN,
|
||||
];
|
||||
if ($this->skipOnEmpty) {
|
||||
$options['skipOnEmpty'] = 1;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
331
vendor/yiisoft/yii2/validators/ExistValidator.php
vendored
Normal file
331
vendor/yiisoft/yii2/validators/ExistValidator.php
vendored
Normal file
@@ -0,0 +1,331 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\base\Model;
|
||||
use yii\db\ActiveQuery;
|
||||
use yii\db\ActiveRecord;
|
||||
use yii\db\QueryInterface;
|
||||
|
||||
/**
|
||||
* ExistValidator validates that the attribute value exists in a table.
|
||||
*
|
||||
* ExistValidator checks if the value being validated can be found in the table column specified by
|
||||
* the ActiveRecord class [[targetClass]] and the attribute [[targetAttribute]].
|
||||
*
|
||||
* This validator is often used to verify that a foreign key contains a value
|
||||
* that can be found in the foreign table.
|
||||
*
|
||||
* The following are examples of validation rules using this validator:
|
||||
*
|
||||
* ```php
|
||||
* // a1 needs to exist
|
||||
* ['a1', 'exist']
|
||||
* // a1 needs to exist, but its value will use a2 to check for the existence
|
||||
* ['a1', 'exist', 'targetAttribute' => 'a2']
|
||||
* // a1 and a2 need to exist together, and they both will receive error message
|
||||
* [['a1', 'a2'], 'exist', 'targetAttribute' => ['a1', 'a2']]
|
||||
* // a1 and a2 need to exist together, only a1 will receive error message
|
||||
* ['a1', 'exist', 'targetAttribute' => ['a1', 'a2']]
|
||||
* // a1 needs to exist by checking the existence of both a2 and a3 (using a1 value)
|
||||
* ['a1', 'exist', 'targetAttribute' => ['a2', 'a1' => 'a3']]
|
||||
* ```
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class ExistValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* @var string the name of the ActiveRecord class that should be used to validate the existence
|
||||
* of the current attribute value. If not set, it will use the ActiveRecord class of the attribute being validated.
|
||||
* @see targetAttribute
|
||||
*/
|
||||
public $targetClass;
|
||||
/**
|
||||
* @var string|array the name of the ActiveRecord attribute that should be used to
|
||||
* validate the existence of the current attribute value. If not set, it will use the name
|
||||
* of the attribute currently being validated. You may use an array to validate the existence
|
||||
* of multiple columns at the same time. The array key is the name of the attribute with the value to validate,
|
||||
* the array value is the name of the database field to search.
|
||||
*/
|
||||
public $targetAttribute;
|
||||
/**
|
||||
* @var string the name of the relation that should be used to validate the existence of the current attribute value
|
||||
* This param overwrites $targetClass and $targetAttribute
|
||||
* @since 2.0.14
|
||||
*/
|
||||
public $targetRelation;
|
||||
/**
|
||||
* @var string|array|\Closure additional filter to be applied to the DB query used to check the existence of the attribute value.
|
||||
* This can be a string or an array representing the additional query condition (refer to [[\yii\db\Query::where()]]
|
||||
* on the format of query condition), or an anonymous function with the signature `function ($query)`, where `$query`
|
||||
* is the [[\yii\db\Query|Query]] object that you can modify in the function.
|
||||
*/
|
||||
public $filter;
|
||||
/**
|
||||
* @var bool whether to allow array type attribute.
|
||||
*/
|
||||
public $allowArray = false;
|
||||
/**
|
||||
* @var string and|or define how target attributes are related
|
||||
* @since 2.0.11
|
||||
*/
|
||||
public $targetAttributeJunction = 'and';
|
||||
/**
|
||||
* @var bool whether this validator is forced to always use master DB
|
||||
* @since 2.0.14
|
||||
*/
|
||||
public $forceMasterDb = true;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if ($this->message === null) {
|
||||
$this->message = Yii::t('yii', '{attribute} is invalid.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAttribute($model, $attribute)
|
||||
{
|
||||
if (!empty($this->targetRelation)) {
|
||||
$this->checkTargetRelationExistence($model, $attribute);
|
||||
} else {
|
||||
$this->checkTargetAttributeExistence($model, $attribute);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates existence of the current attribute based on relation name
|
||||
* @param \yii\db\ActiveRecord $model the data model to be validated
|
||||
* @param string $attribute the name of the attribute to be validated.
|
||||
*/
|
||||
private function checkTargetRelationExistence($model, $attribute)
|
||||
{
|
||||
$exists = false;
|
||||
/** @var ActiveQuery $relationQuery */
|
||||
$relationQuery = $model->{'get' . ucfirst($this->targetRelation)}();
|
||||
|
||||
if ($this->filter instanceof \Closure) {
|
||||
call_user_func($this->filter, $relationQuery);
|
||||
} elseif ($this->filter !== null) {
|
||||
$relationQuery->andWhere($this->filter);
|
||||
}
|
||||
|
||||
if ($this->forceMasterDb && method_exists($model::getDb(), 'useMaster')) {
|
||||
$model::getDb()->useMaster(function() use ($relationQuery, &$exists) {
|
||||
$exists = $relationQuery->exists();
|
||||
});
|
||||
} else {
|
||||
$exists = $relationQuery->exists();
|
||||
}
|
||||
|
||||
|
||||
if (!$exists) {
|
||||
$this->addError($model, $attribute, $this->message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates existence of the current attribute based on targetAttribute
|
||||
* @param \yii\base\Model $model the data model to be validated
|
||||
* @param string $attribute the name of the attribute to be validated.
|
||||
*/
|
||||
private function checkTargetAttributeExistence($model, $attribute)
|
||||
{
|
||||
$targetAttribute = $this->targetAttribute === null ? $attribute : $this->targetAttribute;
|
||||
$params = $this->prepareConditions($targetAttribute, $model, $attribute);
|
||||
$conditions = [$this->targetAttributeJunction == 'or' ? 'or' : 'and'];
|
||||
|
||||
if (!$this->allowArray) {
|
||||
foreach ($params as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$this->addError($model, $attribute, Yii::t('yii', '{attribute} is invalid.'));
|
||||
|
||||
return;
|
||||
}
|
||||
$conditions[] = [$key => $value];
|
||||
}
|
||||
} else {
|
||||
$conditions[] = $params;
|
||||
}
|
||||
|
||||
$targetClass = $this->targetClass === null ? get_class($model) : $this->targetClass;
|
||||
$query = $this->createQuery($targetClass, $conditions);
|
||||
|
||||
if (!$this->valueExists($targetClass, $query, $model->$attribute)) {
|
||||
$this->addError($model, $attribute, $this->message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes attributes' relations described in $targetAttribute parameter into conditions, compatible with
|
||||
* [[\yii\db\Query::where()|Query::where()]] key-value format.
|
||||
*
|
||||
* @param $targetAttribute array|string $attribute the name of the ActiveRecord attribute that should be used to
|
||||
* validate the existence of the current attribute value. If not set, it will use the name
|
||||
* of the attribute currently being validated. You may use an array to validate the existence
|
||||
* of multiple columns at the same time. The array key is the name of the attribute with the value to validate,
|
||||
* the array value is the name of the database field to search.
|
||||
* If the key and the value are the same, you can just specify the value.
|
||||
* @param \yii\base\Model $model the data model to be validated
|
||||
* @param string $attribute the name of the attribute to be validated in the $model
|
||||
* @return array conditions, compatible with [[\yii\db\Query::where()|Query::where()]] key-value format.
|
||||
* @throws InvalidConfigException
|
||||
*/
|
||||
private function prepareConditions($targetAttribute, $model, $attribute)
|
||||
{
|
||||
if (is_array($targetAttribute)) {
|
||||
if ($this->allowArray) {
|
||||
throw new InvalidConfigException('The "targetAttribute" property must be configured as a string.');
|
||||
}
|
||||
$conditions = [];
|
||||
foreach ($targetAttribute as $k => $v) {
|
||||
$conditions[$v] = is_int($k) ? $model->$v : $model->$k;
|
||||
}
|
||||
} else {
|
||||
$conditions = [$targetAttribute => $model->$attribute];
|
||||
}
|
||||
|
||||
$targetModelClass = $this->getTargetClass($model);
|
||||
if (!is_subclass_of($targetModelClass, 'yii\db\ActiveRecord')) {
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
/** @var ActiveRecord $targetModelClass */
|
||||
return $this->applyTableAlias($targetModelClass::find(), $conditions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Model $model the data model to be validated
|
||||
* @return string Target class name
|
||||
*/
|
||||
private function getTargetClass($model)
|
||||
{
|
||||
return $this->targetClass === null ? get_class($model) : $this->targetClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function validateValue($value)
|
||||
{
|
||||
if ($this->targetClass === null) {
|
||||
throw new InvalidConfigException('The "targetClass" property must be set.');
|
||||
}
|
||||
if (!is_string($this->targetAttribute)) {
|
||||
throw new InvalidConfigException('The "targetAttribute" property must be configured as a string.');
|
||||
}
|
||||
|
||||
if (is_array($value) && !$this->allowArray) {
|
||||
return [$this->message, []];
|
||||
}
|
||||
|
||||
$query = $this->createQuery($this->targetClass, [$this->targetAttribute => $value]);
|
||||
|
||||
return $this->valueExists($this->targetClass, $query, $value) ? null : [$this->message, []];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether value exists in target table
|
||||
*
|
||||
* @param string $targetClass
|
||||
* @param QueryInterface $query
|
||||
* @param mixed $value the value want to be checked
|
||||
* @return bool
|
||||
*/
|
||||
private function valueExists($targetClass, $query, $value)
|
||||
{
|
||||
$db = $targetClass::getDb();
|
||||
$exists = false;
|
||||
|
||||
if ($this->forceMasterDb && method_exists($db, 'useMaster')) {
|
||||
$db->useMaster(function ($db) use ($query, $value, &$exists) {
|
||||
$exists = $this->queryValueExists($query, $value);
|
||||
});
|
||||
} else {
|
||||
$exists = $this->queryValueExists($query, $value);
|
||||
}
|
||||
|
||||
return $exists;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run query to check if value exists
|
||||
*
|
||||
* @param QueryInterface $query
|
||||
* @param mixed $value the value to be checked
|
||||
* @return bool
|
||||
*/
|
||||
private function queryValueExists($query, $value)
|
||||
{
|
||||
if (is_array($value)) {
|
||||
return $query->count("DISTINCT [[$this->targetAttribute]]") == count($value) ;
|
||||
}
|
||||
return $query->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a query instance with the given condition.
|
||||
* @param string $targetClass the target AR class
|
||||
* @param mixed $condition query condition
|
||||
* @return \yii\db\ActiveQueryInterface the query instance
|
||||
*/
|
||||
protected function createQuery($targetClass, $condition)
|
||||
{
|
||||
/* @var $targetClass \yii\db\ActiveRecordInterface */
|
||||
$query = $targetClass::find()->andWhere($condition);
|
||||
if ($this->filter instanceof \Closure) {
|
||||
call_user_func($this->filter, $query);
|
||||
} elseif ($this->filter !== null) {
|
||||
$query->andWhere($this->filter);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns conditions with alias.
|
||||
* @param ActiveQuery $query
|
||||
* @param array $conditions array of condition, keys to be modified
|
||||
* @param null|string $alias set empty string for no apply alias. Set null for apply primary table alias
|
||||
* @return array
|
||||
*/
|
||||
private function applyTableAlias($query, $conditions, $alias = null)
|
||||
{
|
||||
if ($alias === null) {
|
||||
$alias = array_keys($query->getTablesUsedInFrom())[0];
|
||||
}
|
||||
$prefixedConditions = [];
|
||||
foreach ($conditions as $columnName => $columnValue) {
|
||||
if (strpos($columnName, '(') === false) {
|
||||
$prefixedColumn = "{$alias}.[[" . preg_replace(
|
||||
'/^' . preg_quote($alias) . '\.(.*)$/',
|
||||
'$1',
|
||||
$columnName) . ']]';
|
||||
} else {
|
||||
// there is an expression, can't prefix it reliably
|
||||
$prefixedColumn = $columnName;
|
||||
}
|
||||
|
||||
$prefixedConditions[$prefixedColumn] = $columnValue;
|
||||
}
|
||||
|
||||
return $prefixedConditions;
|
||||
}
|
||||
}
|
||||
540
vendor/yiisoft/yii2/validators/FileValidator.php
vendored
Normal file
540
vendor/yiisoft/yii2/validators/FileValidator.php
vendored
Normal file
@@ -0,0 +1,540 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use Yii;
|
||||
use yii\helpers\FileHelper;
|
||||
use yii\helpers\Html;
|
||||
use yii\helpers\Json;
|
||||
use yii\web\JsExpression;
|
||||
use yii\web\UploadedFile;
|
||||
|
||||
/**
|
||||
* FileValidator verifies if an attribute is receiving a valid uploaded file.
|
||||
*
|
||||
* Note that you should enable `fileinfo` PHP extension.
|
||||
*
|
||||
* @property int $sizeLimit The size limit for uploaded files. This property is read-only.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class FileValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* @var array|string a list of file name extensions that are allowed to be uploaded.
|
||||
* This can be either an array or a string consisting of file extension names
|
||||
* separated by space or comma (e.g. "gif, jpg").
|
||||
* Extension names are case-insensitive. Defaults to null, meaning all file name
|
||||
* extensions are allowed.
|
||||
* @see wrongExtension for the customized message for wrong file type.
|
||||
*/
|
||||
public $extensions;
|
||||
/**
|
||||
* @var bool whether to check file type (extension) with mime-type. If extension produced by
|
||||
* file mime-type check differs from uploaded file extension, the file will be considered as invalid.
|
||||
*/
|
||||
public $checkExtensionByMimeType = true;
|
||||
/**
|
||||
* @var array|string a list of file MIME types that are allowed to be uploaded.
|
||||
* This can be either an array or a string consisting of file MIME types
|
||||
* separated by space or comma (e.g. "text/plain, image/png").
|
||||
* The mask with the special character `*` can be used to match groups of mime types.
|
||||
* For example `image/*` will pass all mime types, that begin with `image/` (e.g. `image/jpeg`, `image/png`).
|
||||
* Mime type names are case-insensitive. Defaults to null, meaning all MIME types are allowed.
|
||||
* @see wrongMimeType for the customized message for wrong MIME type.
|
||||
*/
|
||||
public $mimeTypes;
|
||||
/**
|
||||
* @var int the minimum number of bytes required for the uploaded file.
|
||||
* Defaults to null, meaning no limit.
|
||||
* @see tooSmall for the customized message for a file that is too small.
|
||||
*/
|
||||
public $minSize;
|
||||
/**
|
||||
* @var int the maximum number of bytes required for the uploaded file.
|
||||
* Defaults to null, meaning no limit.
|
||||
* Note, the size limit is also affected by `upload_max_filesize` and `post_max_size` INI setting
|
||||
* and the 'MAX_FILE_SIZE' hidden field value. See [[getSizeLimit()]] for details.
|
||||
* @see http://php.net/manual/en/ini.core.php#ini.upload-max-filesize
|
||||
* @see http://php.net/post-max-size
|
||||
* @see getSizeLimit
|
||||
* @see tooBig for the customized message for a file that is too big.
|
||||
*/
|
||||
public $maxSize;
|
||||
/**
|
||||
* @var int the maximum file count the given attribute can hold.
|
||||
* Defaults to 1, meaning single file upload. By defining a higher number,
|
||||
* multiple uploads become possible. Setting it to `0` means there is no limit on
|
||||
* the number of files that can be uploaded simultaneously.
|
||||
*
|
||||
* > Note: The maximum number of files allowed to be uploaded simultaneously is
|
||||
* also limited with PHP directive `max_file_uploads`, which defaults to 20.
|
||||
*
|
||||
* @see http://php.net/manual/en/ini.core.php#ini.max-file-uploads
|
||||
* @see tooMany for the customized message when too many files are uploaded.
|
||||
*/
|
||||
public $maxFiles = 1;
|
||||
/**
|
||||
* @var int the minimum file count the given attribute can hold.
|
||||
* Defaults to 0. Higher value means at least that number of files should be uploaded.
|
||||
*
|
||||
* @see tooFew for the customized message when too few files are uploaded.
|
||||
* @since 2.0.14
|
||||
*/
|
||||
public $minFiles = 0;
|
||||
/**
|
||||
* @var string the error message used when a file is not uploaded correctly.
|
||||
*/
|
||||
public $message;
|
||||
/**
|
||||
* @var string the error message used when no file is uploaded.
|
||||
* Note that this is the text of the validation error message. To make uploading files required,
|
||||
* you have to set [[skipOnEmpty]] to `false`.
|
||||
*/
|
||||
public $uploadRequired;
|
||||
/**
|
||||
* @var string the error message used when the uploaded file is too large.
|
||||
* You may use the following tokens in the message:
|
||||
*
|
||||
* - {attribute}: the attribute name
|
||||
* - {file}: the uploaded file name
|
||||
* - {limit}: the maximum size allowed (see [[getSizeLimit()]])
|
||||
* - {formattedLimit}: the maximum size formatted
|
||||
* with [[\yii\i18n\Formatter::asShortSize()|Formatter::asShortSize()]]
|
||||
*/
|
||||
public $tooBig;
|
||||
/**
|
||||
* @var string the error message used when the uploaded file is too small.
|
||||
* You may use the following tokens in the message:
|
||||
*
|
||||
* - {attribute}: the attribute name
|
||||
* - {file}: the uploaded file name
|
||||
* - {limit}: the value of [[minSize]]
|
||||
* - {formattedLimit}: the value of [[minSize]] formatted
|
||||
* with [[\yii\i18n\Formatter::asShortSize()|Formatter::asShortSize()]
|
||||
*/
|
||||
public $tooSmall;
|
||||
/**
|
||||
* @var string the error message used if the count of multiple uploads exceeds limit.
|
||||
* You may use the following tokens in the message:
|
||||
*
|
||||
* - {attribute}: the attribute name
|
||||
* - {limit}: the value of [[maxFiles]]
|
||||
*/
|
||||
public $tooMany;
|
||||
/**
|
||||
* @var string the error message used if the count of multiple uploads less that minFiles.
|
||||
* You may use the following tokens in the message:
|
||||
*
|
||||
* - {attribute}: the attribute name
|
||||
* - {limit}: the value of [[minFiles]]
|
||||
*
|
||||
* @since 2.0.14
|
||||
*/
|
||||
public $tooFew;
|
||||
/**
|
||||
* @var string the error message used when the uploaded file has an extension name
|
||||
* that is not listed in [[extensions]]. You may use the following tokens in the message:
|
||||
*
|
||||
* - {attribute}: the attribute name
|
||||
* - {file}: the uploaded file name
|
||||
* - {extensions}: the list of the allowed extensions.
|
||||
*/
|
||||
public $wrongExtension;
|
||||
/**
|
||||
* @var string the error message used when the file has an mime type
|
||||
* that is not allowed by [[mimeTypes]] property.
|
||||
* You may use the following tokens in the message:
|
||||
*
|
||||
* - {attribute}: the attribute name
|
||||
* - {file}: the uploaded file name
|
||||
* - {mimeTypes}: the value of [[mimeTypes]]
|
||||
*/
|
||||
public $wrongMimeType;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if ($this->message === null) {
|
||||
$this->message = Yii::t('yii', 'File upload failed.');
|
||||
}
|
||||
if ($this->uploadRequired === null) {
|
||||
$this->uploadRequired = Yii::t('yii', 'Please upload a file.');
|
||||
}
|
||||
if ($this->tooMany === null) {
|
||||
$this->tooMany = Yii::t('yii', 'You can upload at most {limit, number} {limit, plural, one{file} other{files}}.');
|
||||
}
|
||||
if ($this->tooFew === null) {
|
||||
$this->tooFew = Yii::t('yii', 'You should upload at least {limit, number} {limit, plural, one{file} other{files}}.');
|
||||
}
|
||||
if ($this->wrongExtension === null) {
|
||||
$this->wrongExtension = Yii::t('yii', 'Only files with these extensions are allowed: {extensions}.');
|
||||
}
|
||||
if ($this->tooBig === null) {
|
||||
$this->tooBig = Yii::t('yii', 'The file "{file}" is too big. Its size cannot exceed {formattedLimit}.');
|
||||
}
|
||||
if ($this->tooSmall === null) {
|
||||
$this->tooSmall = Yii::t('yii', 'The file "{file}" is too small. Its size cannot be smaller than {formattedLimit}.');
|
||||
}
|
||||
if (!is_array($this->extensions)) {
|
||||
$this->extensions = preg_split('/[\s,]+/', strtolower($this->extensions), -1, PREG_SPLIT_NO_EMPTY);
|
||||
} else {
|
||||
$this->extensions = array_map('strtolower', $this->extensions);
|
||||
}
|
||||
if ($this->wrongMimeType === null) {
|
||||
$this->wrongMimeType = Yii::t('yii', 'Only files with these MIME types are allowed: {mimeTypes}.');
|
||||
}
|
||||
if (!is_array($this->mimeTypes)) {
|
||||
$this->mimeTypes = preg_split('/[\s,]+/', strtolower($this->mimeTypes), -1, PREG_SPLIT_NO_EMPTY);
|
||||
} else {
|
||||
$this->mimeTypes = array_map('strtolower', $this->mimeTypes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAttribute($model, $attribute)
|
||||
{
|
||||
if ($this->maxFiles != 1 || $this->minFiles > 1) {
|
||||
$rawFiles = $model->$attribute;
|
||||
if (!is_array($rawFiles)) {
|
||||
$this->addError($model, $attribute, $this->uploadRequired);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$files = $this->filterFiles($rawFiles);
|
||||
$model->$attribute = $files;
|
||||
|
||||
if (empty($files)) {
|
||||
$this->addError($model, $attribute, $this->uploadRequired);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$filesCount = count($files);
|
||||
if ($this->maxFiles && $filesCount > $this->maxFiles) {
|
||||
$this->addError($model, $attribute, $this->tooMany, ['limit' => $this->maxFiles]);
|
||||
}
|
||||
|
||||
if ($this->minFiles && $this->minFiles > $filesCount) {
|
||||
$this->addError($model, $attribute, $this->tooFew, ['limit' => $this->minFiles]);
|
||||
}
|
||||
|
||||
foreach ($files as $file) {
|
||||
$result = $this->validateValue($file);
|
||||
if (!empty($result)) {
|
||||
$this->addError($model, $attribute, $result[0], $result[1]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = $this->validateValue($model->$attribute);
|
||||
if (!empty($result)) {
|
||||
$this->addError($model, $attribute, $result[0], $result[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Files filter.
|
||||
* @param array $files
|
||||
* @return UploadedFile[]
|
||||
*/
|
||||
private function filterFiles(array $files)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach ($files as $fileName => $file) {
|
||||
if ($file instanceof UploadedFile && $file->error !== UPLOAD_ERR_NO_FILE) {
|
||||
$result[$fileName] = $file;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function validateValue($value)
|
||||
{
|
||||
if (!$value instanceof UploadedFile || $value->error == UPLOAD_ERR_NO_FILE) {
|
||||
return [$this->uploadRequired, []];
|
||||
}
|
||||
|
||||
switch ($value->error) {
|
||||
case UPLOAD_ERR_OK:
|
||||
if ($this->maxSize !== null && $value->size > $this->getSizeLimit()) {
|
||||
return [
|
||||
$this->tooBig,
|
||||
[
|
||||
'file' => $value->name,
|
||||
'limit' => $this->getSizeLimit(),
|
||||
'formattedLimit' => Yii::$app->formatter->asShortSize($this->getSizeLimit()),
|
||||
],
|
||||
];
|
||||
} elseif ($this->minSize !== null && $value->size < $this->minSize) {
|
||||
return [
|
||||
$this->tooSmall,
|
||||
[
|
||||
'file' => $value->name,
|
||||
'limit' => $this->minSize,
|
||||
'formattedLimit' => Yii::$app->formatter->asShortSize($this->minSize),
|
||||
],
|
||||
];
|
||||
} elseif (!empty($this->extensions) && !$this->validateExtension($value)) {
|
||||
return [$this->wrongExtension, ['file' => $value->name, 'extensions' => implode(', ', $this->extensions)]];
|
||||
} elseif (!empty($this->mimeTypes) && !$this->validateMimeType($value)) {
|
||||
return [$this->wrongMimeType, ['file' => $value->name, 'mimeTypes' => implode(', ', $this->mimeTypes)]];
|
||||
}
|
||||
|
||||
return null;
|
||||
case UPLOAD_ERR_INI_SIZE:
|
||||
case UPLOAD_ERR_FORM_SIZE:
|
||||
return [$this->tooBig, [
|
||||
'file' => $value->name,
|
||||
'limit' => $this->getSizeLimit(),
|
||||
'formattedLimit' => Yii::$app->formatter->asShortSize($this->getSizeLimit()),
|
||||
]];
|
||||
case UPLOAD_ERR_PARTIAL:
|
||||
Yii::warning('File was only partially uploaded: ' . $value->name, __METHOD__);
|
||||
break;
|
||||
case UPLOAD_ERR_NO_TMP_DIR:
|
||||
Yii::warning('Missing the temporary folder to store the uploaded file: ' . $value->name, __METHOD__);
|
||||
break;
|
||||
case UPLOAD_ERR_CANT_WRITE:
|
||||
Yii::warning('Failed to write the uploaded file to disk: ' . $value->name, __METHOD__);
|
||||
break;
|
||||
case UPLOAD_ERR_EXTENSION:
|
||||
Yii::warning('File upload was stopped by some PHP extension: ' . $value->name, __METHOD__);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return [$this->message, []];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum size allowed for uploaded files.
|
||||
*
|
||||
* This is determined based on four factors:
|
||||
*
|
||||
* - 'upload_max_filesize' in php.ini
|
||||
* - 'post_max_size' in php.ini
|
||||
* - 'MAX_FILE_SIZE' hidden field
|
||||
* - [[maxSize]]
|
||||
*
|
||||
* @return int the size limit for uploaded files.
|
||||
*/
|
||||
public function getSizeLimit()
|
||||
{
|
||||
// Get the lowest between post_max_size and upload_max_filesize, log a warning if the first is < than the latter
|
||||
$limit = $this->sizeToBytes(ini_get('upload_max_filesize'));
|
||||
$postLimit = $this->sizeToBytes(ini_get('post_max_size'));
|
||||
if ($postLimit > 0 && $postLimit < $limit) {
|
||||
Yii::warning('PHP.ini\'s \'post_max_size\' is less than \'upload_max_filesize\'.', __METHOD__);
|
||||
$limit = $postLimit;
|
||||
}
|
||||
if ($this->maxSize !== null && $limit > 0 && $this->maxSize < $limit) {
|
||||
$limit = $this->maxSize;
|
||||
}
|
||||
if (isset($_POST['MAX_FILE_SIZE']) && $_POST['MAX_FILE_SIZE'] > 0 && $_POST['MAX_FILE_SIZE'] < $limit) {
|
||||
$limit = (int) $_POST['MAX_FILE_SIZE'];
|
||||
}
|
||||
|
||||
return $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @param bool $trim
|
||||
*/
|
||||
public function isEmpty($value, $trim = false)
|
||||
{
|
||||
$value = is_array($value) ? reset($value) : $value;
|
||||
return !($value instanceof UploadedFile) || $value->error == UPLOAD_ERR_NO_FILE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts php.ini style size to bytes.
|
||||
*
|
||||
* @param string $sizeStr $sizeStr
|
||||
* @return int
|
||||
*/
|
||||
private function sizeToBytes($sizeStr)
|
||||
{
|
||||
switch (substr($sizeStr, -1)) {
|
||||
case 'M':
|
||||
case 'm':
|
||||
return (int) $sizeStr * 1048576;
|
||||
case 'K':
|
||||
case 'k':
|
||||
return (int) $sizeStr * 1024;
|
||||
case 'G':
|
||||
case 'g':
|
||||
return (int) $sizeStr * 1073741824;
|
||||
default:
|
||||
return (int) $sizeStr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if given uploaded file have correct type (extension) according current validator settings.
|
||||
* @param UploadedFile $file
|
||||
* @return bool
|
||||
*/
|
||||
protected function validateExtension($file)
|
||||
{
|
||||
$extension = mb_strtolower($file->extension, 'UTF-8');
|
||||
|
||||
if ($this->checkExtensionByMimeType) {
|
||||
$mimeType = FileHelper::getMimeType($file->tempName, null, false);
|
||||
if ($mimeType === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$extensionsByMimeType = FileHelper::getExtensionsByMimeType($mimeType);
|
||||
|
||||
if (!in_array($extension, $extensionsByMimeType, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!in_array($extension, $this->extensions, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clientValidateAttribute($model, $attribute, $view)
|
||||
{
|
||||
ValidationAsset::register($view);
|
||||
$options = $this->getClientOptions($model, $attribute);
|
||||
return 'yii.validation.file(attribute, messages, ' . Json::encode($options) . ');';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClientOptions($model, $attribute)
|
||||
{
|
||||
$label = $model->getAttributeLabel($attribute);
|
||||
|
||||
$options = [];
|
||||
if ($this->message !== null) {
|
||||
$options['message'] = $this->formatMessage($this->message, [
|
||||
'attribute' => $label,
|
||||
]);
|
||||
}
|
||||
|
||||
$options['skipOnEmpty'] = $this->skipOnEmpty;
|
||||
|
||||
if (!$this->skipOnEmpty) {
|
||||
$options['uploadRequired'] = $this->formatMessage($this->uploadRequired, [
|
||||
'attribute' => $label,
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->mimeTypes !== null) {
|
||||
$mimeTypes = [];
|
||||
foreach ($this->mimeTypes as $mimeType) {
|
||||
$mimeTypes[] = new JsExpression(Html::escapeJsRegularExpression($this->buildMimeTypeRegexp($mimeType)));
|
||||
}
|
||||
$options['mimeTypes'] = $mimeTypes;
|
||||
$options['wrongMimeType'] = $this->formatMessage($this->wrongMimeType, [
|
||||
'attribute' => $label,
|
||||
'mimeTypes' => implode(', ', $this->mimeTypes),
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->extensions !== null) {
|
||||
$options['extensions'] = $this->extensions;
|
||||
$options['wrongExtension'] = $this->formatMessage($this->wrongExtension, [
|
||||
'attribute' => $label,
|
||||
'extensions' => implode(', ', $this->extensions),
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->minSize !== null) {
|
||||
$options['minSize'] = $this->minSize;
|
||||
$options['tooSmall'] = $this->formatMessage($this->tooSmall, [
|
||||
'attribute' => $label,
|
||||
'limit' => $this->minSize,
|
||||
'formattedLimit' => Yii::$app->formatter->asShortSize($this->minSize),
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->maxSize !== null) {
|
||||
$options['maxSize'] = $this->maxSize;
|
||||
$options['tooBig'] = $this->formatMessage($this->tooBig, [
|
||||
'attribute' => $label,
|
||||
'limit' => $this->getSizeLimit(),
|
||||
'formattedLimit' => Yii::$app->formatter->asShortSize($this->getSizeLimit()),
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->maxFiles !== null) {
|
||||
$options['maxFiles'] = $this->maxFiles;
|
||||
$options['tooMany'] = $this->formatMessage($this->tooMany, [
|
||||
'attribute' => $label,
|
||||
'limit' => $this->maxFiles,
|
||||
]);
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the RegExp from the $mask.
|
||||
*
|
||||
* @param string $mask
|
||||
* @return string the regular expression
|
||||
* @see mimeTypes
|
||||
*/
|
||||
private function buildMimeTypeRegexp($mask)
|
||||
{
|
||||
return '/^' . str_replace('\*', '.*', preg_quote($mask, '/')) . '$/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the mimeType of the $file against the list in the [[mimeTypes]] property.
|
||||
*
|
||||
* @param UploadedFile $file
|
||||
* @return bool whether the $file mimeType is allowed
|
||||
* @throws \yii\base\InvalidConfigException
|
||||
* @see mimeTypes
|
||||
* @since 2.0.8
|
||||
*/
|
||||
protected function validateMimeType($file)
|
||||
{
|
||||
$fileMimeType = FileHelper::getMimeType($file->tempName);
|
||||
|
||||
foreach ($this->mimeTypes as $mimeType) {
|
||||
if ($mimeType === $fileMimeType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strpos($mimeType, '*') !== false && preg_match($this->buildMimeTypeRegexp($mimeType), $fileMimeType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
109
vendor/yiisoft/yii2/validators/FilterValidator.php
vendored
Normal file
109
vendor/yiisoft/yii2/validators/FilterValidator.php
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use yii\base\InvalidConfigException;
|
||||
|
||||
/**
|
||||
* FilterValidator converts the attribute value according to a filter.
|
||||
*
|
||||
* FilterValidator is actually not a validator but a data processor.
|
||||
* It invokes the specified filter callback to process the attribute value
|
||||
* and save the processed value back to the attribute. The filter must be
|
||||
* a valid PHP callback with the following signature:
|
||||
*
|
||||
* ```php
|
||||
* function foo($value) {
|
||||
* // compute $newValue here
|
||||
* return $newValue;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Many PHP functions qualify this signature (e.g. `trim()`).
|
||||
*
|
||||
* To specify the filter, set [[filter]] property to be the callback.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class FilterValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* @var callable the filter. This can be a global function name, anonymous function, etc.
|
||||
* The function signature must be as follows,
|
||||
*
|
||||
* ```php
|
||||
* function foo($value) {
|
||||
* // compute $newValue here
|
||||
* return $newValue;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
public $filter;
|
||||
/**
|
||||
* @var bool whether the filter should be skipped if an array input is given.
|
||||
* If true and an array input is given, the filter will not be applied.
|
||||
*/
|
||||
public $skipOnArray = false;
|
||||
/**
|
||||
* @var bool this property is overwritten to be false so that this validator will
|
||||
* be applied when the value being validated is empty.
|
||||
*/
|
||||
public $skipOnEmpty = false;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if ($this->filter === null) {
|
||||
throw new InvalidConfigException('The "filter" property must be set.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAttribute($model, $attribute)
|
||||
{
|
||||
$value = $model->$attribute;
|
||||
if (!$this->skipOnArray || !is_array($value)) {
|
||||
$model->$attribute = call_user_func($this->filter, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clientValidateAttribute($model, $attribute, $view)
|
||||
{
|
||||
if ($this->filter !== 'trim') {
|
||||
return null;
|
||||
}
|
||||
|
||||
ValidationAsset::register($view);
|
||||
$options = $this->getClientOptions($model, $attribute);
|
||||
|
||||
return 'value = yii.validation.trim($form, attribute, ' . json_encode($options, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . ');';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClientOptions($model, $attribute)
|
||||
{
|
||||
$options = [];
|
||||
if ($this->skipOnEmpty) {
|
||||
$options['skipOnEmpty'] = 1;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
221
vendor/yiisoft/yii2/validators/ImageValidator.php
vendored
Normal file
221
vendor/yiisoft/yii2/validators/ImageValidator.php
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use Yii;
|
||||
use yii\web\UploadedFile;
|
||||
|
||||
/**
|
||||
* ImageValidator verifies if an attribute is receiving a valid image.
|
||||
*
|
||||
* @author Taras Gudz <gudz.taras@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class ImageValidator extends FileValidator
|
||||
{
|
||||
/**
|
||||
* @var string the error message used when the uploaded file is not an image.
|
||||
* You may use the following tokens in the message:
|
||||
*
|
||||
* - {attribute}: the attribute name
|
||||
* - {file}: the uploaded file name
|
||||
*/
|
||||
public $notImage;
|
||||
/**
|
||||
* @var int the minimum width in pixels.
|
||||
* Defaults to null, meaning no limit.
|
||||
* @see underWidth for the customized message used when image width is too small.
|
||||
*/
|
||||
public $minWidth;
|
||||
/**
|
||||
* @var int the maximum width in pixels.
|
||||
* Defaults to null, meaning no limit.
|
||||
* @see overWidth for the customized message used when image width is too big.
|
||||
*/
|
||||
public $maxWidth;
|
||||
/**
|
||||
* @var int the minimum height in pixels.
|
||||
* Defaults to null, meaning no limit.
|
||||
* @see underHeight for the customized message used when image height is too small.
|
||||
*/
|
||||
public $minHeight;
|
||||
/**
|
||||
* @var int the maximum width in pixels.
|
||||
* Defaults to null, meaning no limit.
|
||||
* @see overWidth for the customized message used when image height is too big.
|
||||
*/
|
||||
public $maxHeight;
|
||||
/**
|
||||
* @var string the error message used when the image is under [[minWidth]].
|
||||
* You may use the following tokens in the message:
|
||||
*
|
||||
* - {attribute}: the attribute name
|
||||
* - {file}: the uploaded file name
|
||||
* - {limit}: the value of [[minWidth]]
|
||||
*/
|
||||
public $underWidth;
|
||||
/**
|
||||
* @var string the error message used when the image is over [[maxWidth]].
|
||||
* You may use the following tokens in the message:
|
||||
*
|
||||
* - {attribute}: the attribute name
|
||||
* - {file}: the uploaded file name
|
||||
* - {limit}: the value of [[maxWidth]]
|
||||
*/
|
||||
public $overWidth;
|
||||
/**
|
||||
* @var string the error message used when the image is under [[minHeight]].
|
||||
* You may use the following tokens in the message:
|
||||
*
|
||||
* - {attribute}: the attribute name
|
||||
* - {file}: the uploaded file name
|
||||
* - {limit}: the value of [[minHeight]]
|
||||
*/
|
||||
public $underHeight;
|
||||
/**
|
||||
* @var string the error message used when the image is over [[maxHeight]].
|
||||
* You may use the following tokens in the message:
|
||||
*
|
||||
* - {attribute}: the attribute name
|
||||
* - {file}: the uploaded file name
|
||||
* - {limit}: the value of [[maxHeight]]
|
||||
*/
|
||||
public $overHeight;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
|
||||
if ($this->notImage === null) {
|
||||
$this->notImage = Yii::t('yii', 'The file "{file}" is not an image.');
|
||||
}
|
||||
if ($this->underWidth === null) {
|
||||
$this->underWidth = Yii::t('yii', 'The image "{file}" is too small. The width cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.');
|
||||
}
|
||||
if ($this->underHeight === null) {
|
||||
$this->underHeight = Yii::t('yii', 'The image "{file}" is too small. The height cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.');
|
||||
}
|
||||
if ($this->overWidth === null) {
|
||||
$this->overWidth = Yii::t('yii', 'The image "{file}" is too large. The width cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.');
|
||||
}
|
||||
if ($this->overHeight === null) {
|
||||
$this->overHeight = Yii::t('yii', 'The image "{file}" is too large. The height cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function validateValue($value)
|
||||
{
|
||||
$result = parent::validateValue($value);
|
||||
|
||||
return empty($result) ? $this->validateImage($value) : $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates an image file.
|
||||
* @param UploadedFile $image uploaded file passed to check against a set of rules
|
||||
* @return array|null the error message and the parameters to be inserted into the error message.
|
||||
* Null should be returned if the data is valid.
|
||||
*/
|
||||
protected function validateImage($image)
|
||||
{
|
||||
if (false === ($imageInfo = getimagesize($image->tempName))) {
|
||||
return [$this->notImage, ['file' => $image->name]];
|
||||
}
|
||||
|
||||
list($width, $height) = $imageInfo;
|
||||
|
||||
if ($width == 0 || $height == 0) {
|
||||
return [$this->notImage, ['file' => $image->name]];
|
||||
}
|
||||
|
||||
if ($this->minWidth !== null && $width < $this->minWidth) {
|
||||
return [$this->underWidth, ['file' => $image->name, 'limit' => $this->minWidth]];
|
||||
}
|
||||
|
||||
if ($this->minHeight !== null && $height < $this->minHeight) {
|
||||
return [$this->underHeight, ['file' => $image->name, 'limit' => $this->minHeight]];
|
||||
}
|
||||
|
||||
if ($this->maxWidth !== null && $width > $this->maxWidth) {
|
||||
return [$this->overWidth, ['file' => $image->name, 'limit' => $this->maxWidth]];
|
||||
}
|
||||
|
||||
if ($this->maxHeight !== null && $height > $this->maxHeight) {
|
||||
return [$this->overHeight, ['file' => $image->name, 'limit' => $this->maxHeight]];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clientValidateAttribute($model, $attribute, $view)
|
||||
{
|
||||
ValidationAsset::register($view);
|
||||
$options = $this->getClientOptions($model, $attribute);
|
||||
return 'yii.validation.image(attribute, messages, ' . json_encode($options, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . ', deferred);';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClientOptions($model, $attribute)
|
||||
{
|
||||
$options = parent::getClientOptions($model, $attribute);
|
||||
|
||||
$label = $model->getAttributeLabel($attribute);
|
||||
|
||||
if ($this->notImage !== null) {
|
||||
$options['notImage'] = $this->formatMessage($this->notImage, [
|
||||
'attribute' => $label,
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->minWidth !== null) {
|
||||
$options['minWidth'] = $this->minWidth;
|
||||
$options['underWidth'] = $this->formatMessage($this->underWidth, [
|
||||
'attribute' => $label,
|
||||
'limit' => $this->minWidth,
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->maxWidth !== null) {
|
||||
$options['maxWidth'] = $this->maxWidth;
|
||||
$options['overWidth'] = $this->formatMessage($this->overWidth, [
|
||||
'attribute' => $label,
|
||||
'limit' => $this->maxWidth,
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->minHeight !== null) {
|
||||
$options['minHeight'] = $this->minHeight;
|
||||
$options['underHeight'] = $this->formatMessage($this->underHeight, [
|
||||
'attribute' => $label,
|
||||
'limit' => $this->minHeight,
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->maxHeight !== null) {
|
||||
$options['maxHeight'] = $this->maxHeight;
|
||||
$options['overHeight'] = $this->formatMessage($this->overHeight, [
|
||||
'attribute' => $label,
|
||||
'limit' => $this->maxHeight,
|
||||
]);
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
91
vendor/yiisoft/yii2/validators/InlineValidator.php
vendored
Normal file
91
vendor/yiisoft/yii2/validators/InlineValidator.php
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
/**
|
||||
* InlineValidator represents a validator which is defined as a method in the object being validated.
|
||||
*
|
||||
* The validation method must have the following signature:
|
||||
*
|
||||
* ```php
|
||||
* function foo($attribute, $params, $validator)
|
||||
* ```
|
||||
*
|
||||
* where `$attribute` refers to the name of the attribute being validated, while `$params` is an array representing the
|
||||
* additional parameters supplied in the validation rule. Parameter `$validator` refers to the related
|
||||
* [[InlineValidator]] object and is available since version 2.0.11.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class InlineValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* @var string|\Closure an anonymous function or the name of a model class method that will be
|
||||
* called to perform the actual validation. The signature of the method should be like the following:
|
||||
*
|
||||
* ```php
|
||||
* function foo($attribute, $params, $validator)
|
||||
* ```
|
||||
*
|
||||
* - `$attribute` is the name of the attribute to be validated;
|
||||
* - `$params` contains the value of [[params]] that you specify when declaring the inline validation rule;
|
||||
* - `$validator` is a reference to related [[InlineValidator]] object. This parameter is available since version 2.0.11.
|
||||
*/
|
||||
public $method;
|
||||
/**
|
||||
* @var mixed additional parameters that are passed to the validation method
|
||||
*/
|
||||
public $params;
|
||||
/**
|
||||
* @var string|\Closure an anonymous function or the name of a model class method that returns the client validation code.
|
||||
* The signature of the method should be like the following:
|
||||
*
|
||||
* ```php
|
||||
* function foo($attribute, $params, $validator)
|
||||
* {
|
||||
* return "javascript";
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* where `$attribute` refers to the attribute name to be validated.
|
||||
*
|
||||
* Please refer to [[clientValidateAttribute()]] for details on how to return client validation code.
|
||||
*/
|
||||
public $clientValidate;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAttribute($model, $attribute)
|
||||
{
|
||||
$method = $this->method;
|
||||
if (is_string($method)) {
|
||||
$method = [$model, $method];
|
||||
}
|
||||
call_user_func($method, $attribute, $this->params, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clientValidateAttribute($model, $attribute, $view)
|
||||
{
|
||||
if ($this->clientValidate !== null) {
|
||||
$method = $this->clientValidate;
|
||||
if (is_string($method)) {
|
||||
$method = [$model, $method];
|
||||
}
|
||||
|
||||
return call_user_func($method, $attribute, $this->params, $this);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
580
vendor/yiisoft/yii2/validators/IpValidator.php
vendored
Normal file
580
vendor/yiisoft/yii2/validators/IpValidator.php
vendored
Normal file
@@ -0,0 +1,580 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\helpers\Html;
|
||||
use yii\helpers\IpHelper;
|
||||
use yii\helpers\Json;
|
||||
use yii\web\JsExpression;
|
||||
|
||||
/**
|
||||
* The validator checks if the attribute value is a valid IPv4/IPv6 address or subnet.
|
||||
*
|
||||
* It also may change attribute's value if normalization of IPv6 expansion is enabled.
|
||||
*
|
||||
* The following are examples of validation rules using this validator:
|
||||
*
|
||||
* ```php
|
||||
* ['ip_address', 'ip'], // IPv4 or IPv6 address
|
||||
* ['ip_address', 'ip', 'ipv6' => false], // IPv4 address (IPv6 is disabled)
|
||||
* ['ip_address', 'ip', 'subnet' => true], // requires a CIDR prefix (like 10.0.0.1/24) for the IP address
|
||||
* ['ip_address', 'ip', 'subnet' => null], // CIDR prefix is optional
|
||||
* ['ip_address', 'ip', 'subnet' => null, 'normalize' => true], // CIDR prefix is optional and will be added when missing
|
||||
* ['ip_address', 'ip', 'ranges' => ['192.168.0.0/24']], // only IP addresses from the specified subnet are allowed
|
||||
* ['ip_address', 'ip', 'ranges' => ['!192.168.0.0/24', 'any']], // any IP is allowed except IP in the specified subnet
|
||||
* ['ip_address', 'ip', 'expandIPv6' => true], // expands IPv6 address to a full notation format
|
||||
* ```
|
||||
*
|
||||
* @property array $ranges The IPv4 or IPv6 ranges that are allowed or forbidden. See [[setRanges()]] for
|
||||
* detailed description.
|
||||
*
|
||||
* @author Dmitry Naumenko <d.naumenko.a@gmail.com>
|
||||
* @since 2.0.7
|
||||
*/
|
||||
class IpValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* Negation char.
|
||||
*
|
||||
* Used to negate [[ranges]] or [[networks]] or to negate validating value when [[negation]] is set to `true`.
|
||||
* @see negation
|
||||
* @see networks
|
||||
* @see ranges
|
||||
*/
|
||||
const NEGATION_CHAR = '!';
|
||||
|
||||
/**
|
||||
* @var array The network aliases, that can be used in [[ranges]].
|
||||
* - key - alias name
|
||||
* - value - array of strings. String can be an IP range, IP address or another alias. String can be
|
||||
* negated with [[NEGATION_CHAR]] (independent of `negation` option).
|
||||
*
|
||||
* The following aliases are defined by default:
|
||||
* - `*`: `any`
|
||||
* - `any`: `0.0.0.0/0, ::/0`
|
||||
* - `private`: `10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fd00::/8`
|
||||
* - `multicast`: `224.0.0.0/4, ff00::/8`
|
||||
* - `linklocal`: `169.254.0.0/16, fe80::/10`
|
||||
* - `localhost`: `127.0.0.0/8', ::1`
|
||||
* - `documentation`: `192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24, 2001:db8::/32`
|
||||
* - `system`: `multicast, linklocal, localhost, documentation`
|
||||
*/
|
||||
public $networks = [
|
||||
'*' => ['any'],
|
||||
'any' => ['0.0.0.0/0', '::/0'],
|
||||
'private' => ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', 'fd00::/8'],
|
||||
'multicast' => ['224.0.0.0/4', 'ff00::/8'],
|
||||
'linklocal' => ['169.254.0.0/16', 'fe80::/10'],
|
||||
'localhost' => ['127.0.0.0/8', '::1'],
|
||||
'documentation' => ['192.0.2.0/24', '198.51.100.0/24', '203.0.113.0/24', '2001:db8::/32'],
|
||||
'system' => ['multicast', 'linklocal', 'localhost', 'documentation'],
|
||||
];
|
||||
/**
|
||||
* @var bool whether the validating value can be an IPv6 address. Defaults to `true`.
|
||||
*/
|
||||
public $ipv6 = true;
|
||||
/**
|
||||
* @var bool whether the validating value can be an IPv4 address. Defaults to `true`.
|
||||
*/
|
||||
public $ipv4 = true;
|
||||
/**
|
||||
* @var bool whether the address can be an IP with CIDR subnet, like `192.168.10.0/24`.
|
||||
* The following values are possible:
|
||||
*
|
||||
* - `false` - the address must not have a subnet (default).
|
||||
* - `true` - specifying a subnet is required.
|
||||
* - `null` - specifying a subnet is optional.
|
||||
*/
|
||||
public $subnet = false;
|
||||
/**
|
||||
* @var bool whether to add the CIDR prefix with the smallest length (32 for IPv4 and 128 for IPv6) to an
|
||||
* address without it. Works only when `subnet` is not `false`. For example:
|
||||
* - `10.0.1.5` will normalized to `10.0.1.5/32`
|
||||
* - `2008:db0::1` will be normalized to `2008:db0::1/128`
|
||||
* Defaults to `false`.
|
||||
* @see subnet
|
||||
*/
|
||||
public $normalize = false;
|
||||
/**
|
||||
* @var bool whether address may have a [[NEGATION_CHAR]] character at the beginning.
|
||||
* Defaults to `false`.
|
||||
*/
|
||||
public $negation = false;
|
||||
/**
|
||||
* @var bool whether to expand an IPv6 address to the full notation format.
|
||||
* Defaults to `false`.
|
||||
*/
|
||||
public $expandIPv6 = false;
|
||||
/**
|
||||
* @var string Regexp-pattern to validate IPv4 address
|
||||
*/
|
||||
public $ipv4Pattern = '/^(?:(?:2(?:[0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9])\.){3}(?:(?:2([0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9]))$/';
|
||||
/**
|
||||
* @var string Regexp-pattern to validate IPv6 address
|
||||
*/
|
||||
public $ipv6Pattern = '/^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/';
|
||||
/**
|
||||
* @var string user-defined error message is used when validation fails due to the wrong IP address format.
|
||||
*
|
||||
* You may use the following placeholders in the message:
|
||||
*
|
||||
* - `{attribute}`: the label of the attribute being validated
|
||||
* - `{value}`: the value of the attribute being validated
|
||||
*/
|
||||
public $message;
|
||||
/**
|
||||
* @var string user-defined error message is used when validation fails due to the disabled IPv6 validation.
|
||||
*
|
||||
* You may use the following placeholders in the message:
|
||||
*
|
||||
* - `{attribute}`: the label of the attribute being validated
|
||||
* - `{value}`: the value of the attribute being validated
|
||||
*
|
||||
* @see ipv6
|
||||
*/
|
||||
public $ipv6NotAllowed;
|
||||
/**
|
||||
* @var string user-defined error message is used when validation fails due to the disabled IPv4 validation.
|
||||
*
|
||||
* You may use the following placeholders in the message:
|
||||
*
|
||||
* - `{attribute}`: the label of the attribute being validated
|
||||
* - `{value}`: the value of the attribute being validated
|
||||
*
|
||||
* @see ipv4
|
||||
*/
|
||||
public $ipv4NotAllowed;
|
||||
/**
|
||||
* @var string user-defined error message is used when validation fails due to the wrong CIDR.
|
||||
*
|
||||
* You may use the following placeholders in the message:
|
||||
*
|
||||
* - `{attribute}`: the label of the attribute being validated
|
||||
* - `{value}`: the value of the attribute being validated
|
||||
* @see subnet
|
||||
*/
|
||||
public $wrongCidr;
|
||||
/**
|
||||
* @var string user-defined error message is used when validation fails due to subnet [[subnet]] set to 'only',
|
||||
* but the CIDR prefix is not set.
|
||||
*
|
||||
* You may use the following placeholders in the message:
|
||||
*
|
||||
* - `{attribute}`: the label of the attribute being validated
|
||||
* - `{value}`: the value of the attribute being validated
|
||||
*
|
||||
* @see subnet
|
||||
*/
|
||||
public $noSubnet;
|
||||
/**
|
||||
* @var string user-defined error message is used when validation fails
|
||||
* due to [[subnet]] is false, but CIDR prefix is present.
|
||||
*
|
||||
* You may use the following placeholders in the message:
|
||||
*
|
||||
* - `{attribute}`: the label of the attribute being validated
|
||||
* - `{value}`: the value of the attribute being validated
|
||||
*
|
||||
* @see subnet
|
||||
*/
|
||||
public $hasSubnet;
|
||||
/**
|
||||
* @var string user-defined error message is used when validation fails due to IP address
|
||||
* is not not allowed by [[ranges]] check.
|
||||
*
|
||||
* You may use the following placeholders in the message:
|
||||
*
|
||||
* - `{attribute}`: the label of the attribute being validated
|
||||
* - `{value}`: the value of the attribute being validated
|
||||
*
|
||||
* @see ranges
|
||||
*/
|
||||
public $notInRange;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $_ranges = [];
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
|
||||
if (!$this->ipv4 && !$this->ipv6) {
|
||||
throw new InvalidConfigException('Both IPv4 and IPv6 checks can not be disabled at the same time');
|
||||
}
|
||||
if ($this->message === null) {
|
||||
$this->message = Yii::t('yii', '{attribute} must be a valid IP address.');
|
||||
}
|
||||
if ($this->ipv6NotAllowed === null) {
|
||||
$this->ipv6NotAllowed = Yii::t('yii', '{attribute} must not be an IPv6 address.');
|
||||
}
|
||||
if ($this->ipv4NotAllowed === null) {
|
||||
$this->ipv4NotAllowed = Yii::t('yii', '{attribute} must not be an IPv4 address.');
|
||||
}
|
||||
if ($this->wrongCidr === null) {
|
||||
$this->wrongCidr = Yii::t('yii', '{attribute} contains wrong subnet mask.');
|
||||
}
|
||||
if ($this->noSubnet === null) {
|
||||
$this->noSubnet = Yii::t('yii', '{attribute} must be an IP address with specified subnet.');
|
||||
}
|
||||
if ($this->hasSubnet === null) {
|
||||
$this->hasSubnet = Yii::t('yii', '{attribute} must not be a subnet.');
|
||||
}
|
||||
if ($this->notInRange === null) {
|
||||
$this->notInRange = Yii::t('yii', '{attribute} is not in the allowed range.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the IPv4 or IPv6 ranges that are allowed or forbidden.
|
||||
*
|
||||
* The following preparation tasks are performed:
|
||||
*
|
||||
* - Recursively substitutes aliases (described in [[networks]]) with their values.
|
||||
* - Removes duplicates
|
||||
*
|
||||
* @property array the IPv4 or IPv6 ranges that are allowed or forbidden.
|
||||
* See [[setRanges()]] for detailed description.
|
||||
* @param array $ranges the IPv4 or IPv6 ranges that are allowed or forbidden.
|
||||
*
|
||||
* When the array is empty, or the option not set, all IP addresses are allowed.
|
||||
*
|
||||
* Otherwise, the rules are checked sequentially until the first match is found.
|
||||
* An IP address is forbidden, when it has not matched any of the rules.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```php
|
||||
* [
|
||||
* 'ranges' => [
|
||||
* '192.168.10.128'
|
||||
* '!192.168.10.0/24',
|
||||
* 'any' // allows any other IP addresses
|
||||
* ]
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* In this example, access is allowed for all the IPv4 and IPv6 addresses excluding the `192.168.10.0/24` subnet.
|
||||
* IPv4 address `192.168.10.128` is also allowed, because it is listed before the restriction.
|
||||
*/
|
||||
public function setRanges($ranges)
|
||||
{
|
||||
$this->_ranges = $this->prepareRanges((array) $ranges);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array The IPv4 or IPv6 ranges that are allowed or forbidden.
|
||||
*/
|
||||
public function getRanges()
|
||||
{
|
||||
return $this->_ranges;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function validateValue($value)
|
||||
{
|
||||
$result = $this->validateSubnet($value);
|
||||
if (is_array($result)) {
|
||||
$result[1] = array_merge(['ip' => is_array($value) ? 'array()' : $value], $result[1]);
|
||||
return $result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAttribute($model, $attribute)
|
||||
{
|
||||
$value = $model->$attribute;
|
||||
|
||||
$result = $this->validateSubnet($value);
|
||||
if (is_array($result)) {
|
||||
$result[1] = array_merge(['ip' => is_array($value) ? 'array()' : $value], $result[1]);
|
||||
$this->addError($model, $attribute, $result[0], $result[1]);
|
||||
} else {
|
||||
$model->$attribute = $result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates an IPv4/IPv6 address or subnet.
|
||||
*
|
||||
* @param $ip string
|
||||
* @return string|array
|
||||
* string - the validation was successful;
|
||||
* array - an error occurred during the validation.
|
||||
* Array[0] contains the text of an error, array[1] contains values for the placeholders in the error message
|
||||
*/
|
||||
private function validateSubnet($ip)
|
||||
{
|
||||
if (!is_string($ip)) {
|
||||
return [$this->message, []];
|
||||
}
|
||||
|
||||
$negation = null;
|
||||
$cidr = null;
|
||||
$isCidrDefault = false;
|
||||
|
||||
if (preg_match($this->getIpParsePattern(), $ip, $matches)) {
|
||||
$negation = ($matches[1] !== '') ? $matches[1] : null;
|
||||
$ip = $matches[2];
|
||||
$cidr = isset($matches[4]) ? $matches[4] : null;
|
||||
}
|
||||
|
||||
if ($this->subnet === true && $cidr === null) {
|
||||
return [$this->noSubnet, []];
|
||||
}
|
||||
if ($this->subnet === false && $cidr !== null) {
|
||||
return [$this->hasSubnet, []];
|
||||
}
|
||||
if ($this->negation === false && $negation !== null) {
|
||||
return [$this->message, []];
|
||||
}
|
||||
|
||||
if ($this->getIpVersion($ip) === IpHelper::IPV6) {
|
||||
if ($cidr !== null) {
|
||||
if ($cidr > IpHelper::IPV6_ADDRESS_LENGTH || $cidr < 0) {
|
||||
return [$this->wrongCidr, []];
|
||||
}
|
||||
} else {
|
||||
$isCidrDefault = true;
|
||||
$cidr = IpHelper::IPV6_ADDRESS_LENGTH;
|
||||
}
|
||||
|
||||
if (!$this->validateIPv6($ip)) {
|
||||
return [$this->message, []];
|
||||
}
|
||||
if (!$this->ipv6) {
|
||||
return [$this->ipv6NotAllowed, []];
|
||||
}
|
||||
|
||||
if ($this->expandIPv6) {
|
||||
$ip = $this->expandIPv6($ip);
|
||||
}
|
||||
} else {
|
||||
if ($cidr !== null) {
|
||||
if ($cidr > IpHelper::IPV4_ADDRESS_LENGTH || $cidr < 0) {
|
||||
return [$this->wrongCidr, []];
|
||||
}
|
||||
} else {
|
||||
$isCidrDefault = true;
|
||||
$cidr = IpHelper::IPV4_ADDRESS_LENGTH;
|
||||
}
|
||||
if (!$this->validateIPv4($ip)) {
|
||||
return [$this->message, []];
|
||||
}
|
||||
if (!$this->ipv4) {
|
||||
return [$this->ipv4NotAllowed, []];
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->isAllowed($ip, $cidr)) {
|
||||
return [$this->notInRange, []];
|
||||
}
|
||||
|
||||
$result = $negation . $ip;
|
||||
|
||||
if ($this->subnet !== false && (!$isCidrDefault || $isCidrDefault && $this->normalize)) {
|
||||
$result .= "/$cidr";
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands an IPv6 address to it's full notation.
|
||||
*
|
||||
* For example `2001:db8::1` will be expanded to `2001:0db8:0000:0000:0000:0000:0000:0001`.
|
||||
*
|
||||
* @param string $ip the original IPv6
|
||||
* @return string the expanded IPv6
|
||||
*/
|
||||
private function expandIPv6($ip)
|
||||
{
|
||||
return IpHelper::expandIPv6($ip);
|
||||
}
|
||||
|
||||
/**
|
||||
* The method checks whether the IP address with specified CIDR is allowed according to the [[ranges]] list.
|
||||
*
|
||||
* @param string $ip
|
||||
* @param int $cidr
|
||||
* @return bool
|
||||
* @see ranges
|
||||
*/
|
||||
private function isAllowed($ip, $cidr)
|
||||
{
|
||||
if (empty($this->ranges)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($this->ranges as $string) {
|
||||
list($isNegated, $range) = $this->parseNegatedRange($string);
|
||||
if ($this->inRange($ip, $cidr, $range)) {
|
||||
return !$isNegated;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses IP address/range for the negation with [[NEGATION_CHAR]].
|
||||
*
|
||||
* @param $string
|
||||
* @return array `[0 => bool, 1 => string]`
|
||||
* - boolean: whether the string is negated
|
||||
* - string: the string without negation (when the negation were present)
|
||||
*/
|
||||
private function parseNegatedRange($string)
|
||||
{
|
||||
$isNegated = strpos($string, static::NEGATION_CHAR) === 0;
|
||||
return [$isNegated, $isNegated ? substr($string, strlen(static::NEGATION_CHAR)) : $string];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares array to fill in [[ranges]].
|
||||
*
|
||||
* - Recursively substitutes aliases, described in [[networks]] with their values,
|
||||
* - Removes duplicates.
|
||||
*
|
||||
* @param $ranges
|
||||
* @return array
|
||||
* @see networks
|
||||
*/
|
||||
private function prepareRanges($ranges)
|
||||
{
|
||||
$result = [];
|
||||
foreach ($ranges as $string) {
|
||||
list($isRangeNegated, $range) = $this->parseNegatedRange($string);
|
||||
if (isset($this->networks[$range])) {
|
||||
$replacements = $this->prepareRanges($this->networks[$range]);
|
||||
foreach ($replacements as &$replacement) {
|
||||
list($isReplacementNegated, $replacement) = $this->parseNegatedRange($replacement);
|
||||
$result[] = ($isRangeNegated && !$isReplacementNegated ? static::NEGATION_CHAR : '') . $replacement;
|
||||
}
|
||||
} else {
|
||||
$result[] = $string;
|
||||
}
|
||||
}
|
||||
|
||||
return array_unique($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates IPv4 address.
|
||||
*
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*/
|
||||
protected function validateIPv4($value)
|
||||
{
|
||||
return preg_match($this->ipv4Pattern, $value) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates IPv6 address.
|
||||
*
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*/
|
||||
protected function validateIPv6($value)
|
||||
{
|
||||
return preg_match($this->ipv6Pattern, $value) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the IP version.
|
||||
*
|
||||
* @param string $ip
|
||||
* @return int
|
||||
*/
|
||||
private function getIpVersion($ip)
|
||||
{
|
||||
return IpHelper::getIpVersion($ip);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get the Regexp pattern for initial IP address parsing.
|
||||
* @return string
|
||||
*/
|
||||
private function getIpParsePattern()
|
||||
{
|
||||
return '/^(' . preg_quote(static::NEGATION_CHAR, '/') . '?)(.+?)(\/(\d+))?$/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the IP is in subnet range.
|
||||
*
|
||||
* @param string $ip an IPv4 or IPv6 address
|
||||
* @param int $cidr
|
||||
* @param string $range subnet in CIDR format e.g. `10.0.0.0/8` or `2001:af::/64`
|
||||
* @return bool
|
||||
*/
|
||||
private function inRange($ip, $cidr, $range)
|
||||
{
|
||||
return IpHelper::inRange($ip . '/' . $cidr, $range);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clientValidateAttribute($model, $attribute, $view)
|
||||
{
|
||||
ValidationAsset::register($view);
|
||||
$options = $this->getClientOptions($model, $attribute);
|
||||
|
||||
return 'yii.validation.ip(value, messages, ' . Json::htmlEncode($options) . ');';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClientOptions($model, $attribute)
|
||||
{
|
||||
$messages = [
|
||||
'ipv6NotAllowed' => $this->ipv6NotAllowed,
|
||||
'ipv4NotAllowed' => $this->ipv4NotAllowed,
|
||||
'message' => $this->message,
|
||||
'noSubnet' => $this->noSubnet,
|
||||
'hasSubnet' => $this->hasSubnet,
|
||||
];
|
||||
foreach ($messages as &$message) {
|
||||
$message = $this->formatMessage($message, [
|
||||
'attribute' => $model->getAttributeLabel($attribute),
|
||||
]);
|
||||
}
|
||||
|
||||
$options = [
|
||||
'ipv4Pattern' => new JsExpression(Html::escapeJsRegularExpression($this->ipv4Pattern)),
|
||||
'ipv6Pattern' => new JsExpression(Html::escapeJsRegularExpression($this->ipv6Pattern)),
|
||||
'messages' => $messages,
|
||||
'ipv4' => (bool) $this->ipv4,
|
||||
'ipv6' => (bool) $this->ipv6,
|
||||
'ipParsePattern' => new JsExpression(Html::escapeJsRegularExpression($this->getIpParsePattern())),
|
||||
'negation' => $this->negation,
|
||||
'subnet' => $this->subnet,
|
||||
];
|
||||
if ($this->skipOnEmpty) {
|
||||
$options['skipOnEmpty'] = 1;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
180
vendor/yiisoft/yii2/validators/NumberValidator.php
vendored
Normal file
180
vendor/yiisoft/yii2/validators/NumberValidator.php
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use Yii;
|
||||
use yii\helpers\Json;
|
||||
use yii\helpers\StringHelper;
|
||||
use yii\web\JsExpression;
|
||||
|
||||
/**
|
||||
* NumberValidator validates that the attribute value is a number.
|
||||
*
|
||||
* The format of the number must match the regular expression specified in [[integerPattern]] or [[numberPattern]].
|
||||
* Optionally, you may configure the [[max]] and [[min]] properties to ensure the number
|
||||
* is within certain range.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class NumberValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* @var bool whether the attribute value can only be an integer. Defaults to false.
|
||||
*/
|
||||
public $integerOnly = false;
|
||||
/**
|
||||
* @var int|float upper limit of the number. Defaults to null, meaning no upper limit.
|
||||
* @see tooBig for the customized message used when the number is too big.
|
||||
*/
|
||||
public $max;
|
||||
/**
|
||||
* @var int|float lower limit of the number. Defaults to null, meaning no lower limit.
|
||||
* @see tooSmall for the customized message used when the number is too small.
|
||||
*/
|
||||
public $min;
|
||||
/**
|
||||
* @var string user-defined error message used when the value is bigger than [[max]].
|
||||
*/
|
||||
public $tooBig;
|
||||
/**
|
||||
* @var string user-defined error message used when the value is smaller than [[min]].
|
||||
*/
|
||||
public $tooSmall;
|
||||
/**
|
||||
* @var string the regular expression for matching integers.
|
||||
*/
|
||||
public $integerPattern = '/^\s*[+-]?\d+\s*$/';
|
||||
/**
|
||||
* @var string the regular expression for matching numbers. It defaults to a pattern
|
||||
* that matches floating numbers with optional exponential part (e.g. -1.23e-10).
|
||||
*/
|
||||
public $numberPattern = '/^\s*[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\s*$/';
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if ($this->message === null) {
|
||||
$this->message = $this->integerOnly ? Yii::t('yii', '{attribute} must be an integer.')
|
||||
: Yii::t('yii', '{attribute} must be a number.');
|
||||
}
|
||||
if ($this->min !== null && $this->tooSmall === null) {
|
||||
$this->tooSmall = Yii::t('yii', '{attribute} must be no less than {min}.');
|
||||
}
|
||||
if ($this->max !== null && $this->tooBig === null) {
|
||||
$this->tooBig = Yii::t('yii', '{attribute} must be no greater than {max}.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAttribute($model, $attribute)
|
||||
{
|
||||
$value = $model->$attribute;
|
||||
if ($this->isNotNumber($value)) {
|
||||
$this->addError($model, $attribute, $this->message);
|
||||
return;
|
||||
}
|
||||
$pattern = $this->integerOnly ? $this->integerPattern : $this->numberPattern;
|
||||
|
||||
if (!preg_match($pattern, StringHelper::normalizeNumber($value))) {
|
||||
$this->addError($model, $attribute, $this->message);
|
||||
}
|
||||
if ($this->min !== null && $value < $this->min) {
|
||||
$this->addError($model, $attribute, $this->tooSmall, ['min' => $this->min]);
|
||||
}
|
||||
if ($this->max !== null && $value > $this->max) {
|
||||
$this->addError($model, $attribute, $this->tooBig, ['max' => $this->max]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function validateValue($value)
|
||||
{
|
||||
if ($this->isNotNumber($value)) {
|
||||
return [Yii::t('yii', '{attribute} is invalid.'), []];
|
||||
}
|
||||
$pattern = $this->integerOnly ? $this->integerPattern : $this->numberPattern;
|
||||
if (!preg_match($pattern, StringHelper::normalizeNumber($value))) {
|
||||
return [$this->message, []];
|
||||
} elseif ($this->min !== null && $value < $this->min) {
|
||||
return [$this->tooSmall, ['min' => $this->min]];
|
||||
} elseif ($this->max !== null && $value > $this->max) {
|
||||
return [$this->tooBig, ['max' => $this->max]];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* @param mixed $value the data value to be checked.
|
||||
*/
|
||||
private function isNotNumber($value)
|
||||
{
|
||||
return is_array($value)
|
||||
|| (is_object($value) && !method_exists($value, '__toString'))
|
||||
|| (!is_object($value) && !is_scalar($value) && $value !== null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clientValidateAttribute($model, $attribute, $view)
|
||||
{
|
||||
ValidationAsset::register($view);
|
||||
$options = $this->getClientOptions($model, $attribute);
|
||||
|
||||
return 'yii.validation.number(value, messages, ' . Json::htmlEncode($options) . ');';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClientOptions($model, $attribute)
|
||||
{
|
||||
$label = $model->getAttributeLabel($attribute);
|
||||
|
||||
$options = [
|
||||
'pattern' => new JsExpression($this->integerOnly ? $this->integerPattern : $this->numberPattern),
|
||||
'message' => $this->formatMessage($this->message, [
|
||||
'attribute' => $label,
|
||||
]),
|
||||
];
|
||||
|
||||
if ($this->min !== null) {
|
||||
// ensure numeric value to make javascript comparison equal to PHP comparison
|
||||
// https://github.com/yiisoft/yii2/issues/3118
|
||||
$options['min'] = is_string($this->min) ? (float) $this->min : $this->min;
|
||||
$options['tooSmall'] = $this->formatMessage($this->tooSmall, [
|
||||
'attribute' => $label,
|
||||
'min' => $this->min,
|
||||
]);
|
||||
}
|
||||
if ($this->max !== null) {
|
||||
// ensure numeric value to make javascript comparison equal to PHP comparison
|
||||
// https://github.com/yiisoft/yii2/issues/3118
|
||||
$options['max'] = is_string($this->max) ? (float) $this->max : $this->max;
|
||||
$options['tooBig'] = $this->formatMessage($this->tooBig, [
|
||||
'attribute' => $label,
|
||||
'max' => $this->max,
|
||||
]);
|
||||
}
|
||||
if ($this->skipOnEmpty) {
|
||||
$options['skipOnEmpty'] = 1;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
24
vendor/yiisoft/yii2/validators/PunycodeAsset.php
vendored
Normal file
24
vendor/yiisoft/yii2/validators/PunycodeAsset.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use yii\web\AssetBundle;
|
||||
|
||||
/**
|
||||
* This asset bundle provides the javascript files needed for the [[EmailValidator]]s client validation.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class PunycodeAsset extends AssetBundle
|
||||
{
|
||||
public $sourcePath = '@bower/punycode';
|
||||
public $js = [
|
||||
'punycode.js',
|
||||
];
|
||||
}
|
||||
142
vendor/yiisoft/yii2/validators/RangeValidator.php
vendored
Normal file
142
vendor/yiisoft/yii2/validators/RangeValidator.php
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\helpers\ArrayHelper;
|
||||
|
||||
/**
|
||||
* RangeValidator validates that the attribute value is among a list of values.
|
||||
*
|
||||
* The range can be specified via the [[range]] property.
|
||||
* If the [[not]] property is set true, the validator will ensure the attribute value
|
||||
* is NOT among the specified range.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class RangeValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* @var array|\Traversable|\Closure a list of valid values that the attribute value should be among or an anonymous function that returns
|
||||
* such a list. The signature of the anonymous function should be as follows,
|
||||
*
|
||||
* ```php
|
||||
* function($model, $attribute) {
|
||||
* // compute range
|
||||
* return $range;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
public $range;
|
||||
/**
|
||||
* @var bool whether the comparison is strict (both type and value must be the same)
|
||||
*/
|
||||
public $strict = false;
|
||||
/**
|
||||
* @var bool whether to invert the validation logic. Defaults to false. If set to true,
|
||||
* the attribute value should NOT be among the list of values defined via [[range]].
|
||||
*/
|
||||
public $not = false;
|
||||
/**
|
||||
* @var bool whether to allow array type attribute.
|
||||
*/
|
||||
public $allowArray = false;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if (!is_array($this->range)
|
||||
&& !($this->range instanceof \Closure)
|
||||
&& !($this->range instanceof \Traversable)
|
||||
) {
|
||||
throw new InvalidConfigException('The "range" property must be set.');
|
||||
}
|
||||
if ($this->message === null) {
|
||||
$this->message = Yii::t('yii', '{attribute} is invalid.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function validateValue($value)
|
||||
{
|
||||
$in = false;
|
||||
|
||||
if ($this->allowArray
|
||||
&& ($value instanceof \Traversable || is_array($value))
|
||||
&& ArrayHelper::isSubset($value, $this->range, $this->strict)
|
||||
) {
|
||||
$in = true;
|
||||
}
|
||||
|
||||
if (!$in && ArrayHelper::isIn($value, $this->range, $this->strict)) {
|
||||
$in = true;
|
||||
}
|
||||
|
||||
return $this->not !== $in ? null : [$this->message, []];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAttribute($model, $attribute)
|
||||
{
|
||||
if ($this->range instanceof \Closure) {
|
||||
$this->range = call_user_func($this->range, $model, $attribute);
|
||||
}
|
||||
parent::validateAttribute($model, $attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clientValidateAttribute($model, $attribute, $view)
|
||||
{
|
||||
if ($this->range instanceof \Closure) {
|
||||
$this->range = call_user_func($this->range, $model, $attribute);
|
||||
}
|
||||
|
||||
ValidationAsset::register($view);
|
||||
$options = $this->getClientOptions($model, $attribute);
|
||||
|
||||
return 'yii.validation.range(value, messages, ' . json_encode($options, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . ');';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClientOptions($model, $attribute)
|
||||
{
|
||||
$range = [];
|
||||
foreach ($this->range as $value) {
|
||||
$range[] = (string) $value;
|
||||
}
|
||||
$options = [
|
||||
'range' => $range,
|
||||
'not' => $this->not,
|
||||
'message' => $this->formatMessage($this->message, [
|
||||
'attribute' => $model->getAttributeLabel($attribute),
|
||||
]),
|
||||
];
|
||||
if ($this->skipOnEmpty) {
|
||||
$options['skipOnEmpty'] = 1;
|
||||
}
|
||||
if ($this->allowArray) {
|
||||
$options['allowArray'] = 1;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
94
vendor/yiisoft/yii2/validators/RegularExpressionValidator.php
vendored
Normal file
94
vendor/yiisoft/yii2/validators/RegularExpressionValidator.php
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\helpers\Html;
|
||||
use yii\helpers\Json;
|
||||
use yii\web\JsExpression;
|
||||
|
||||
/**
|
||||
* RegularExpressionValidator validates that the attribute value matches the specified [[pattern]].
|
||||
*
|
||||
* If the [[not]] property is set true, the validator will ensure the attribute value do NOT match the [[pattern]].
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class RegularExpressionValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* @var string the regular expression to be matched with
|
||||
*/
|
||||
public $pattern;
|
||||
/**
|
||||
* @var bool whether to invert the validation logic. Defaults to false. If set to true,
|
||||
* the regular expression defined via [[pattern]] should NOT match the attribute value.
|
||||
*/
|
||||
public $not = false;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if ($this->pattern === null) {
|
||||
throw new InvalidConfigException('The "pattern" property must be set.');
|
||||
}
|
||||
if ($this->message === null) {
|
||||
$this->message = Yii::t('yii', '{attribute} is invalid.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function validateValue($value)
|
||||
{
|
||||
$valid = !is_array($value) &&
|
||||
(!$this->not && preg_match($this->pattern, $value)
|
||||
|| $this->not && !preg_match($this->pattern, $value));
|
||||
|
||||
return $valid ? null : [$this->message, []];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clientValidateAttribute($model, $attribute, $view)
|
||||
{
|
||||
ValidationAsset::register($view);
|
||||
$options = $this->getClientOptions($model, $attribute);
|
||||
|
||||
return 'yii.validation.regularExpression(value, messages, ' . Json::htmlEncode($options) . ');';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClientOptions($model, $attribute)
|
||||
{
|
||||
$pattern = Html::escapeJsRegularExpression($this->pattern);
|
||||
|
||||
$options = [
|
||||
'pattern' => new JsExpression($pattern),
|
||||
'not' => $this->not,
|
||||
'message' => $this->formatMessage($this->message, [
|
||||
'attribute' => $model->getAttributeLabel($attribute),
|
||||
]),
|
||||
];
|
||||
if ($this->skipOnEmpty) {
|
||||
$options['skipOnEmpty'] = 1;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
121
vendor/yiisoft/yii2/validators/RequiredValidator.php
vendored
Normal file
121
vendor/yiisoft/yii2/validators/RequiredValidator.php
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use Yii;
|
||||
|
||||
/**
|
||||
* RequiredValidator validates that the specified attribute does not have null or empty value.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class RequiredValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* @var bool whether to skip this validator if the value being validated is empty.
|
||||
*/
|
||||
public $skipOnEmpty = false;
|
||||
/**
|
||||
* @var mixed the desired value that the attribute must have.
|
||||
* If this is null, the validator will validate that the specified attribute is not empty.
|
||||
* If this is set as a value that is not null, the validator will validate that
|
||||
* the attribute has a value that is the same as this property value.
|
||||
* Defaults to null.
|
||||
* @see strict
|
||||
*/
|
||||
public $requiredValue;
|
||||
/**
|
||||
* @var bool whether the comparison between the attribute value and [[requiredValue]] is strict.
|
||||
* When this is true, both the values and types must match.
|
||||
* Defaults to false, meaning only the values need to match.
|
||||
* Note that when [[requiredValue]] is null, if this property is true, the validator will check
|
||||
* if the attribute value is null; If this property is false, the validator will call [[isEmpty]]
|
||||
* to check if the attribute value is empty.
|
||||
*/
|
||||
public $strict = false;
|
||||
/**
|
||||
* @var string the user-defined error message. It may contain the following placeholders which
|
||||
* will be replaced accordingly by the validator:
|
||||
*
|
||||
* - `{attribute}`: the label of the attribute being validated
|
||||
* - `{value}`: the value of the attribute being validated
|
||||
* - `{requiredValue}`: the value of [[requiredValue]]
|
||||
*/
|
||||
public $message;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if ($this->message === null) {
|
||||
$this->message = $this->requiredValue === null ? Yii::t('yii', '{attribute} cannot be blank.')
|
||||
: Yii::t('yii', '{attribute} must be "{requiredValue}".');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function validateValue($value)
|
||||
{
|
||||
if ($this->requiredValue === null) {
|
||||
if ($this->strict && $value !== null || !$this->strict && !$this->isEmpty(is_string($value) ? trim($value) : $value)) {
|
||||
return null;
|
||||
}
|
||||
} elseif (!$this->strict && $value == $this->requiredValue || $this->strict && $value === $this->requiredValue) {
|
||||
return null;
|
||||
}
|
||||
if ($this->requiredValue === null) {
|
||||
return [$this->message, []];
|
||||
}
|
||||
|
||||
return [$this->message, [
|
||||
'requiredValue' => $this->requiredValue,
|
||||
]];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clientValidateAttribute($model, $attribute, $view)
|
||||
{
|
||||
ValidationAsset::register($view);
|
||||
$options = $this->getClientOptions($model, $attribute);
|
||||
|
||||
return 'yii.validation.required(value, messages, ' . json_encode($options, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . ');';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClientOptions($model, $attribute)
|
||||
{
|
||||
$options = [];
|
||||
if ($this->requiredValue !== null) {
|
||||
$options['message'] = $this->formatMessage($this->message, [
|
||||
'requiredValue' => $this->requiredValue,
|
||||
]);
|
||||
$options['requiredValue'] = $this->requiredValue;
|
||||
} else {
|
||||
$options['message'] = $this->message;
|
||||
}
|
||||
if ($this->strict) {
|
||||
$options['strict'] = 1;
|
||||
}
|
||||
|
||||
$options['message'] = $this->formatMessage($options['message'], [
|
||||
'attribute' => $model->getAttributeLabel($attribute),
|
||||
]);
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
41
vendor/yiisoft/yii2/validators/SafeValidator.php
vendored
Normal file
41
vendor/yiisoft/yii2/validators/SafeValidator.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
/**
|
||||
* SafeValidator serves as a dummy validator whose main purpose is to mark the attributes to be safe for massive assignment.
|
||||
*
|
||||
* This class is required because of the way in which Yii determines whether a property is safe for massive assignment, that is,
|
||||
* when a user submits form data to be loaded into a model directly from the POST data, is it ok for a property to be copied.
|
||||
* In many cases, this is required but because sometimes properties are internal and you do not want the POST data to be able to
|
||||
* override these internal values (especially things like database row ids), Yii assumes all values are unsafe for massive assignment
|
||||
* unless a validation rule exists for the property, which in most cases it will. Sometimes, however, an item is safe for massive assigment but
|
||||
* does not have a validation rule associated with it - for instance, due to no validation being performed, in which case, you use this class
|
||||
* as a validation rule for that property. Although it has no functionality, it allows Yii to determine that the property is safe to copy.
|
||||
*
|
||||
* > Note: [[when]] property is not supported by SafeValidator.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class SafeValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAttributes($model, $attributes = null)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAttribute($model, $attribute)
|
||||
{
|
||||
}
|
||||
}
|
||||
202
vendor/yiisoft/yii2/validators/StringValidator.php
vendored
Normal file
202
vendor/yiisoft/yii2/validators/StringValidator.php
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use Yii;
|
||||
|
||||
/**
|
||||
* StringValidator validates that the attribute value is of certain length.
|
||||
*
|
||||
* Note, this validator should only be used with string-typed attributes.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class StringValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* @var int|array specifies the length limit of the value to be validated.
|
||||
* This can be specified in one of the following forms:
|
||||
*
|
||||
* - an integer: the exact length that the value should be of;
|
||||
* - an array of one element: the minimum length that the value should be of. For example, `[8]`.
|
||||
* This will overwrite [[min]].
|
||||
* - an array of two elements: the minimum and maximum lengths that the value should be of.
|
||||
* For example, `[8, 128]`. This will overwrite both [[min]] and [[max]].
|
||||
* @see tooShort for the customized message for a too short string.
|
||||
* @see tooLong for the customized message for a too long string.
|
||||
* @see notEqual for the customized message for a string that does not match desired length.
|
||||
*/
|
||||
public $length;
|
||||
/**
|
||||
* @var int maximum length. If not set, it means no maximum length limit.
|
||||
* @see tooLong for the customized message for a too long string.
|
||||
*/
|
||||
public $max;
|
||||
/**
|
||||
* @var int minimum length. If not set, it means no minimum length limit.
|
||||
* @see tooShort for the customized message for a too short string.
|
||||
*/
|
||||
public $min;
|
||||
/**
|
||||
* @var string user-defined error message used when the value is not a string.
|
||||
*/
|
||||
public $message;
|
||||
/**
|
||||
* @var string user-defined error message used when the length of the value is smaller than [[min]].
|
||||
*/
|
||||
public $tooShort;
|
||||
/**
|
||||
* @var string user-defined error message used when the length of the value is greater than [[max]].
|
||||
*/
|
||||
public $tooLong;
|
||||
/**
|
||||
* @var string user-defined error message used when the length of the value is not equal to [[length]].
|
||||
*/
|
||||
public $notEqual;
|
||||
/**
|
||||
* @var string the encoding of the string value to be validated (e.g. 'UTF-8').
|
||||
* If this property is not set, [[\yii\base\Application::charset]] will be used.
|
||||
*/
|
||||
public $encoding;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if (is_array($this->length)) {
|
||||
if (isset($this->length[0])) {
|
||||
$this->min = $this->length[0];
|
||||
}
|
||||
if (isset($this->length[1])) {
|
||||
$this->max = $this->length[1];
|
||||
}
|
||||
$this->length = null;
|
||||
}
|
||||
if ($this->encoding === null) {
|
||||
$this->encoding = Yii::$app ? Yii::$app->charset : 'UTF-8';
|
||||
}
|
||||
if ($this->message === null) {
|
||||
$this->message = Yii::t('yii', '{attribute} must be a string.');
|
||||
}
|
||||
if ($this->min !== null && $this->tooShort === null) {
|
||||
$this->tooShort = Yii::t('yii', '{attribute} should contain at least {min, number} {min, plural, one{character} other{characters}}.');
|
||||
}
|
||||
if ($this->max !== null && $this->tooLong === null) {
|
||||
$this->tooLong = Yii::t('yii', '{attribute} should contain at most {max, number} {max, plural, one{character} other{characters}}.');
|
||||
}
|
||||
if ($this->length !== null && $this->notEqual === null) {
|
||||
$this->notEqual = Yii::t('yii', '{attribute} should contain {length, number} {length, plural, one{character} other{characters}}.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAttribute($model, $attribute)
|
||||
{
|
||||
$value = $model->$attribute;
|
||||
|
||||
if (!is_string($value)) {
|
||||
$this->addError($model, $attribute, $this->message);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$length = mb_strlen($value, $this->encoding);
|
||||
|
||||
if ($this->min !== null && $length < $this->min) {
|
||||
$this->addError($model, $attribute, $this->tooShort, ['min' => $this->min]);
|
||||
}
|
||||
if ($this->max !== null && $length > $this->max) {
|
||||
$this->addError($model, $attribute, $this->tooLong, ['max' => $this->max]);
|
||||
}
|
||||
if ($this->length !== null && $length !== $this->length) {
|
||||
$this->addError($model, $attribute, $this->notEqual, ['length' => $this->length]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function validateValue($value)
|
||||
{
|
||||
if (!is_string($value)) {
|
||||
return [$this->message, []];
|
||||
}
|
||||
|
||||
$length = mb_strlen($value, $this->encoding);
|
||||
|
||||
if ($this->min !== null && $length < $this->min) {
|
||||
return [$this->tooShort, ['min' => $this->min]];
|
||||
}
|
||||
if ($this->max !== null && $length > $this->max) {
|
||||
return [$this->tooLong, ['max' => $this->max]];
|
||||
}
|
||||
if ($this->length !== null && $length !== $this->length) {
|
||||
return [$this->notEqual, ['length' => $this->length]];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clientValidateAttribute($model, $attribute, $view)
|
||||
{
|
||||
ValidationAsset::register($view);
|
||||
$options = $this->getClientOptions($model, $attribute);
|
||||
|
||||
return 'yii.validation.string(value, messages, ' . json_encode($options, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . ');';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClientOptions($model, $attribute)
|
||||
{
|
||||
$label = $model->getAttributeLabel($attribute);
|
||||
|
||||
$options = [
|
||||
'message' => $this->formatMessage($this->message, [
|
||||
'attribute' => $label,
|
||||
]),
|
||||
];
|
||||
|
||||
if ($this->min !== null) {
|
||||
$options['min'] = $this->min;
|
||||
$options['tooShort'] = $this->formatMessage($this->tooShort, [
|
||||
'attribute' => $label,
|
||||
'min' => $this->min,
|
||||
]);
|
||||
}
|
||||
if ($this->max !== null) {
|
||||
$options['max'] = $this->max;
|
||||
$options['tooLong'] = $this->formatMessage($this->tooLong, [
|
||||
'attribute' => $label,
|
||||
'max' => $this->max,
|
||||
]);
|
||||
}
|
||||
if ($this->length !== null) {
|
||||
$options['is'] = $this->length;
|
||||
$options['notEqual'] = $this->formatMessage($this->notEqual, [
|
||||
'attribute' => $label,
|
||||
'length' => $this->length,
|
||||
]);
|
||||
}
|
||||
if ($this->skipOnEmpty) {
|
||||
$options['skipOnEmpty'] = 1;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
328
vendor/yiisoft/yii2/validators/UniqueValidator.php
vendored
Normal file
328
vendor/yiisoft/yii2/validators/UniqueValidator.php
vendored
Normal file
@@ -0,0 +1,328 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Model;
|
||||
use yii\db\ActiveQuery;
|
||||
use yii\db\ActiveQueryInterface;
|
||||
use yii\db\ActiveRecord;
|
||||
use yii\db\ActiveRecordInterface;
|
||||
use yii\helpers\Inflector;
|
||||
|
||||
/**
|
||||
* UniqueValidator validates that the attribute value is unique in the specified database table.
|
||||
*
|
||||
* UniqueValidator checks if the value being validated is unique in the table column specified by
|
||||
* the ActiveRecord class [[targetClass]] and the attribute [[targetAttribute]].
|
||||
*
|
||||
* The following are examples of validation rules using this validator:
|
||||
*
|
||||
* ```php
|
||||
* // a1 needs to be unique
|
||||
* ['a1', 'unique']
|
||||
* // a1 needs to be unique, but column a2 will be used to check the uniqueness of the a1 value
|
||||
* ['a1', 'unique', 'targetAttribute' => 'a2']
|
||||
* // a1 and a2 need to be unique together, and they both will receive error message
|
||||
* [['a1', 'a2'], 'unique', 'targetAttribute' => ['a1', 'a2']]
|
||||
* // a1 and a2 need to be unique together, only a1 will receive error message
|
||||
* ['a1', 'unique', 'targetAttribute' => ['a1', 'a2']]
|
||||
* // a1 needs to be unique by checking the uniqueness of both a2 and a3 (using a1 value)
|
||||
* ['a1', 'unique', 'targetAttribute' => ['a2', 'a1' => 'a3']]
|
||||
* ```
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class UniqueValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* @var string the name of the ActiveRecord class that should be used to validate the uniqueness
|
||||
* of the current attribute value. If not set, it will use the ActiveRecord class of the attribute being validated.
|
||||
* @see targetAttribute
|
||||
*/
|
||||
public $targetClass;
|
||||
/**
|
||||
* @var string|array the name of the [[\yii\db\ActiveRecord|ActiveRecord]] attribute that should be used to
|
||||
* validate the uniqueness of the current attribute value. If not set, it will use the name
|
||||
* of the attribute currently being validated. You may use an array to validate the uniqueness
|
||||
* of multiple columns at the same time. The array values are the attributes that will be
|
||||
* used to validate the uniqueness, while the array keys are the attributes whose values are to be validated.
|
||||
*/
|
||||
public $targetAttribute;
|
||||
/**
|
||||
* @var string|array|\Closure additional filter to be applied to the DB query used to check the uniqueness of the attribute value.
|
||||
* This can be a string or an array representing the additional query condition (refer to [[\yii\db\Query::where()]]
|
||||
* on the format of query condition), or an anonymous function with the signature `function ($query)`, where `$query`
|
||||
* is the [[\yii\db\Query|Query]] object that you can modify in the function.
|
||||
*/
|
||||
public $filter;
|
||||
/**
|
||||
* @var string the user-defined error message.
|
||||
*
|
||||
* When validating single attribute, it may contain
|
||||
* the following placeholders which will be replaced accordingly by the validator:
|
||||
*
|
||||
* - `{attribute}`: the label of the attribute being validated
|
||||
* - `{value}`: the value of the attribute being validated
|
||||
*
|
||||
* When validating mutliple attributes, it may contain the following placeholders:
|
||||
*
|
||||
* - `{attributes}`: the labels of the attributes being validated.
|
||||
* - `{values}`: the values of the attributes being validated.
|
||||
*/
|
||||
public $message;
|
||||
/**
|
||||
* @var string
|
||||
* @since 2.0.9
|
||||
* @deprecated since version 2.0.10, to be removed in 2.1. Use [[message]] property
|
||||
* to setup custom message for multiple target attributes.
|
||||
*/
|
||||
public $comboNotUnique;
|
||||
/**
|
||||
* @var string and|or define how target attributes are related
|
||||
* @since 2.0.11
|
||||
*/
|
||||
public $targetAttributeJunction = 'and';
|
||||
/**
|
||||
* @var bool whether this validator is forced to always use master DB
|
||||
* @since 2.0.14
|
||||
*/
|
||||
public $forceMasterDb = true;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if ($this->message !== null) {
|
||||
return;
|
||||
}
|
||||
if (is_array($this->targetAttribute) && count($this->targetAttribute) > 1) {
|
||||
// fallback for deprecated `comboNotUnique` property - use it as message if is set
|
||||
if ($this->comboNotUnique === null) {
|
||||
$this->message = Yii::t('yii', 'The combination {values} of {attributes} has already been taken.');
|
||||
} else {
|
||||
$this->message = $this->comboNotUnique;
|
||||
}
|
||||
} else {
|
||||
$this->message = Yii::t('yii', '{attribute} "{value}" has already been taken.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAttribute($model, $attribute)
|
||||
{
|
||||
/* @var $targetClass ActiveRecordInterface */
|
||||
$targetClass = $this->getTargetClass($model);
|
||||
$targetAttribute = $this->targetAttribute === null ? $attribute : $this->targetAttribute;
|
||||
$rawConditions = $this->prepareConditions($targetAttribute, $model, $attribute);
|
||||
$conditions = [$this->targetAttributeJunction === 'or' ? 'or' : 'and'];
|
||||
|
||||
foreach ($rawConditions as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$this->addError($model, $attribute, Yii::t('yii', '{attribute} is invalid.'));
|
||||
return;
|
||||
}
|
||||
$conditions[] = [$key => $value];
|
||||
}
|
||||
|
||||
$db = $targetClass::getDb();
|
||||
|
||||
$modelExists = false;
|
||||
|
||||
if ($this->forceMasterDb && method_exists($db, 'useMaster')) {
|
||||
$db->useMaster(function () use ($targetClass, $conditions, $model, &$modelExists) {
|
||||
$modelExists = $this->modelExists($targetClass, $conditions, $model);
|
||||
});
|
||||
} else {
|
||||
$modelExists = $this->modelExists($targetClass, $conditions, $model);
|
||||
}
|
||||
|
||||
if ($modelExists) {
|
||||
if (is_array($targetAttribute) && count($targetAttribute) > 1) {
|
||||
$this->addComboNotUniqueError($model, $attribute);
|
||||
} else {
|
||||
$this->addError($model, $attribute, $this->message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Model $model the data model to be validated
|
||||
* @return string Target class name
|
||||
*/
|
||||
private function getTargetClass($model)
|
||||
{
|
||||
return $this->targetClass === null ? get_class($model) : $this->targetClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the $model exists in the database.
|
||||
*
|
||||
* @param string $targetClass the name of the ActiveRecord class that should be used to validate the uniqueness
|
||||
* of the current attribute value.
|
||||
* @param array $conditions conditions, compatible with [[\yii\db\Query::where()|Query::where()]] key-value format.
|
||||
* @param Model $model the data model to be validated
|
||||
*
|
||||
* @return bool whether the model already exists
|
||||
*/
|
||||
private function modelExists($targetClass, $conditions, $model)
|
||||
{
|
||||
/** @var ActiveRecordInterface $targetClass $query */
|
||||
$query = $this->prepareQuery($targetClass, $conditions);
|
||||
|
||||
if (!$model instanceof ActiveRecordInterface || $model->getIsNewRecord() || $model->className() !== $targetClass::className()) {
|
||||
// if current $model isn't in the database yet then it's OK just to call exists()
|
||||
// also there's no need to run check based on primary keys, when $targetClass is not the same as $model's class
|
||||
$exists = $query->exists();
|
||||
} else {
|
||||
// if current $model is in the database already we can't use exists()
|
||||
if ($query instanceof \yii\db\ActiveQuery) {
|
||||
// only select primary key to optimize query
|
||||
$columnsCondition = array_flip($targetClass::primaryKey());
|
||||
$query->select(array_flip($this->applyTableAlias($query, $columnsCondition)));
|
||||
|
||||
// any with relation can't be loaded because related fields are not selected
|
||||
$query->with = null;
|
||||
}
|
||||
$models = $query->limit(2)->asArray()->all();
|
||||
$n = count($models);
|
||||
if ($n === 1) {
|
||||
// if there is one record, check if it is the currently validated model
|
||||
$dbModel = reset($models);
|
||||
$pks = $targetClass::primaryKey();
|
||||
$pk = [];
|
||||
foreach ($pks as $pkAttribute) {
|
||||
$pk[$pkAttribute] = $dbModel[$pkAttribute];
|
||||
}
|
||||
$exists = ($pk != $model->getOldPrimaryKey(true));
|
||||
} else {
|
||||
// if there is more than one record, the value is not unique
|
||||
$exists = $n > 1;
|
||||
}
|
||||
}
|
||||
|
||||
return $exists;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a query by applying filtering conditions defined in $conditions method property
|
||||
* and [[filter]] class property.
|
||||
*
|
||||
* @param ActiveRecordInterface $targetClass the name of the ActiveRecord class that should be used to validate
|
||||
* the uniqueness of the current attribute value.
|
||||
* @param array $conditions conditions, compatible with [[\yii\db\Query::where()|Query::where()]] key-value format
|
||||
*
|
||||
* @return ActiveQueryInterface|ActiveQuery
|
||||
*/
|
||||
private function prepareQuery($targetClass, $conditions)
|
||||
{
|
||||
$query = $targetClass::find();
|
||||
$query->andWhere($conditions);
|
||||
if ($this->filter instanceof \Closure) {
|
||||
call_user_func($this->filter, $query);
|
||||
} elseif ($this->filter !== null) {
|
||||
$query->andWhere($this->filter);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes attributes' relations described in $targetAttribute parameter into conditions, compatible with
|
||||
* [[\yii\db\Query::where()|Query::where()]] key-value format.
|
||||
*
|
||||
* @param string|array $targetAttribute the name of the [[\yii\db\ActiveRecord|ActiveRecord]] attribute that
|
||||
* should be used to validate the uniqueness of the current attribute value. You may use an array to validate
|
||||
* the uniqueness of multiple columns at the same time. The array values are the attributes that will be
|
||||
* used to validate the uniqueness, while the array keys are the attributes whose values are to be validated.
|
||||
* If the key and the value are the same, you can just specify the value.
|
||||
* @param Model $model the data model to be validated
|
||||
* @param string $attribute the name of the attribute to be validated in the $model
|
||||
*
|
||||
* @return array conditions, compatible with [[\yii\db\Query::where()|Query::where()]] key-value format.
|
||||
*/
|
||||
private function prepareConditions($targetAttribute, $model, $attribute)
|
||||
{
|
||||
if (is_array($targetAttribute)) {
|
||||
$conditions = [];
|
||||
foreach ($targetAttribute as $k => $v) {
|
||||
$conditions[$v] = is_int($k) ? $model->$v : $model->$k;
|
||||
}
|
||||
} else {
|
||||
$conditions = [$targetAttribute => $model->$attribute];
|
||||
}
|
||||
|
||||
$targetModelClass = $this->getTargetClass($model);
|
||||
if (!is_subclass_of($targetModelClass, 'yii\db\ActiveRecord')) {
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
/** @var ActiveRecord $targetModelClass */
|
||||
return $this->applyTableAlias($targetModelClass::find(), $conditions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and adds [[comboNotUnique]] error message to the specified model attribute.
|
||||
* @param \yii\base\Model $model the data model.
|
||||
* @param string $attribute the name of the attribute.
|
||||
*/
|
||||
private function addComboNotUniqueError($model, $attribute)
|
||||
{
|
||||
$attributeCombo = [];
|
||||
$valueCombo = [];
|
||||
foreach ($this->targetAttribute as $key => $value) {
|
||||
if (is_int($key)) {
|
||||
$attributeCombo[] = $model->getAttributeLabel($value);
|
||||
$valueCombo[] = '"' . $model->$value . '"';
|
||||
} else {
|
||||
$attributeCombo[] = $model->getAttributeLabel($key);
|
||||
$valueCombo[] = '"' . $model->$key . '"';
|
||||
}
|
||||
}
|
||||
$this->addError($model, $attribute, $this->message, [
|
||||
'attributes' => Inflector::sentence($attributeCombo),
|
||||
'values' => implode('-', $valueCombo),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns conditions with alias.
|
||||
* @param ActiveQuery $query
|
||||
* @param array $conditions array of condition, keys to be modified
|
||||
* @param null|string $alias set empty string for no apply alias. Set null for apply primary table alias
|
||||
* @return array
|
||||
*/
|
||||
private function applyTableAlias($query, $conditions, $alias = null)
|
||||
{
|
||||
if ($alias === null) {
|
||||
$alias = array_keys($query->getTablesUsedInFrom())[0];
|
||||
}
|
||||
$prefixedConditions = [];
|
||||
foreach ($conditions as $columnName => $columnValue) {
|
||||
if (strpos($columnName, '(') === false) {
|
||||
$prefixedColumn = "{$alias}.[[" . preg_replace(
|
||||
'/^' . preg_quote($alias) . '\.(.*)$/',
|
||||
'$1',
|
||||
$columnName) . ']]';
|
||||
} else {
|
||||
// there is an expression, can't prefix it reliably
|
||||
$prefixedColumn = $columnName;
|
||||
}
|
||||
|
||||
$prefixedConditions[$prefixedColumn] = $columnValue;
|
||||
}
|
||||
|
||||
return $prefixedConditions;
|
||||
}
|
||||
}
|
||||
162
vendor/yiisoft/yii2/validators/UrlValidator.php
vendored
Normal file
162
vendor/yiisoft/yii2/validators/UrlValidator.php
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\helpers\Json;
|
||||
use yii\web\JsExpression;
|
||||
|
||||
/**
|
||||
* UrlValidator validates that the attribute value is a valid http or https URL.
|
||||
*
|
||||
* Note that this validator only checks if the URL scheme and host part are correct.
|
||||
* It does not check the remaining parts of a URL.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class UrlValidator extends Validator
|
||||
{
|
||||
/**
|
||||
* @var string the regular expression used to validate the attribute value.
|
||||
* The pattern may contain a `{schemes}` token that will be replaced
|
||||
* by a regular expression which represents the [[validSchemes]].
|
||||
*/
|
||||
public $pattern = '/^{schemes}:\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(?::\d{1,5})?(?:$|[?\/#])/i';
|
||||
/**
|
||||
* @var array list of URI schemes which should be considered valid. By default, http and https
|
||||
* are considered to be valid schemes.
|
||||
*/
|
||||
public $validSchemes = ['http', 'https'];
|
||||
/**
|
||||
* @var string the default URI scheme. If the input doesn't contain the scheme part, the default
|
||||
* scheme will be prepended to it (thus changing the input). Defaults to null, meaning a URL must
|
||||
* contain the scheme part.
|
||||
*/
|
||||
public $defaultScheme;
|
||||
/**
|
||||
* @var bool whether validation process should take into account IDN (internationalized
|
||||
* domain names). Defaults to false meaning that validation of URLs containing IDN will always
|
||||
* fail. Note that in order to use IDN validation you have to install and enable `intl` PHP
|
||||
* extension, otherwise an exception would be thrown.
|
||||
*/
|
||||
public $enableIDN = false;
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if ($this->enableIDN && !function_exists('idn_to_ascii')) {
|
||||
throw new InvalidConfigException('In order to use IDN validation intl extension must be installed and enabled.');
|
||||
}
|
||||
if ($this->message === null) {
|
||||
$this->message = Yii::t('yii', '{attribute} is not a valid URL.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateAttribute($model, $attribute)
|
||||
{
|
||||
$value = $model->$attribute;
|
||||
$result = $this->validateValue($value);
|
||||
if (!empty($result)) {
|
||||
$this->addError($model, $attribute, $result[0], $result[1]);
|
||||
} elseif ($this->defaultScheme !== null && strpos($value, '://') === false) {
|
||||
$model->$attribute = $this->defaultScheme . '://' . $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function validateValue($value)
|
||||
{
|
||||
// make sure the length is limited to avoid DOS attacks
|
||||
if (is_string($value) && strlen($value) < 2000) {
|
||||
if ($this->defaultScheme !== null && strpos($value, '://') === false) {
|
||||
$value = $this->defaultScheme . '://' . $value;
|
||||
}
|
||||
|
||||
if (strpos($this->pattern, '{schemes}') !== false) {
|
||||
$pattern = str_replace('{schemes}', '(' . implode('|', $this->validSchemes) . ')', $this->pattern);
|
||||
} else {
|
||||
$pattern = $this->pattern;
|
||||
}
|
||||
|
||||
if ($this->enableIDN) {
|
||||
$value = preg_replace_callback('/:\/\/([^\/]+)/', function ($matches) {
|
||||
return '://' . $this->idnToAscii($matches[1]);
|
||||
}, $value);
|
||||
}
|
||||
|
||||
if (preg_match($pattern, $value)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return [$this->message, []];
|
||||
}
|
||||
|
||||
private function idnToAscii($idn)
|
||||
{
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
// TODO: drop old PHP versions support
|
||||
return idn_to_ascii($idn);
|
||||
}
|
||||
|
||||
return idn_to_ascii($idn, 0, INTL_IDNA_VARIANT_UTS46);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clientValidateAttribute($model, $attribute, $view)
|
||||
{
|
||||
ValidationAsset::register($view);
|
||||
if ($this->enableIDN) {
|
||||
PunycodeAsset::register($view);
|
||||
}
|
||||
$options = $this->getClientOptions($model, $attribute);
|
||||
|
||||
return 'yii.validation.url(value, messages, ' . Json::htmlEncode($options) . ');';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClientOptions($model, $attribute)
|
||||
{
|
||||
if (strpos($this->pattern, '{schemes}') !== false) {
|
||||
$pattern = str_replace('{schemes}', '(' . implode('|', $this->validSchemes) . ')', $this->pattern);
|
||||
} else {
|
||||
$pattern = $this->pattern;
|
||||
}
|
||||
|
||||
$options = [
|
||||
'pattern' => new JsExpression($pattern),
|
||||
'message' => $this->formatMessage($this->message, [
|
||||
'attribute' => $model->getAttributeLabel($attribute),
|
||||
]),
|
||||
'enableIDN' => (bool) $this->enableIDN,
|
||||
];
|
||||
if ($this->skipOnEmpty) {
|
||||
$options['skipOnEmpty'] = 1;
|
||||
}
|
||||
if ($this->defaultScheme !== null) {
|
||||
$options['defaultScheme'] = $this->defaultScheme;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
27
vendor/yiisoft/yii2/validators/ValidationAsset.php
vendored
Normal file
27
vendor/yiisoft/yii2/validators/ValidationAsset.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use yii\web\AssetBundle;
|
||||
|
||||
/**
|
||||
* This asset bundle provides the javascript files for client validation.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class ValidationAsset extends AssetBundle
|
||||
{
|
||||
public $sourcePath = '@yii/assets';
|
||||
public $js = [
|
||||
'yii.validation.js',
|
||||
];
|
||||
public $depends = [
|
||||
'yii\web\YiiAsset',
|
||||
];
|
||||
}
|
||||
482
vendor/yiisoft/yii2/validators/Validator.php
vendored
Normal file
482
vendor/yiisoft/yii2/validators/Validator.php
vendored
Normal file
@@ -0,0 +1,482 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\validators;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Component;
|
||||
use yii\base\NotSupportedException;
|
||||
|
||||
/**
|
||||
* Validator is the base class for all validators.
|
||||
*
|
||||
* Child classes should override the [[validateValue()]] and/or [[validateAttribute()]] methods to provide the actual
|
||||
* logic of performing data validation. Child classes may also override [[clientValidateAttribute()]]
|
||||
* to provide client-side validation support.
|
||||
*
|
||||
* Validator declares a set of [[builtInValidators|built-in validators]] which can
|
||||
* be referenced using short names. They are listed as follows:
|
||||
*
|
||||
* - `boolean`: [[BooleanValidator]]
|
||||
* - `captcha`: [[\yii\captcha\CaptchaValidator]]
|
||||
* - `compare`: [[CompareValidator]]
|
||||
* - `date`: [[DateValidator]]
|
||||
* - `datetime`: [[DateValidator]]
|
||||
* - `time`: [[DateValidator]]
|
||||
* - `default`: [[DefaultValueValidator]]
|
||||
* - `double`: [[NumberValidator]]
|
||||
* - `each`: [[EachValidator]]
|
||||
* - `email`: [[EmailValidator]]
|
||||
* - `exist`: [[ExistValidator]]
|
||||
* - `file`: [[FileValidator]]
|
||||
* - `filter`: [[FilterValidator]]
|
||||
* - `image`: [[ImageValidator]]
|
||||
* - `in`: [[RangeValidator]]
|
||||
* - `integer`: [[NumberValidator]]
|
||||
* - `match`: [[RegularExpressionValidator]]
|
||||
* - `required`: [[RequiredValidator]]
|
||||
* - `safe`: [[SafeValidator]]
|
||||
* - `string`: [[StringValidator]]
|
||||
* - `trim`: [[FilterValidator]]
|
||||
* - `unique`: [[UniqueValidator]]
|
||||
* - `url`: [[UrlValidator]]
|
||||
* - `ip`: [[IpValidator]]
|
||||
*
|
||||
* For more details and usage information on Validator, see the [guide article on validators](guide:input-validation).
|
||||
*
|
||||
* @property array $attributeNames Attribute names. This property is read-only.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class Validator extends Component
|
||||
{
|
||||
/**
|
||||
* @var array list of built-in validators (name => class or configuration)
|
||||
*/
|
||||
public static $builtInValidators = [
|
||||
'boolean' => 'yii\validators\BooleanValidator',
|
||||
'captcha' => 'yii\captcha\CaptchaValidator',
|
||||
'compare' => 'yii\validators\CompareValidator',
|
||||
'date' => 'yii\validators\DateValidator',
|
||||
'datetime' => [
|
||||
'class' => 'yii\validators\DateValidator',
|
||||
'type' => DateValidator::TYPE_DATETIME,
|
||||
],
|
||||
'time' => [
|
||||
'class' => 'yii\validators\DateValidator',
|
||||
'type' => DateValidator::TYPE_TIME,
|
||||
],
|
||||
'default' => 'yii\validators\DefaultValueValidator',
|
||||
'double' => 'yii\validators\NumberValidator',
|
||||
'each' => 'yii\validators\EachValidator',
|
||||
'email' => 'yii\validators\EmailValidator',
|
||||
'exist' => 'yii\validators\ExistValidator',
|
||||
'file' => 'yii\validators\FileValidator',
|
||||
'filter' => 'yii\validators\FilterValidator',
|
||||
'image' => 'yii\validators\ImageValidator',
|
||||
'in' => 'yii\validators\RangeValidator',
|
||||
'integer' => [
|
||||
'class' => 'yii\validators\NumberValidator',
|
||||
'integerOnly' => true,
|
||||
],
|
||||
'match' => 'yii\validators\RegularExpressionValidator',
|
||||
'number' => 'yii\validators\NumberValidator',
|
||||
'required' => 'yii\validators\RequiredValidator',
|
||||
'safe' => 'yii\validators\SafeValidator',
|
||||
'string' => 'yii\validators\StringValidator',
|
||||
'trim' => [
|
||||
'class' => 'yii\validators\FilterValidator',
|
||||
'filter' => 'trim',
|
||||
'skipOnArray' => true,
|
||||
],
|
||||
'unique' => 'yii\validators\UniqueValidator',
|
||||
'url' => 'yii\validators\UrlValidator',
|
||||
'ip' => 'yii\validators\IpValidator',
|
||||
];
|
||||
/**
|
||||
* @var array|string attributes to be validated by this validator. For multiple attributes,
|
||||
* please specify them as an array; for single attribute, you may use either a string or an array.
|
||||
*/
|
||||
public $attributes = [];
|
||||
/**
|
||||
* @var string the user-defined error message. It may contain the following placeholders which
|
||||
* will be replaced accordingly by the validator:
|
||||
*
|
||||
* - `{attribute}`: the label of the attribute being validated
|
||||
* - `{value}`: the value of the attribute being validated
|
||||
*
|
||||
* Note that some validators may introduce other properties for error messages used when specific
|
||||
* validation conditions are not met. Please refer to individual class API documentation for details
|
||||
* about these properties. By convention, this property represents the primary error message
|
||||
* used when the most important validation condition is not met.
|
||||
*/
|
||||
public $message;
|
||||
/**
|
||||
* @var array|string scenarios that the validator can be applied to. For multiple scenarios,
|
||||
* please specify them as an array; for single scenario, you may use either a string or an array.
|
||||
*/
|
||||
public $on = [];
|
||||
/**
|
||||
* @var array|string scenarios that the validator should not be applied to. For multiple scenarios,
|
||||
* please specify them as an array; for single scenario, you may use either a string or an array.
|
||||
*/
|
||||
public $except = [];
|
||||
/**
|
||||
* @var bool whether this validation rule should be skipped if the attribute being validated
|
||||
* already has some validation error according to some previous rules. Defaults to true.
|
||||
*/
|
||||
public $skipOnError = true;
|
||||
/**
|
||||
* @var bool whether this validation rule should be skipped if the attribute value
|
||||
* is null or an empty string.
|
||||
*/
|
||||
public $skipOnEmpty = true;
|
||||
/**
|
||||
* @var bool whether to enable client-side validation for this validator.
|
||||
* The actual client-side validation is done via the JavaScript code returned
|
||||
* by [[clientValidateAttribute()]]. If that method returns null, even if this property
|
||||
* is true, no client-side validation will be done by this validator.
|
||||
*/
|
||||
public $enableClientValidation = true;
|
||||
/**
|
||||
* @var callable a PHP callable that replaces the default implementation of [[isEmpty()]].
|
||||
* If not set, [[isEmpty()]] will be used to check if a value is empty. The signature
|
||||
* of the callable should be `function ($value)` which returns a boolean indicating
|
||||
* whether the value is empty.
|
||||
*/
|
||||
public $isEmpty;
|
||||
/**
|
||||
* @var callable a PHP callable whose return value determines whether this validator should be applied.
|
||||
* The signature of the callable should be `function ($model, $attribute)`, where `$model` and `$attribute`
|
||||
* refer to the model and the attribute currently being validated. The callable should return a boolean value.
|
||||
*
|
||||
* This property is mainly provided to support conditional validation on the server-side.
|
||||
* If this property is not set, this validator will be always applied on the server-side.
|
||||
*
|
||||
* The following example will enable the validator only when the country currently selected is USA:
|
||||
*
|
||||
* ```php
|
||||
* function ($model) {
|
||||
* return $model->country == Country::USA;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @see whenClient
|
||||
*/
|
||||
public $when;
|
||||
/**
|
||||
* @var string a JavaScript function name whose return value determines whether this validator should be applied
|
||||
* on the client-side. The signature of the function should be `function (attribute, value)`, where
|
||||
* `attribute` is an object describing the attribute being validated (see [[clientValidateAttribute()]])
|
||||
* and `value` the current value of the attribute.
|
||||
*
|
||||
* This property is mainly provided to support conditional validation on the client-side.
|
||||
* If this property is not set, this validator will be always applied on the client-side.
|
||||
*
|
||||
* The following example will enable the validator only when the country currently selected is USA:
|
||||
*
|
||||
* ```javascript
|
||||
* function (attribute, value) {
|
||||
* return $('#country').val() === 'USA';
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @see when
|
||||
*/
|
||||
public $whenClient;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a validator object.
|
||||
* @param string|\Closure $type the validator type. This can be either:
|
||||
* * a built-in validator name listed in [[builtInValidators]];
|
||||
* * a method name of the model class;
|
||||
* * an anonymous function;
|
||||
* * a validator class name.
|
||||
* @param \yii\base\Model $model the data model to be validated.
|
||||
* @param array|string $attributes list of attributes to be validated. This can be either an array of
|
||||
* the attribute names or a string of comma-separated attribute names.
|
||||
* @param array $params initial values to be applied to the validator properties.
|
||||
* @return Validator the validator
|
||||
*/
|
||||
public static function createValidator($type, $model, $attributes, $params = [])
|
||||
{
|
||||
$params['attributes'] = $attributes;
|
||||
|
||||
if ($type instanceof \Closure || ($model->hasMethod($type) && !isset(static::$builtInValidators[$type]))) {
|
||||
// method-based validator
|
||||
$params['class'] = __NAMESPACE__ . '\InlineValidator';
|
||||
$params['method'] = $type;
|
||||
} else {
|
||||
if (isset(static::$builtInValidators[$type])) {
|
||||
$type = static::$builtInValidators[$type];
|
||||
}
|
||||
if (is_array($type)) {
|
||||
$params = array_merge($type, $params);
|
||||
} else {
|
||||
$params['class'] = $type;
|
||||
}
|
||||
}
|
||||
|
||||
return Yii::createObject($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
$this->attributes = (array) $this->attributes;
|
||||
$this->on = (array) $this->on;
|
||||
$this->except = (array) $this->except;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the specified object.
|
||||
* @param \yii\base\Model $model the data model being validated
|
||||
* @param array|null $attributes the list of attributes to be validated.
|
||||
* Note that if an attribute is not associated with the validator - it will be
|
||||
* ignored. If this parameter is null, every attribute listed in [[attributes]] will be validated.
|
||||
*/
|
||||
public function validateAttributes($model, $attributes = null)
|
||||
{
|
||||
if (is_array($attributes)) {
|
||||
$newAttributes = [];
|
||||
$attributeNames = $this->getAttributeNames();
|
||||
foreach ($attributes as $attribute) {
|
||||
if (in_array($attribute, $attributeNames, true)) {
|
||||
$newAttributes[] = $attribute;
|
||||
}
|
||||
}
|
||||
$attributes = $newAttributes;
|
||||
} else {
|
||||
$attributes = $this->getAttributeNames();
|
||||
}
|
||||
|
||||
foreach ($attributes as $attribute) {
|
||||
$skip = $this->skipOnError && $model->hasErrors($attribute)
|
||||
|| $this->skipOnEmpty && $this->isEmpty($model->$attribute);
|
||||
if (!$skip) {
|
||||
if ($this->when === null || call_user_func($this->when, $model, $attribute)) {
|
||||
$this->validateAttribute($model, $attribute);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a single attribute.
|
||||
* Child classes must implement this method to provide the actual validation logic.
|
||||
* @param \yii\base\Model $model the data model to be validated
|
||||
* @param string $attribute the name of the attribute to be validated.
|
||||
*/
|
||||
public function validateAttribute($model, $attribute)
|
||||
{
|
||||
$result = $this->validateValue($model->$attribute);
|
||||
if (!empty($result)) {
|
||||
$this->addError($model, $attribute, $result[0], $result[1]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a given value.
|
||||
* You may use this method to validate a value out of the context of a data model.
|
||||
* @param mixed $value the data value to be validated.
|
||||
* @param string $error the error message to be returned, if the validation fails.
|
||||
* @return bool whether the data is valid.
|
||||
*/
|
||||
public function validate($value, &$error = null)
|
||||
{
|
||||
$result = $this->validateValue($value);
|
||||
if (empty($result)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
list($message, $params) = $result;
|
||||
$params['attribute'] = Yii::t('yii', 'the input value');
|
||||
if (is_array($value)) {
|
||||
$params['value'] = 'array()';
|
||||
} elseif (is_object($value)) {
|
||||
$params['value'] = 'object';
|
||||
} else {
|
||||
$params['value'] = $value;
|
||||
}
|
||||
$error = $this->formatMessage($message, $params);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a value.
|
||||
* A validator class can implement this method to support data validation out of the context of a data model.
|
||||
* @param mixed $value the data value to be validated.
|
||||
* @return array|null the error message and the array of parameters to be inserted into the error message.
|
||||
* ```php
|
||||
* if (!$valid) {
|
||||
* return [$this->message, [
|
||||
* 'param1' => $this->param1,
|
||||
* 'formattedLimit' => Yii::$app->formatter->asShortSize($this->getSizeLimit()),
|
||||
* 'mimeTypes' => implode(', ', $this->mimeTypes),
|
||||
* 'param4' => 'etc...',
|
||||
* ]];
|
||||
* }
|
||||
*
|
||||
* return null;
|
||||
* ```
|
||||
* for this example `message` template can contain `{param1}`, `{formattedLimit}`, `{mimeTypes}`, `{param4}`
|
||||
*
|
||||
* Null should be returned if the data is valid.
|
||||
* @throws NotSupportedException if the validator does not supporting data validation without a model
|
||||
*/
|
||||
protected function validateValue($value)
|
||||
{
|
||||
throw new NotSupportedException(get_class($this) . ' does not support validateValue().');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JavaScript needed for performing client-side validation.
|
||||
*
|
||||
* Calls [[getClientOptions()]] to generate options array for client-side validation.
|
||||
*
|
||||
* You may override this method to return the JavaScript validation code if
|
||||
* the validator can support client-side validation.
|
||||
*
|
||||
* The following JavaScript variables are predefined and can be used in the validation code:
|
||||
*
|
||||
* - `attribute`: an object describing the the attribute being validated.
|
||||
* - `value`: the value being validated.
|
||||
* - `messages`: an array used to hold the validation error messages for the attribute.
|
||||
* - `deferred`: an array used to hold deferred objects for asynchronous validation
|
||||
* - `$form`: a jQuery object containing the form element
|
||||
*
|
||||
* The `attribute` object contains the following properties:
|
||||
* - `id`: a unique ID identifying the attribute (e.g. "loginform-username") in the form
|
||||
* - `name`: attribute name or expression (e.g. "[0]content" for tabular input)
|
||||
* - `container`: the jQuery selector of the container of the input field
|
||||
* - `input`: the jQuery selector of the input field under the context of the form
|
||||
* - `error`: the jQuery selector of the error tag under the context of the container
|
||||
* - `status`: status of the input field, 0: empty, not entered before, 1: validated, 2: pending validation, 3: validating
|
||||
*
|
||||
* @param \yii\base\Model $model the data model being validated
|
||||
* @param string $attribute the name of the attribute to be validated.
|
||||
* @param \yii\web\View $view the view object that is going to be used to render views or view files
|
||||
* containing a model form with this validator applied.
|
||||
* @return string|null the client-side validation script. Null if the validator does not support
|
||||
* client-side validation.
|
||||
* @see getClientOptions()
|
||||
* @see \yii\widgets\ActiveForm::enableClientValidation
|
||||
*/
|
||||
public function clientValidateAttribute($model, $attribute, $view)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the client-side validation options.
|
||||
* This method is usually called from [[clientValidateAttribute()]]. You may override this method to modify options
|
||||
* that will be passed to the client-side validation.
|
||||
* @param \yii\base\Model $model the model being validated
|
||||
* @param string $attribute the attribute name being validated
|
||||
* @return array the client-side validation options
|
||||
* @since 2.0.11
|
||||
*/
|
||||
public function getClientOptions($model, $attribute)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value indicating whether the validator is active for the given scenario and attribute.
|
||||
*
|
||||
* A validator is active if
|
||||
*
|
||||
* - the validator's `on` property is empty, or
|
||||
* - the validator's `on` property contains the specified scenario
|
||||
*
|
||||
* @param string $scenario scenario name
|
||||
* @return bool whether the validator applies to the specified scenario.
|
||||
*/
|
||||
public function isActive($scenario)
|
||||
{
|
||||
return !in_array($scenario, $this->except, true) && (empty($this->on) || in_array($scenario, $this->on, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error about the specified attribute to the model object.
|
||||
* This is a helper method that performs message selection and internationalization.
|
||||
* @param \yii\base\Model $model the data model being validated
|
||||
* @param string $attribute the attribute being validated
|
||||
* @param string $message the error message
|
||||
* @param array $params values for the placeholders in the error message
|
||||
*/
|
||||
public function addError($model, $attribute, $message, $params = [])
|
||||
{
|
||||
$params['attribute'] = $model->getAttributeLabel($attribute);
|
||||
if (!isset($params['value'])) {
|
||||
$value = $model->$attribute;
|
||||
if (is_array($value)) {
|
||||
$params['value'] = 'array()';
|
||||
} elseif (is_object($value) && !method_exists($value, '__toString')) {
|
||||
$params['value'] = '(object)';
|
||||
} else {
|
||||
$params['value'] = $value;
|
||||
}
|
||||
}
|
||||
$model->addError($attribute, $this->formatMessage($message, $params));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given value is empty.
|
||||
* A value is considered empty if it is null, an empty array, or an empty string.
|
||||
* Note that this method is different from PHP empty(). It will return false when the value is 0.
|
||||
* @param mixed $value the value to be checked
|
||||
* @return bool whether the value is empty
|
||||
*/
|
||||
public function isEmpty($value)
|
||||
{
|
||||
if ($this->isEmpty !== null) {
|
||||
return call_user_func($this->isEmpty, $value);
|
||||
}
|
||||
|
||||
return $value === null || $value === [] || $value === '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a mesage using the I18N, or simple strtr if `\Yii::$app` is not available.
|
||||
* @param string $message
|
||||
* @param array $params
|
||||
* @since 2.0.12
|
||||
* @return string
|
||||
*/
|
||||
protected function formatMessage($message, $params)
|
||||
{
|
||||
if (Yii::$app !== null) {
|
||||
return \Yii::$app->getI18n()->format($message, $params, Yii::$app->language);
|
||||
}
|
||||
|
||||
$placeholders = [];
|
||||
foreach ((array) $params as $name => $value) {
|
||||
$placeholders['{' . $name . '}'] = $value;
|
||||
}
|
||||
|
||||
return ($placeholders === []) ? $message : strtr($message, $placeholders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns cleaned attribute names without the `!` character at the beginning.
|
||||
* @return array attribute names.
|
||||
* @since 2.0.12
|
||||
*/
|
||||
public function getAttributeNames()
|
||||
{
|
||||
return array_map(function ($attribute) {
|
||||
return ltrim($attribute, '!');
|
||||
}, $this->attributes);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user