Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yii2
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PSDI Army
yii2
Commits
da786f65
Commit
da786f65
authored
Nov 09, 2012
by
Qiang Xue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented new rules and safe attributes
parent
fbcf6776
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
120 additions
and
111 deletions
+120
-111
Model.php
framework/base/Model.php
+106
-91
ActiveRecord.php
framework/db/ar/ActiveRecord.php
+4
-4
Validator.php
framework/validators/Validator.php
+9
-15
Sort.php
framework/web/Sort.php
+1
-1
No files found.
framework/base/Model.php
View file @
da786f65
...
...
@@ -10,6 +10,8 @@
namespace
yii\base
;
use
yii\util\StringHelper
;
use
yii\validators\Validator
;
use
yii\validators\RequiredValidator
;
/**
* 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 $attributes Attribute values (name=>value).
* @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
* [[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
$_errors
;
// attribute name => array of errors
private
$_validators
;
// validators
private
$_scenario
;
// scenario
/**
* 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
;
}
private
$_validators
;
// Vector of validators
private
$_scenario
=
'default'
;
/**
* 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;
* - 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
* 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.
...
...
@@ -145,6 +111,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
* merge the parent rules with child rules using functions such as `array_merge()`.
*
* @return array validation rules
* @see scenarios
*/
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.
*
* 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.
*
* This method executes the validation rules as declared in [[rules()]].
* Only the rules applicable to the current [[scenario]] will be executed.
* A rule is considered applicable to a scenario if its `on` option is not set
* or contains the scenario.
* This method executes the validation rules applicable to the current [[scenario]].
* The following criteria are used to determine whether a rule is currently applicable:
*
* - 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
* after actual validation, respectively. If [[beforeValidate()]] returns false,
* the validation
and [[afterValidate()]] will be cance
lled.
* after
the
actual validation, respectively. If [[beforeValidate()]] returns false,
* the validation
will be cancelled and [[afterValidate()]] will not be ca
lled.
*
* 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.
* If this parameter is empty, it means any attribute listed in the applicable
* validation rules should be validated.
* @param boolean $clearErrors whether to call [[clearErrors()]] before performing validation
* @return boolean whether the validation is successful without any error.
* @see beforeValidate()
* @see afterValidate()
*/
public
function
validate
(
$attributes
=
null
,
$clearErrors
=
true
)
{
if
(
$clearErrors
)
{
$this
->
clearErrors
();
}
if
(
$attributes
===
null
)
{
$attributes
=
$this
->
activeAttributes
();
}
if
(
$this
->
beforeValidate
())
{
foreach
(
$this
->
getActiveValidators
()
as
$validator
)
{
$validator
->
validate
(
$this
,
$attributes
);
...
...
@@ -214,7 +234,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
* The default implementation raises a `beforeValidate` event.
* 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.
* @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.
*/
public
function
beforeValidate
()
...
...
@@ -269,8 +289,9 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
{
$validators
=
array
();
$scenario
=
$this
->
getScenario
();
/** @var $validator Validator */
foreach
(
$this
->
getValidators
()
as
$validator
)
{
if
(
$validator
->
applyTo
(
$scenario
,
$attribute
))
{
if
(
$validator
->
isActive
(
$scenario
,
$attribute
))
{
$validators
[]
=
$validator
;
}
}
...
...
@@ -287,8 +308,10 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
{
$validators
=
new
Vector
;
foreach
(
$this
->
rules
()
as
$rule
)
{
if
(
isset
(
$rule
[
0
],
$rule
[
1
]))
{
// attributes, validator type
$validator
=
\yii\validators\Validator
::
createValidator
(
$rule
[
1
],
$this
,
$rule
[
0
],
array_slice
(
$rule
,
2
));
if
(
$rule
instanceof
Validator
)
{
$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
);
}
else
{
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
)
{
foreach
(
$this
->
getActiveValidators
(
$attribute
)
as
$validator
)
{
if
(
$validator
instanceof
\yii\validators\
RequiredValidator
)
{
if
(
$validator
instanceof
RequiredValidator
)
{
return
true
;
}
}
...
...
@@ -322,13 +345,8 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
*/
public
function
isAttributeSafe
(
$attribute
)
{
$validators
=
$this
->
getActiveValidators
(
$attribute
);
foreach
(
$validators
as
$validator
)
{
if
(
!
$validator
->
safe
)
{
return
false
;
}
}
return
$validators
!==
array
();
$scenarios
=
$this
->
scenarios
();
return
in_array
(
$attribute
,
$scenarios
[
$this
->
getScenario
()],
true
);
}
/**
...
...
@@ -346,7 +364,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
/**
* 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.
*/
public
function
hasErrors
(
$attribute
=
null
)
...
...
@@ -452,7 +470,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
/**
* Returns attribute values.
* @param array $names list of attributes whose value needs to be returned.
* Defaults to null, meaning all attributes listed in [[attribute
Name
s()]] 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.
* @return array attribute values (name=>value).
*/
...
...
@@ -461,13 +479,13 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
$values
=
array
();
if
(
is_array
(
$names
))
{
foreach
(
$this
->
attribute
Name
s
()
as
$name
)
{
foreach
(
$this
->
attributes
()
as
$name
)
{
if
(
in_array
(
$name
,
$names
,
true
))
{
$values
[
$name
]
=
$this
->
$name
;
}
}
}
else
{
foreach
(
$this
->
attribute
Name
s
()
as
$name
)
{
foreach
(
$this
->
attributes
()
as
$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 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]].
* @see
getSafeAttributeNames
* @see attribute
Names
* @see
safeAttributes()
* @see attribute
s()
*/
public
function
setAttributes
(
$values
,
$safeOnly
=
true
)
{
if
(
is_array
(
$values
))
{
$attributes
=
array_flip
(
$safeOnly
?
$this
->
getSafeAttributeNames
()
:
$this
->
attributeNam
es
());
$attributes
=
array_flip
(
$safeOnly
?
$this
->
safeAttributes
()
:
$this
->
attribut
es
());
foreach
(
$values
as
$name
=>
$value
)
{
if
(
isset
(
$attributes
[
$name
]))
{
$this
->
$name
=
$value
;
...
...
@@ -517,15 +535,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess
* Scenario affects how validation is performed and which attributes can
* be massively assigned.
*
* A validation rule will be performed when calling [[validate()]]
* 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.
* @return string the scenario that this model is in. Defaults to 'default'.
*/
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.
* A safe attribute is one that is associated with a validation rule in the current [[scenario]].
* Returns the attribute names that are safe to be massively assigned in the current scenario.
* @return array safe attribute names
*/
public
function
getSafeAttributeNam
es
()
public
function
safeAttribut
es
()
{
$scenarios
=
$this
->
scenarios
();
$attributes
=
array
();
$unsafe
=
array
();
foreach
(
$this
->
getActiveValidators
()
as
$validator
)
{
if
(
!
$validator
->
safe
)
{
foreach
(
$validator
->
attributes
as
$name
)
{
$unsafe
[]
=
$name
;
}
}
else
{
foreach
(
$validator
->
attributes
as
$name
)
{
$attributes
[
$name
]
=
true
;
foreach
(
$scenarios
[
$this
->
getScenario
()]
as
$attribute
)
{
if
(
$attribute
[
0
]
!==
'!'
)
{
$attributes
[]
=
$attribute
;
}
}
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
;
}
/**
...
...
framework/db/ar/ActiveRecord.php
View file @
da786f65
...
...
@@ -588,7 +588,7 @@ abstract class ActiveRecord extends Model
* This would return all column names of the table associated with this AR class.
* @return array list of attribute names.
*/
public
function
attribute
Name
s
()
public
function
attributes
()
{
return
array_keys
(
$this
->
getMetaData
()
->
table
->
columns
);
}
...
...
@@ -633,7 +633,7 @@ abstract class ActiveRecord extends Model
public
function
getAttributes
(
$names
=
null
)
{
if
(
$names
===
null
)
{
$names
=
$this
->
attribute
Name
s
();
$names
=
$this
->
attributes
();
}
$values
=
array
();
foreach
(
$names
as
$name
)
{
...
...
@@ -645,7 +645,7 @@ abstract class ActiveRecord extends Model
public
function
getChangedAttributes
(
$names
=
null
)
{
if
(
$names
===
null
)
{
$names
=
$this
->
attribute
Name
s
();
$names
=
$this
->
attributes
();
}
$names
=
array_flip
(
$names
);
$attributes
=
array
();
...
...
@@ -931,7 +931,7 @@ abstract class ActiveRecord extends Model
return
false
;
}
if
(
$attributes
===
null
)
{
foreach
(
$this
->
attribute
Name
s
()
as
$name
)
{
foreach
(
$this
->
attributes
()
as
$name
)
{
$this
->
_attributes
[
$name
]
=
$record
->
_attributes
[
$name
];
}
$this
->
_oldAttributes
=
$this
->
_attributes
;
...
...
framework/validators/Validator.php
View file @
da786f65
...
...
@@ -42,8 +42,6 @@ namespace yii\validators;
* - `captcha`: [[CaptchaValidator]]
* - `default`: [[DefaultValueValidator]]
* - `exist`: [[ExistValidator]]
* - `safe`: [[SafeValidator]]
* - `unsafe`: [[UnsafeValidator]]
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
...
...
@@ -58,8 +56,6 @@ abstract class Validator extends \yii\base\Component
'match'
=>
'\yii\validators\RegularExpressionValidator'
,
'email'
=>
'\yii\validators\EmailValidator'
,
'url'
=>
'\yii\validators\UrlValidator'
,
'safe'
=>
'\yii\validators\SafeValidator'
,
'unsafe'
=>
'\yii\validators\UnsafeValidator'
,
'filter'
=>
'\yii\validators\FilterValidator'
,
'captcha'
=>
'\yii\validators\CaptchaValidator'
,
'default'
=>
'\yii\validators\DefaultValueValidator'
,
...
...
@@ -103,11 +99,6 @@ abstract class Validator extends \yii\base\Component
*/
public
$skipOnError
=
true
;
/**
* @var boolean whether attributes listed with this validator should be considered safe for
* massive assignment. Defaults to true.
*/
public
$safe
=
true
;
/**
* @var boolean whether to enable client-side validation. Defaults to true.
* Please refer to [[\yii\web\ActiveForm::enableClientValidation]] for more details about
* client-side validation.
...
...
@@ -187,8 +178,10 @@ abstract class Validator extends \yii\base\Component
/**
* Validates the specified object.
* @param \yii\base\Model $object the data object being validated
* @param array $attributes the list of attributes to be validated. Defaults to null,
* meaning every attribute listed in [[attributes]] will be 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
validate
(
$object
,
$attributes
=
null
)
{
...
...
@@ -228,10 +221,11 @@ abstract class Validator extends \yii\base\Component
}
/**
* Returns a value indicating whether the validator applies to the specified scenario.
* A validator applies to a scenario as long as any of the following conditions is met:
* 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
* - the validator's `on` property is empty
, or
* - the validator's `on` property contains the specified scenario
*
* @param string $scenario scenario name
...
...
@@ -239,7 +233,7 @@ abstract class Validator extends \yii\base\Component
* the method will also check if the attribute appears in [[attributes]].
* @return boolean whether the validator applies to the specified scenario.
*/
public
function
applyTo
(
$scenario
,
$attribute
=
null
)
public
function
isActive
(
$scenario
,
$attribute
=
null
)
{
$applies
=
!
isset
(
$this
->
except
[
$scenario
])
&&
(
empty
(
$this
->
on
)
||
isset
(
$this
->
on
[
$scenario
]));
return
$attribute
===
null
?
$applies
:
$applies
&&
in_array
(
$attribute
,
$this
->
attributes
,
true
);
...
...
framework/web/Sort.php
View file @
da786f65
...
...
@@ -429,7 +429,7 @@ class CSort extends CComponent
$attributes
=
$this
->
attributes
;
}
else
{
if
(
$this
->
modelClass
!==
null
)
{
$attributes
=
CActiveRecord
::
model
(
$this
->
modelClass
)
->
attribute
Name
s
();
$attributes
=
CActiveRecord
::
model
(
$this
->
modelClass
)
->
attributes
();
}
else
{
return
false
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment