1: <?php
2: /**
3: * CCompareValidator class file.
4: *
5: * @author Qiang Xue <qiang.xue@gmail.com>
6: * @link http://www.yiiframework.com/
7: * @copyright 2008-2013 Yii Software LLC
8: * @license http://www.yiiframework.com/license/
9: */
10:
11: /**
12: * CCompareValidator compares the specified attribute value with another value and validates if they are equal.
13: *
14: * The value being compared with can be another attribute value
15: * (specified via {@link compareAttribute}) or a constant (specified via
16: * {@link compareValue}. When both are specified, the latter takes
17: * precedence. If neither is specified, the attribute will be compared
18: * with another attribute whose name is by appending "_repeat" to the source
19: * attribute name.
20: *
21: * The comparison can be either {@link strict} or not.
22: *
23: * CCompareValidator supports different comparison operators.
24: * Previously, it only compares to see if two values are equal or not.
25: *
26: * When using the {@link message} property to define a custom error message, the message
27: * may contain additional placeholders that will be replaced with the actual content. In addition
28: * to the "{attribute}" placeholder, recognized by all validators (see {@link CValidator}),
29: * CCompareValidator allows for the following placeholders to be specified:
30: * <ul>
31: * <li>{compareValue}: replaced with the constant value being compared with ({@link compareValue}).</li>
32: * <li>{compareAttribute}: replaced with the label of the attribute being compared with ({@link compareAttribute}).</li>
33: * </ul>
34: *
35: * @author Qiang Xue <qiang.xue@gmail.com>
36: * @package system.validators
37: * @since 1.0
38: */
39: class CCompareValidator extends CValidator
40: {
41: /**
42: * @var string the name of the attribute to be compared with
43: */
44: public $compareAttribute;
45: /**
46: * @var string the constant value to be compared with
47: */
48: public $compareValue;
49: /**
50: * @var boolean whether the comparison is strict (both value and type must be the same.)
51: * Defaults to false.
52: */
53: public $strict=false;
54: /**
55: * @var boolean whether the attribute value can be null or empty. Defaults to false.
56: * If this is true, it means the attribute is considered valid when it is empty.
57: */
58: public $allowEmpty=false;
59: /**
60: * @var string the operator for comparison. Defaults to '='.
61: * The followings are valid operators:
62: * <ul>
63: * <li>'=' or '==': validates to see if the two values are equal. If {@link strict} is true, the comparison
64: * will be done in strict mode (i.e. checking value type as well).</li>
65: * <li>'!=': validates to see if the two values are NOT equal. If {@link strict} is true, the comparison
66: * will be done in strict mode (i.e. checking value type as well).</li>
67: * <li>'>': validates to see if the value being validated is greater than the value being compared with.</li>
68: * <li>'>=': validates to see if the value being validated is greater than or equal to the value being compared with.</li>
69: * <li>'<': validates to see if the value being validated is less than the value being compared with.</li>
70: * <li>'<=': validates to see if the value being validated is less than or equal to the value being compared with.</li>
71: * </ul>
72: */
73: public $operator='=';
74:
75: /**
76: * Validates the attribute of the object.
77: * If there is any error, the error message is added to the object.
78: * @param CModel $object the object being validated
79: * @param string $attribute the attribute being validated
80: * @throws CException if invalid operator is used
81: */
82: protected function validateAttribute($object,$attribute)
83: {
84: $value=$object->$attribute;
85: if($this->allowEmpty && $this->isEmpty($value))
86: return;
87: if($this->compareValue!==null)
88: $compareTo=$compareValue=$this->compareValue;
89: else
90: {
91: $compareAttribute=$this->compareAttribute===null ? $attribute.'_repeat' : $this->compareAttribute;
92: $compareValue=$object->$compareAttribute;
93: $compareTo=$object->getAttributeLabel($compareAttribute);
94: }
95:
96: switch($this->operator)
97: {
98: case '=':
99: case '==':
100: if(($this->strict && $value!==$compareValue) || (!$this->strict && $value!=$compareValue))
101: $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must be repeated exactly.');
102: break;
103: case '!=':
104: if(($this->strict && $value===$compareValue) || (!$this->strict && $value==$compareValue))
105: $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must not be equal to "{compareValue}".');
106: break;
107: case '>':
108: if($value<=$compareValue)
109: $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must be greater than "{compareValue}".');
110: break;
111: case '>=':
112: if($value<$compareValue)
113: $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must be greater than or equal to "{compareValue}".');
114: break;
115: case '<':
116: if($value>=$compareValue)
117: $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must be less than "{compareValue}".');
118: break;
119: case '<=':
120: if($value>$compareValue)
121: $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must be less than or equal to "{compareValue}".');
122: break;
123: default:
124: throw new CException(Yii::t('yii','Invalid operator "{operator}".',array('{operator}'=>$this->operator)));
125: }
126: if(!empty($message))
127: $this->addError($object,$attribute,$message,array('{compareAttribute}'=>$compareTo,'{compareValue}'=>$compareValue));
128: }
129:
130: /**
131: * Returns the JavaScript needed for performing client-side validation.
132: * @param CModel $object the data object being validated
133: * @param string $attribute the name of the attribute to be validated.
134: * @throws CException if invalid operator is used
135: * @return string the client-side validation script.
136: * @see CActiveForm::enableClientValidation
137: * @since 1.1.7
138: */
139: public function clientValidateAttribute($object,$attribute)
140: {
141: if($this->compareValue !== null)
142: {
143: $compareTo=$this->compareValue;
144: $compareValue=CJSON::encode($this->compareValue);
145: }
146: else
147: {
148: $compareAttribute=$this->compareAttribute === null ? $attribute . '_repeat' : $this->compareAttribute;
149: $compareValue="jQuery('#" . (CHtml::activeId($object, $compareAttribute)) . "').val()";
150: $compareTo=$object->getAttributeLabel($compareAttribute);
151: }
152:
153: $message=$this->message;
154: switch($this->operator)
155: {
156: case '=':
157: case '==':
158: if($message===null)
159: $message=Yii::t('yii','{attribute} must be repeated exactly.');
160: $condition='value!='.$compareValue;
161: break;
162: case '!=':
163: if($message===null)
164: $message=Yii::t('yii','{attribute} must not be equal to "{compareValue}".');
165: $condition='value=='.$compareValue;
166: break;
167: case '>':
168: if($message===null)
169: $message=Yii::t('yii','{attribute} must be greater than "{compareValue}".');
170: $condition='parseFloat(value)<=parseFloat('.$compareValue.')';
171: break;
172: case '>=':
173: if($message===null)
174: $message=Yii::t('yii','{attribute} must be greater than or equal to "{compareValue}".');
175: $condition='parseFloat(value)<parseFloat('.$compareValue.')';
176: break;
177: case '<':
178: if($message===null)
179: $message=Yii::t('yii','{attribute} must be less than "{compareValue}".');
180: $condition='parseFloat(value)>=parseFloat('.$compareValue.')';
181: break;
182: case '<=':
183: if($message===null)
184: $message=Yii::t('yii','{attribute} must be less than or equal to "{compareValue}".');
185: $condition='parseFloat(value)>parseFloat('.$compareValue.')';
186: break;
187: default:
188: throw new CException(Yii::t('yii','Invalid operator "{operator}".',array('{operator}'=>$this->operator)));
189: }
190:
191: $message=strtr($message,array(
192: '{attribute}'=>$object->getAttributeLabel($attribute),
193: '{compareAttribute}'=>$compareTo,
194: ));
195:
196: return "
197: if(".($this->allowEmpty ? "jQuery.trim(value)!='' && " : '').$condition.") {
198: messages.push(".CJSON::encode($message).".replace('{compareValue}', ".$compareValue."));
199: }
200: ";
201: }
202: }
203: