|  |  | @ -10,6 +10,8 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | namespace yii\base; |  |  |  | namespace yii\base; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | use yii\util\StringHelper; |  |  |  | use yii\util\StringHelper; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | use yii\validators\Validator; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | use yii\validators\RequiredValidator; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /** |  |  |  | /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  * Model is the base class for data models. |  |  |  |  * Model is the base class for data models. | 
			
		
	
	
		
		
			
				
					|  |  | @ -35,7 +37,6 @@ use yii\util\StringHelper; | 
			
		
	
		
		
			
				
					
					|  |  |  |  * @property array $errors Errors for all attributes or the specified attribute. Empty array is returned if no error. |  |  |  |  * @property array $errors Errors for all attributes or the specified attribute. Empty array is returned if no error. | 
			
		
	
		
		
			
				
					
					|  |  |  |  * @property array $attributes Attribute values (name=>value). |  |  |  |  * @property array $attributes Attribute values (name=>value). | 
			
		
	
		
		
			
				
					
					|  |  |  |  * @property string $scenario The scenario that this model is in. |  |  |  |  * @property string $scenario The scenario that this model is in. | 
			
		
	
		
		
			
				
					
					|  |  |  |  * @property array $safeAttributeNames Safe attribute names in the current [[scenario]]. |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  * |  |  |  |  * | 
			
		
	
		
		
			
				
					
					|  |  |  |  * @event ModelEvent beforeValidate an event raised at the beginning of [[validate()]]. You may set |  |  |  |  * @event ModelEvent beforeValidate an event raised at the beginning of [[validate()]]. You may set | 
			
		
	
		
		
			
				
					
					|  |  |  |  * [[ModelEvent::isValid]] to be false to stop the validation. |  |  |  |  * [[ModelEvent::isValid]] to be false to stop the validation. | 
			
		
	
	
		
		
			
				
					|  |  | @ -48,43 +49,8 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess | 
			
		
	
		
		
			
				
					
					|  |  |  | { |  |  |  | { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	private static $_attributes = array(); // class name => array of attribute names |  |  |  | 	private static $_attributes = array(); // class name => array of attribute names | 
			
		
	
		
		
			
				
					
					|  |  |  | 	private $_errors; // attribute name => array of errors |  |  |  | 	private $_errors; // attribute name => array of errors | 
			
		
	
		
		
			
				
					
					|  |  |  | 	private $_validators; // validators |  |  |  | 	private $_validators; // Vector of validators | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	private $_scenario; // scenario |  |  |  | 	private $_scenario = 'default'; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	/** |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Constructor. |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * @param string|null $scenario name of the [[scenario]] that this model is used in. |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * @param array $config name-value pairs that will be used to initialize the object properties |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	public function __construct($scenario = null, $config = array()) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	{ |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		$this->_scenario = $scenario; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		parent::__construct($config); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	/** |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Returns the list of attribute names. |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * By default, this method returns all public non-static properties of the class. |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * You may override this method to change the default behavior. |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * @return array list of attribute names. |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	public function attributeNames() |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	{ |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		$className = get_class($this); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (isset(self::$_attributes[$className])) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			return self::$_attributes[$className]; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		$class = new \ReflectionClass($this); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		$names = array(); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			$name = $property->getName(); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if (!$property->isStatic()) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				$names[] = $name; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return self::$_attributes[$className] = $names; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	/** |  |  |  | 	/** | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Returns the validation rules for attributes. |  |  |  | 	 * Returns the validation rules for attributes. | 
			
		
	
	
		
		
			
				
					|  |  | @ -107,7 +73,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * |  |  |  | 	 * | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 *  - attribute list: required, specifies the attributes (separated by commas) to be validated; |  |  |  | 	 *  - attribute list: required, specifies the attributes (separated by commas) to be validated; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 *  - validator type: required, specifies the validator to be used. It can be the name of a model |  |  |  | 	 *  - validator type: required, specifies the validator to be used. It can be the name of a model | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 *	class method, the name of a built-in validator, or a validator class (or its path alias). |  |  |  | 	 *	class method, the name of a built-in validator, or a validator class name (or its path alias). | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	 *  - on: optional, specifies the [[scenario|scenarios]] (separated by commas) when the validation |  |  |  | 	 *  - on: optional, specifies the [[scenario|scenarios]] (separated by commas) when the validation | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 *	rule can be applied. If this option is not set, the rule will apply to all scenarios. |  |  |  | 	 *	rule can be applied. If this option is not set, the rule will apply to all scenarios. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 *  - additional name-value pairs can be specified to initialize the corresponding validator properties. |  |  |  | 	 *  - additional name-value pairs can be specified to initialize the corresponding validator properties. | 
			
		
	
	
		
		
			
				
					|  |  | @ -145,6 +111,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * merge the parent rules with child rules using functions such as `array_merge()`. |  |  |  | 	 * merge the parent rules with child rules using functions such as `array_merge()`. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * |  |  |  | 	 * | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * @return array validation rules |  |  |  | 	 * @return array validation rules | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * @see scenarios | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	public function rules() |  |  |  | 	public function rules() | 
			
		
	
		
		
			
				
					
					|  |  |  | 	{ |  |  |  | 	{ | 
			
		
	
	
		
		
			
				
					|  |  | @ -152,6 +119,56 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	/** |  |  |  | 	/** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * Returns a list of scenarios and the corresponding relevant attributes. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * The returned array should be in the following format: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * ~~~ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * array( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 *     'scenario1' => array('attribute11', 'attribute12', ...), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 *     'scenario2' => array('attribute21', 'attribute22', ...), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 *     ... | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * ) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * ~~~ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * Attributes relevant to the current scenario are considered safe and can be | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * massively assigned. When [[validate()]] is invoked, these attributes will | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * be validated using the rules declared in [[rules()]]. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * If an attribute should NOT be massively assigned (thus considered unsafe), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * please prefix the attribute with an exclamation character (e.g. '!attribute'). | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * @return array a list of scenarios and the corresponding relevant attributes. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	public function scenarios() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	{ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		return array(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	/** | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * Returns the list of attribute names. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * By default, this method returns all public non-static properties of the class. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * You may override this method to change the default behavior. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * @return array list of attribute names. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	public function attributes() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	{ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		$className = get_class($this); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (isset(self::$_attributes[$className])) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			return self::$_attributes[$className]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		$class = new \ReflectionClass($this); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		$names = array(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			$name = $property->getName(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			if (!$property->isStatic()) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				$names[] = $name; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		return self::$_attributes[$className] = $names; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	/** | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Returns the attribute labels. |  |  |  | 	 * Returns the attribute labels. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * |  |  |  | 	 * | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Attribute labels are mainly used for display purpose. For example, given an attribute |  |  |  | 	 * Attribute labels are mainly used for display purpose. For example, given an attribute | 
			
		
	
	
		
		
			
				
					|  |  | @ -175,30 +192,33 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess | 
			
		
	
		
		
			
				
					
					|  |  |  | 	/** |  |  |  | 	/** | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Performs the data validation. |  |  |  | 	 * Performs the data validation. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * |  |  |  | 	 * | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * This method executes the validation rules as declared in [[rules()]]. |  |  |  | 	 * This method executes the validation rules applicable to the current [[scenario]]. | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Only the rules applicable to the current [[scenario]] will be executed. |  |  |  | 	 * The following criteria are used to determine whether a rule is currently applicable: | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	 * A rule is considered applicable to a scenario if its `on` option is not set |  |  |  | 	 * | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	 * or contains the scenario. |  |  |  | 	 * - the rule must be associated with the attributes relevant to the current scenario; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * - the rules must be effective for the current scenario. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * |  |  |  | 	 * | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * This method will call [[beforeValidate()]] and [[afterValidate()]] before and |  |  |  | 	 * This method will call [[beforeValidate()]] and [[afterValidate()]] before and | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * after actual validation, respectively. If [[beforeValidate()]] returns false, |  |  |  | 	 * after the actual validation, respectively. If [[beforeValidate()]] returns false, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	 * the validation and [[afterValidate()]] will be cancelled. |  |  |  | 	 * the validation will be cancelled and [[afterValidate()]] will not be called. | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	 * |  |  |  | 	 * | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Errors found during the validation can be retrieved via [[getErrors()]]. |  |  |  | 	 * Errors found during the validation can be retrieved via [[getErrors()]] | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * and [[getError()]]. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * |  |  |  | 	 * | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * @param array $attributes list of attributes that should be validated. |  |  |  | 	 * @param array $attributes list of attributes that should be validated. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * If this parameter is empty, it means any attribute listed in the applicable |  |  |  | 	 * If this parameter is empty, it means any attribute listed in the applicable | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * validation rules should be validated. |  |  |  | 	 * validation rules should be validated. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * @param boolean $clearErrors whether to call [[clearErrors()]] before performing validation |  |  |  | 	 * @param boolean $clearErrors whether to call [[clearErrors()]] before performing validation | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * @return boolean whether the validation is successful without any error. |  |  |  | 	 * @return boolean whether the validation is successful without any error. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * @see beforeValidate() |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * @see afterValidate() |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	public function validate($attributes = null, $clearErrors = true) |  |  |  | 	public function validate($attributes = null, $clearErrors = true) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	{ |  |  |  | 	{ | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if ($clearErrors) { |  |  |  | 		if ($clearErrors) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 			$this->clearErrors(); |  |  |  | 			$this->clearErrors(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if ($attributes === null) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			$attributes = $this->activeAttributes(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if ($this->beforeValidate()) { |  |  |  | 		if ($this->beforeValidate()) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 			foreach ($this->getActiveValidators() as $validator) { |  |  |  | 			foreach ($this->getActiveValidators() as $validator) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 				$validator->validate($this, $attributes); |  |  |  | 				$validator->validate($this, $attributes); | 
			
		
	
	
		
		
			
				
					|  |  | @ -214,7 +234,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * The default implementation raises a `beforeValidate` event. |  |  |  | 	 * The default implementation raises a `beforeValidate` event. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * You may override this method to do preliminary checks before validation. |  |  |  | 	 * You may override this method to do preliminary checks before validation. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Make sure the parent implementation is invoked so that the event can be raised. |  |  |  | 	 * Make sure the parent implementation is invoked so that the event can be raised. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * @return boolean whether validation should be executed. Defaults to true. |  |  |  | 	 * @return boolean whether the validation should be executed. Defaults to true. | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	 * If false is returned, the validation will stop and the model is considered invalid. |  |  |  | 	 * If false is returned, the validation will stop and the model is considered invalid. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	public function beforeValidate() |  |  |  | 	public function beforeValidate() | 
			
		
	
	
		
		
			
				
					|  |  | @ -269,8 +289,9 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess | 
			
		
	
		
		
			
				
					
					|  |  |  | 	{ |  |  |  | 	{ | 
			
		
	
		
		
			
				
					
					|  |  |  | 		$validators = array(); |  |  |  | 		$validators = array(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		$scenario = $this->getScenario(); |  |  |  | 		$scenario = $this->getScenario(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		/** @var $validator Validator */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 		foreach ($this->getValidators() as $validator) { |  |  |  | 		foreach ($this->getValidators() as $validator) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if ($validator->applyTo($scenario, $attribute)) { |  |  |  | 			if ($validator->isActive($scenario, $attribute)) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 				$validators[] = $validator; |  |  |  | 				$validators[] = $validator; | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  | 			} | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
	
		
		
			
				
					|  |  | @ -287,8 +308,10 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess | 
			
		
	
		
		
			
				
					
					|  |  |  | 	{ |  |  |  | 	{ | 
			
		
	
		
		
			
				
					
					|  |  |  | 		$validators = new Vector; |  |  |  | 		$validators = new Vector; | 
			
		
	
		
		
			
				
					
					|  |  |  | 		foreach ($this->rules() as $rule) { |  |  |  | 		foreach ($this->rules() as $rule) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if (isset($rule[0], $rule[1])) { // attributes, validator type |  |  |  | 			if ($rule instanceof Validator) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				$validator = \yii\validators\Validator::createValidator($rule[1], $this, $rule[0], array_slice($rule, 2)); |  |  |  | 				$validators->add($rule); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			} elseif (isset($rule[0], $rule[1])) { // attributes, validator type | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				$validator = Validator::createValidator($rule[1], $this, $rule[0], array_slice($rule, 2)); | 
			
		
	
		
		
			
				
					
					|  |  |  | 				$validators->add($validator); |  |  |  | 				$validators->add($validator); | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} else { |  |  |  | 			} else { | 
			
		
	
		
		
			
				
					
					|  |  |  | 				throw new BadConfigException('Invalid validation rule: a rule must specify both attribute names and validator type.'); |  |  |  | 				throw new BadConfigException('Invalid validation rule: a rule must specify both attribute names and validator type.'); | 
			
		
	
	
		
		
			
				
					|  |  | @ -308,7 +331,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess | 
			
		
	
		
		
			
				
					
					|  |  |  | 	public function isAttributeRequired($attribute) |  |  |  | 	public function isAttributeRequired($attribute) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	{ |  |  |  | 	{ | 
			
		
	
		
		
			
				
					
					|  |  |  | 		foreach ($this->getActiveValidators($attribute) as $validator) { |  |  |  | 		foreach ($this->getActiveValidators($attribute) as $validator) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if ($validator instanceof \yii\validators\RequiredValidator) { |  |  |  | 			if ($validator instanceof RequiredValidator) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 				return true; |  |  |  | 				return true; | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  | 			} | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
	
		
		
			
				
					|  |  | @ -322,13 +345,8 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	public function isAttributeSafe($attribute) |  |  |  | 	public function isAttributeSafe($attribute) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	{ |  |  |  | 	{ | 
			
		
	
		
		
			
				
					
					|  |  |  | 		$validators = $this->getActiveValidators($attribute); |  |  |  | 		$scenarios = $this->scenarios(); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		foreach ($validators as $validator) { |  |  |  | 		return in_array($attribute, $scenarios[$this->getScenario()], true); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			if (!$validator->safe) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				return false; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return $validators !== array(); |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	/** |  |  |  | 	/** | 
			
		
	
	
		
		
			
				
					|  |  | @ -346,7 +364,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	/** |  |  |  | 	/** | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Returns a value indicating whether there is any validation error. |  |  |  | 	 * Returns a value indicating whether there is any validation error. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * @param string $attribute attribute name. Use null to check all attributes. |  |  |  | 	 * @param string|null $attribute attribute name. Use null to check all attributes. | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	 * @return boolean whether there is any error. |  |  |  | 	 * @return boolean whether there is any error. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	public function hasErrors($attribute = null) |  |  |  | 	public function hasErrors($attribute = null) | 
			
		
	
	
		
		
			
				
					|  |  | @ -452,7 +470,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess | 
			
		
	
		
		
			
				
					
					|  |  |  | 	/** |  |  |  | 	/** | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Returns attribute values. |  |  |  | 	 * Returns attribute values. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * @param array $names list of attributes whose value needs to be returned. |  |  |  | 	 * @param array $names list of attributes whose value needs to be returned. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Defaults to null, meaning all attributes listed in [[attributeNames()]] will be returned. |  |  |  | 	 * Defaults to null, meaning all attributes listed in [[attributes()]] will be returned. | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	 * If it is an array, only the attributes in the array will be returned. |  |  |  | 	 * If it is an array, only the attributes in the array will be returned. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * @return array attribute values (name=>value). |  |  |  | 	 * @return array attribute values (name=>value). | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  | 	 */ | 
			
		
	
	
		
		
			
				
					|  |  | @ -461,13 +479,13 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess | 
			
		
	
		
		
			
				
					
					|  |  |  | 		$values = array(); |  |  |  | 		$values = array(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (is_array($names)) { |  |  |  | 		if (is_array($names)) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 			foreach ($this->attributeNames() as $name) { |  |  |  | 			foreach ($this->attributes() as $name) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 				if (in_array($name, $names, true)) { |  |  |  | 				if (in_array($name, $names, true)) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 					$values[$name] = $this->$name; |  |  |  | 					$values[$name] = $this->$name; | 
			
		
	
		
		
			
				
					
					|  |  |  | 				} |  |  |  | 				} | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  | 			} | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} else { |  |  |  | 		} else { | 
			
		
	
		
		
			
				
					
					|  |  |  | 			foreach ($this->attributeNames() as $name) { |  |  |  | 			foreach ($this->attributes() as $name) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 				$values[$name] = $this->$name; |  |  |  | 				$values[$name] = $this->$name; | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  | 			} | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
	
		
		
			
				
					|  |  | @ -480,13 +498,13 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * @param array $values attribute values (name=>value) to be assigned to the model. |  |  |  | 	 * @param array $values attribute values (name=>value) to be assigned to the model. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * @param boolean $safeOnly whether the assignments should only be done to the safe attributes. |  |  |  | 	 * @param boolean $safeOnly whether the assignments should only be done to the safe attributes. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * A safe attribute is one that is associated with a validation rule in the current [[scenario]]. |  |  |  | 	 * A safe attribute is one that is associated with a validation rule in the current [[scenario]]. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * @see getSafeAttributeNames |  |  |  | 	 * @see safeAttributes() | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	 * @see attributeNames |  |  |  | 	 * @see attributes() | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	public function setAttributes($values, $safeOnly = true) |  |  |  | 	public function setAttributes($values, $safeOnly = true) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	{ |  |  |  | 	{ | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (is_array($values)) { |  |  |  | 		if (is_array($values)) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 			$attributes = array_flip($safeOnly ? $this->getSafeAttributeNames() : $this->attributeNames()); |  |  |  | 			$attributes = array_flip($safeOnly ? $this->safeAttributes() : $this->attributes()); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 			foreach ($values as $name => $value) { |  |  |  | 			foreach ($values as $name => $value) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 				if (isset($attributes[$name])) { |  |  |  | 				if (isset($attributes[$name])) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 					$this->$name = $value; |  |  |  | 					$this->$name = $value; | 
			
		
	
	
		
		
			
				
					|  |  | @ -517,15 +535,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Scenario affects how validation is performed and which attributes can |  |  |  | 	 * Scenario affects how validation is performed and which attributes can | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * be massively assigned. |  |  |  | 	 * be massively assigned. | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * |  |  |  | 	 * | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * A validation rule will be performed when calling [[validate()]] |  |  |  | 	 * @return string the scenario that this model is in. Defaults to 'default'. | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	 * if its 'on' option is not set or contains the current scenario value. |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * And an attribute can be massively assigned if it is associated with |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * a validation rule for the current scenario. An exception is |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * the [[\yii\validators\UnsafeValidator|unsafe]] validator which marks |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * the associated attributes as unsafe and not allowed to be massively assigned. |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * @return string the scenario that this model is in. |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	public function getScenario() |  |  |  | 	public function getScenario() | 
			
		
	
		
		
			
				
					
					|  |  |  | 	{ |  |  |  | 	{ | 
			
		
	
	
		
		
			
				
					|  |  | @ -543,30 +553,35 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	/** |  |  |  | 	/** | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 * Returns the attribute names that are safe to be massively assigned. |  |  |  | 	 * Returns the attribute names that are safe to be massively assigned in the current scenario. | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	 * A safe attribute is one that is associated with a validation rule in the current [[scenario]]. |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	 * @return array safe attribute names |  |  |  | 	 * @return array safe attribute names | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	public function getSafeAttributeNames() |  |  |  | 	public function safeAttributes() | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	{ |  |  |  | 	{ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		$scenarios = $this->scenarios(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		$attributes = array(); |  |  |  | 		$attributes = array(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		$unsafe = array(); |  |  |  | 		foreach ($scenarios[$this->getScenario()] as $attribute) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		foreach ($this->getActiveValidators() as $validator) { |  |  |  | 			if ($attribute[0] !== '!') { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			if (!$validator->safe) { |  |  |  | 				$attributes[] = $attribute; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				foreach ($validator->attributes as $name) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 					$unsafe[] = $name; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				} |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			} else { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				foreach ($validator->attributes as $name) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 					$attributes[$name] = true; |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 			} |  |  |  | 			} | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		return $attributes; | 
			
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		foreach ($unsafe as $name) { |  |  |  | 	/** | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			unset($attributes[$name]); |  |  |  | 	 * Returns the attribute names that are subject to validation in the current scenario. | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 * @return array safe attribute names | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	public function activeAttributes() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	{ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		$scenarios = $this->scenarios(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		$attributes = $scenarios[$this->getScenario()]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		foreach ($attributes as $i => $attribute) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			if ($attribute[0] === '!') { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				$attributes[$i] = substr($attribute, 1); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			} | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  | 		return array_keys($attributes); |  |  |  | 		return $attributes; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	} |  |  |  | 	} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	/** |  |  |  | 	/** | 
			
		
	
	
		
		
			
				
					|  |  | 
 |