1: <?php
2: /**
3: * CFormInputElement 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: * CFormInputElement represents form input element.
13: *
14: * CFormInputElement can represent the following types of form input based on {@link type} property:
15: * <ul>
16: * <li>text: a normal text input generated using {@link CHtml::activeTextField}</li>
17: * <li>hidden: a hidden input generated using {@link CHtml::activeHiddenField}</li>
18: * <li>password: a password input generated using {@link CHtml::activePasswordField}</li>
19: * <li>textarea: a text area generated using {@link CHtml::activeTextArea}</li>
20: * <li>file: a file input generated using {@link CHtml::activeFileField}</li>
21: * <li>radio: a radio button generated using {@link CHtml::activeRadioButton}</li>
22: * <li>checkbox: a check box generated using {@link CHtml::activeCheckBox}</li>
23: * <li>listbox: a list box generated using {@link CHtml::activeListBox}</li>
24: * <li>dropdownlist: a drop-down list generated using {@link CHtml::activeDropDownList}</li>
25: * <li>checkboxlist: a list of check boxes generated using {@link CHtml::activeCheckBoxList}</li>
26: * <li>radiolist: a list of radio buttons generated using {@link CHtml::activeRadioButtonList}</li>
27: * <li>url: an HTML5 url input generated using {@link CHtml::activeUrlField}</li>
28: * <li>email: an HTML5 email input generated using {@link CHtml::activeEmailField}</li>
29: * <li>number: an HTML5 number input generated using {@link CHtml::activeNumberField}</li>
30: * <li>range: an HTML5 range input generated using {@link CHtml::activeRangeField}</li>
31: * <li>date: an HTML5 date input generated using {@link CHtml::activeDateField}</li>
32: * <li>time: an HTML5 time input generated using {@link CHtml::activeTimeField}</li>
33: * <li>datetime: an HTML5 datetime input generated using {@link CHtml::activeDateTimeField}</li>
34: * <li>datetimelocal: an HTML5 datetime-local input generated using {@link CHtml::activeDateTimeLocalField}</li>
35: * <li>week: an HTML5 week input generated using {@link CHtml::activeWeekField}</li>
36: * <li>color: an HTML5 color input generated using {@link CHtml::activeColorField}</li>
37: * <li>tel: an HTML5 tel input generated using {@link CHtml::activeTelField}</li>
38: * <li>search: an HTML5 search input generated using {@link CHtml::activeSearchField}</li>
39: * </ul>
40: * The {@link type} property can also be a class name or a path alias to the class. In this case,
41: * the input is generated using a widget of the specified class. Note, the widget must
42: * have a property called "model" which expects a model object, and a property called "attribute"
43: * which expects the name of a model attribute.
44: *
45: * Because CFormElement is an ancestor class of CFormInputElement, a value assigned to a non-existing property will be
46: * stored in {@link attributes} which will be passed as HTML attribute values to the {@link CHtml} method
47: * generating the input or initial values of the widget properties.
48: *
49: * @property boolean $required Whether this input is required.
50: * @property string $label The label for this input. If the label is not manually set,
51: * this method will call {@link CModel::getAttributeLabel} to determine the label.
52: *
53: * @author Qiang Xue <qiang.xue@gmail.com>
54: * @package system.web.form
55: * @since 1.1
56: */
57: class CFormInputElement extends CFormElement
58: {
59: /**
60: * @var array Core input types (alias=>CHtml method name)
61: */
62: public static $coreTypes=array(
63: 'text'=>'activeTextField',
64: 'hidden'=>'activeHiddenField',
65: 'password'=>'activePasswordField',
66: 'textarea'=>'activeTextArea',
67: 'file'=>'activeFileField',
68: 'radio'=>'activeRadioButton',
69: 'checkbox'=>'activeCheckBox',
70: 'listbox'=>'activeListBox',
71: 'dropdownlist'=>'activeDropDownList',
72: 'checkboxlist'=>'activeCheckBoxList',
73: 'radiolist'=>'activeRadioButtonList',
74: 'url'=>'activeUrlField',
75: 'email'=>'activeEmailField',
76: 'number'=>'activeNumberField',
77: 'range'=>'activeRangeField',
78: 'date'=>'activeDateField',
79: 'time'=>'activeTimeField',
80: 'datetime'=>'activeDateTimeField',
81: 'datetimelocal'=>'activeDateTimeLocalField',
82: 'week'=>'activeWeekField',
83: 'color'=>'activeColorField',
84: 'tel'=>'activeTelField',
85: 'search'=>'activeSearchField',
86: );
87:
88: /**
89: * @var string the type of this input. This can be a widget class name, a path alias of a widget class name,
90: * or an input type alias (text, hidden, password, textarea, file, radio, checkbox, listbox, dropdownlist, checkboxlist, or radiolist).
91: * If a widget class, it must extend from {@link CInputWidget} or (@link CJuiInputWidget).
92: */
93: public $type;
94: /**
95: * @var string name of this input
96: */
97: public $name;
98: /**
99: * @var string hint text of this input
100: */
101: public $hint;
102: /**
103: * @var array the options for this input when it is a list box, drop-down list, check box list, or radio button list.
104: * Please see {@link CHtml::listData} for details of generating this property value.
105: */
106: public $items=array();
107: /**
108: * @var array the options used when rendering the error part. This property will be passed
109: * to the {@link CActiveForm::error} method call as its $htmlOptions parameter.
110: * @see CActiveForm::error
111: * @since 1.1.1
112: */
113: public $errorOptions=array();
114: /**
115: * @var boolean whether to allow AJAX-based validation for this input. Note that in order to use
116: * AJAX-based validation, {@link CForm::activeForm} must be configured with 'enableAjaxValidation'=>true.
117: * This property allows turning on or off AJAX-based validation for individual input fields.
118: * Defaults to true.
119: * @since 1.1.7
120: */
121: public $enableAjaxValidation=true;
122: /**
123: * @var boolean whether to allow client-side validation for this input. Note that in order to use
124: * client-side validation, {@link CForm::activeForm} must be configured with 'enableClientValidation'=>true.
125: * This property allows turning on or off client-side validation for individual input fields.
126: * Defaults to true.
127: * @since 1.1.7
128: */
129: public $enableClientValidation=true;
130: /**
131: * @var string the layout used to render label, input, hint and error. They correspond to the placeholders
132: * "{label}", "{input}", "{hint}" and "{error}".
133: */
134: public $layout="{label}\n{input}\n{hint}\n{error}";
135:
136: private $_label;
137: private $_required;
138:
139: /**
140: * Gets the value indicating whether this input is required.
141: * If this property is not set explicitly, it will be determined by calling
142: * {@link CModel::isAttributeRequired} for the associated model and attribute of this input.
143: * @return boolean whether this input is required.
144: */
145: public function getRequired()
146: {
147: if($this->_required!==null)
148: return $this->_required;
149: else
150: return $this->getParent()->getModel()->isAttributeRequired($this->name);
151: }
152:
153: /**
154: * @param boolean $value whether this input is required.
155: */
156: public function setRequired($value)
157: {
158: $this->_required=$value;
159: }
160:
161: /**
162: * @return string the label for this input. If the label is not manually set,
163: * this method will call {@link CModel::getAttributeLabel} to determine the label.
164: */
165: public function getLabel()
166: {
167: if($this->_label!==null)
168: return $this->_label;
169: else
170: return $this->getParent()->getModel()->getAttributeLabel($this->name);
171: }
172:
173: /**
174: * @param string $value the label for this input
175: */
176: public function setLabel($value)
177: {
178: $this->_label=$value;
179: }
180:
181: /**
182: * Renders everything for this input.
183: * The default implementation simply returns the result of {@link renderLabel}, {@link renderInput},
184: * {@link renderHint}. When {@link CForm::showErrorSummary} is false, {@link renderError} is also called
185: * to show error messages after individual input fields.
186: * @return string the complete rendering result for this input, including label, input field, hint, and error.
187: */
188: public function render()
189: {
190: if($this->type==='hidden')
191: return $this->renderInput();
192: $output=array(
193: '{label}'=>$this->renderLabel(),
194: '{input}'=>$this->renderInput(),
195: '{hint}'=>$this->renderHint(),
196: '{error}'=>!$this->getParent()->showErrors ? '' : $this->renderError(),
197: );
198: return strtr($this->layout,$output);
199: }
200:
201: /**
202: * Renders the label for this input.
203: * The default implementation returns the result of {@link CHtml activeLabelEx}.
204: * @return string the rendering result
205: */
206: public function renderLabel()
207: {
208: $options = array(
209: 'label'=>$this->getLabel(),
210: 'required'=>$this->getRequired()
211: );
212:
213: if(!empty($this->attributes['id']))
214: $options['for']=$this->attributes['id'];
215:
216: return CHtml::activeLabel($this->getParent()->getModel(), $this->name, $options);
217: }
218:
219: /**
220: * Renders the input field.
221: * The default implementation returns the result of the appropriate CHtml method or the widget.
222: * @return string the rendering result
223: */
224: public function renderInput()
225: {
226: if(isset(self::$coreTypes[$this->type]))
227: {
228: $method=self::$coreTypes[$this->type];
229: if(strpos($method,'List')!==false)
230: return CHtml::$method($this->getParent()->getModel(), $this->name, $this->items, $this->attributes);
231: else
232: return CHtml::$method($this->getParent()->getModel(), $this->name, $this->attributes);
233: }
234: else
235: {
236: $attributes=$this->attributes;
237: $attributes['model']=$this->getParent()->getModel();
238: $attributes['attribute']=$this->name;
239: ob_start();
240: $this->getParent()->getOwner()->widget($this->type, $attributes);
241: return ob_get_clean();
242: }
243: }
244:
245: /**
246: * Renders the error display of this input.
247: * The default implementation returns the result of {@link CHtml::error}
248: * @return string the rendering result
249: */
250: public function renderError()
251: {
252: $parent=$this->getParent();
253: return $parent->getActiveFormWidget()->error($parent->getModel(), $this->name, $this->errorOptions, $this->enableAjaxValidation, $this->enableClientValidation);
254: }
255:
256: /**
257: * Renders the hint text for this input.
258: * The default implementation returns the {@link hint} property enclosed in a paragraph HTML tag.
259: * @return string the rendering result.
260: */
261: public function renderHint()
262: {
263: return $this->hint===null ? '' : '<div class="hint">'.$this->hint.'</div>';
264: }
265:
266: /**
267: * Evaluates the visibility of this element.
268: * This method will check if the attribute associated with this input is safe for
269: * the current model scenario.
270: * @return boolean whether this element is visible.
271: */
272: protected function evaluateVisible()
273: {
274: return $this->getParent()->getModel()->isAttributeSafe($this->name);
275: }
276: }
277: