GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

TbActiveForm::error()   F
last analyzed

Complexity

Conditions 22
Paths 5192

Size

Total Lines 90

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 50
CRAP Score 27.9504

Importance

Changes 0
Metric Value
cc 22
nc 5192
nop 5
dl 0
loc 90
rs 0
c 0
b 0
f 0
ccs 50
cts 65
cp 0.7692
crap 27.9504

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * TbActiveForm class file.
4
 * @author Christoffer Niska <[email protected]>
5
 * @copyright Copyright &copy; Christoffer Niska 2011-
6
 * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
7
 * @package bootstrap.widgets
8
 */
9
10 1
Yii::import('bootstrap.widgets.input.TbInput');
11
12
/**
13
 * Bootstrap active form widget.
14
 */
15
class TbActiveForm extends CActiveForm
16
{
17
	// Form types.
18
	const TYPE_VERTICAL = 'vertical';
19
	const TYPE_INLINE = 'inline';
20
	const TYPE_HORIZONTAL = 'horizontal';
21
	const TYPE_SEARCH = 'search';
22
23
	// Input classes.
24
	const INPUT_HORIZONTAL = 'bootstrap.widgets.input.TbInputHorizontal';
25
	const INPUT_INLINE = 'bootstrap.widgets.input.TbInputInline';
26
	const INPUT_SEARCH = 'bootstrap.widgets.input.TbInputSearch';
27
	const INPUT_VERTICAL = 'bootstrap.widgets.input.TbInputVertical';
28
29
	/**
30
	 * @var string the form type. See class constants.
31
	 */
32
	public $type = self::TYPE_VERTICAL;
33
	/**
34
	 * @var string input class.
35
	 */
36
	public $input;
37
	/**
38
	 * @var boolean indicates whether to display errors as blocks.
39
	 */
40
	public $inlineErrors;
41
42
	/**
43
	 * Initializes the widget.
44
	 * This renders the form open tag.
45
	 */
46 2
	public function init()
47
	{
48 2
		if (!isset($this->htmlOptions['class']))
49 2
			$this->htmlOptions['class'] = 'form-'.$this->type;
50
		else
51
			$this->htmlOptions['class'] .= ' form-'.$this->type;
52
53 2
		if (!isset($this->inlineErrors))
54 2
			$this->inlineErrors = $this->type === self::TYPE_HORIZONTAL;
55
56 2
		if ($this->inlineErrors)
57 2
			$this->errorMessageCssClass = 'help-inline error';
58
		else
59
			$this->errorMessageCssClass = 'help-block error';
60
61 2
		parent::init();
62 2
	}
63
64
	/**
65
	 * Renders a checkbox input row.
66
	 * @param CModel $model the data model
67
	 * @param string $attribute the attribute
68
	 * @param array $htmlOptions additional HTML attributes
69
	 * @return string the generated row
70
	 */
71
	public function checkBoxRow($model, $attribute, $htmlOptions = array())
72
	{
73
		return $this->inputRow(TbInput::TYPE_CHECKBOX, $model, $attribute, null, $htmlOptions);
74
	}
75
76
	/**
77
	 * Renders a checkbox list input row.
78
	 * @param CModel $model the data model
79
	 * @param string $attribute the attribute
80
	 * @param array $data the list data
81
	 * @param array $htmlOptions additional HTML attributes
82
	 * @return string the generated row
83
	 */
84
	public function checkBoxListRow($model, $attribute, $data = array(), $htmlOptions = array())
85
	{
86
		return $this->inputRow(TbInput::TYPE_CHECKBOXLIST, $model, $attribute, $data, $htmlOptions);
87
	}
88
89
	/**
90
	 * Renders a checkbox list inline input row.
91
	 * @param CModel $model the data model
92
	 * @param string $attribute the attribute
93
	 * @param array $data the list data
94
	 * @param array $htmlOptions additional HTML attributes
95
	 * @return string the generated row
96
	 */
97
	public function checkBoxListInlineRow($model, $attribute, $data = array(), $htmlOptions = array())
98
	{
99
		return $this->inputRow(TbInput::TYPE_CHECKBOXLIST_INLINE, $model, $attribute, $data, $htmlOptions);
100
	}
101
102
	/**
103
	 * Renders a drop-down list input row.
104
	 * @param CModel $model the data model
105
	 * @param string $attribute the attribute
106
	 * @param array $data the list data
107
	 * @param array $htmlOptions additional HTML attributes
108
	 * @return string the generated row
109
	 */
110
	public function dropDownListRow($model, $attribute, $data = array(), $htmlOptions = array())
111
	{
112
		return $this->inputRow(TbInput::TYPE_DROPDOWN, $model, $attribute, $data, $htmlOptions);
113
	}
114
115
	/**
116
	 * Renders a file field input row.
117
	 * @param CModel $model the data model
118
	 * @param string $attribute the attribute
119
	 * @param array $htmlOptions additional HTML attributes
120
	 * @return string the generated row
121
	 */
122
	public function fileFieldRow($model, $attribute, $htmlOptions = array())
123
	{
124
		return $this->inputRow(TbInput::TYPE_FILE, $model, $attribute, null, $htmlOptions);
125
	}
126
127
	/**
128
	 * Renders a password field input row.
129
	 * @param CModel $model the data model
130
	 * @param string $attribute the attribute
131
	 * @param array $htmlOptions additional HTML attributes
132
	 * @return string the generated row
133
	 */
134
	public function passwordFieldRow($model, $attribute, $htmlOptions = array())
135
	{
136
		return $this->inputRow(TbInput::TYPE_PASSWORD, $model, $attribute, null, $htmlOptions);
137
	}
138
139
	/**
140
	 * Renders a radio button input row.
141
	 * @param CModel $model the data model
142
	 * @param string $attribute the attribute
143
	 * @param array $htmlOptions additional HTML attributes
144
	 * @return string the generated row
145
	 */
146
	public function radioButtonRow($model, $attribute, $htmlOptions = array())
147
	{
148
		return $this->inputRow(TbInput::TYPE_RADIO, $model, $attribute, null, $htmlOptions);
149
	}
150
151
	/**
152
	 * Renders a radio button list input row.
153
	 * @param CModel $model the data model
154
	 * @param string $attribute the attribute
155
	 * @param array $data the list data
156
	 * @param array $htmlOptions additional HTML attributes
157
	 * @return string the generated row
158
	 */
159
	public function radioButtonListRow($model, $attribute, $data = array(), $htmlOptions = array())
160
	{
161
		return $this->inputRow(TbInput::TYPE_RADIOLIST, $model, $attribute, $data, $htmlOptions);
162
	}
163
164
	/**
165
	 * Renders a radio button list inline input row.
166
	 * @param CModel $model the data model
167
	 * @param string $attribute the attribute
168
	 * @param array $data the list data
169
	 * @param array $htmlOptions additional HTML attributes
170
	 * @return string the generated row
171
	 */
172
	public function radioButtonListInlineRow($model, $attribute, $data = array(), $htmlOptions = array())
173
	{
174
		return $this->inputRow(TbInput::TYPE_RADIOLIST_INLINE, $model, $attribute, $data, $htmlOptions);
175
	}
176
177
	/**
178
	 * Renders a text field input row.
179
	 * @param CModel $model the data model
180
	 * @param string $attribute the attribute
181
	 * @param array $htmlOptions additional HTML attributes
182
	 * @return string the generated row
183
	 */
184
	public function textFieldRow($model, $attribute, $htmlOptions = array())
185
	{
186
		return $this->inputRow(TbInput::TYPE_TEXT, $model, $attribute, null, $htmlOptions);
187
	}
188
189
	/**
190
	 * Renders a text area input row.
191
	 * @param CModel $model the data model
192
	 * @param string $attribute the attribute
193
	 * @param array $htmlOptions additional HTML attributes
194
	 * @return string the generated row
195
	 */
196 2
	public function textAreaRow($model, $attribute, $htmlOptions = array())
197
	{
198 2
		return $this->inputRow(TbInput::TYPE_TEXTAREA, $model, $attribute, null, $htmlOptions);
199
	}
200
201
	/**
202
	 * Renders a captcha row.
203
	 * @param CModel $model the data model
204
	 * @param string $attribute the attribute
205
	 * @param array $htmlOptions additional HTML attributes
206
	 * @return string the generated row
207
	 * @since 0.9.3
208
	 */
209
	public function captchaRow($model, $attribute, $htmlOptions = array())
210
	{
211
		return $this->inputRow(TbInput::TYPE_CAPTCHA, $model, $attribute, null, $htmlOptions);
212
	}
213
214
	/**
215
	 * Renders an uneditable text field row.
216
	 * @param CModel $model the data model
217
	 * @param string $attribute the attribute
218
	 * @param array $htmlOptions additional HTML attributes
219
	 * @return string the generated row
220
	 * @since 0.9.5
221
	 */
222
	public function uneditableRow($model, $attribute, $htmlOptions = array())
223
	{
224
		return $this->inputRow(TbInput::TYPE_UNEDITABLE, $model, $attribute, null, $htmlOptions);
225
	}
226
227
	/**
228
	 * Renders a checkbox list for a model attribute.
229
	 * This method is a wrapper of {@link CHtml::activeCheckBoxList}.
230
	 * Please check {@link CHtml::activeCheckBoxList} for detailed information
231
	 * about the parameters for this method.
232
	 * @param CModel $model the data model
233
	 * @param string $attribute the attribute
234
	 * @param array $data value-label pairs used to generate the check box list.
235
	 * @param array $htmlOptions additional HTML options.
236
	 * @return string the generated check box list
237
	 * @since 0.9.5
238
	 */
239
	public function checkBoxList($model, $attribute, $data, $htmlOptions = array())
240
	{
241
		return $this->inputsList(true, $model, $attribute, $data, $htmlOptions);
242
	}
243
244
	/**
245
	 * Renders a radio button list for a model attribute.
246
	 * This method is a wrapper of {@link CHtml::activeRadioButtonList}.
247
	 * Please check {@link CHtml::activeRadioButtonList} for detailed information
248
	 * about the parameters for this method.
249
	 * @param CModel $model the data model
250
	 * @param string $attribute the attribute
251
	 * @param array $data value-label pairs used to generate the radio button list.
252
	 * @param array $htmlOptions additional HTML options.
253
	 * @return string the generated radio button list
254
	 * @since 0.9.5
255
	 */
256
	public function radioButtonList($model, $attribute, $data, $htmlOptions = array())
257
	{
258
		return $this->inputsList(false, $model, $attribute, $data, $htmlOptions);
259
	}
260
261
	/**
262
	 * Renders an input list.
263
	 * @param boolean $checkbox flag that indicates if the list is a checkbox-list.
264
	 * @param CModel $model the data model
265
	 * @param string $attribute the attribute
266
	 * @param array $data value-label pairs used to generate the input list.
267
	 * @param array $htmlOptions additional HTML options.
268
	 * @return string the generated input list.
269
	 * @since 0.9.5
270
	 */
271 2
	protected function inputsList($checkbox, $model, $attribute, $data, $htmlOptions = array())
272
	{
273
		CHtml::resolveNameID($model, $attribute, $htmlOptions);
274
		$select = CHtml::resolveValue($model, $attribute);
275
276
		if ($model->hasErrors($attribute))
277
		{
278
			if (isset($htmlOptions['class']))
279
				$htmlOptions['class'] .= ' '.CHtml::$errorCss;
280
			else
281
				$htmlOptions['class'] = CHtml::$errorCss;
282
		}
283
284
		$name = $htmlOptions['name'];
285
		unset($htmlOptions['name']);
286
287
		if (array_key_exists('uncheckValue', $htmlOptions))
288
		{
289
			$uncheck = $htmlOptions['uncheckValue'];
290
			unset($htmlOptions['uncheckValue']);
291
		}
292
		else
293
			$uncheck = '';
294
295
		$hiddenOptions = isset($htmlOptions['id']) ? array('id' => CHtml::ID_PREFIX.$htmlOptions['id']) : array('id' => false);
296
		$hidden = $uncheck !== null ? CHtml::hiddenField($name, $uncheck, $hiddenOptions) : '';
297
298
		if (isset($htmlOptions['template']))
299
			$template = $htmlOptions['template'];
300
		else
301
			$template = '<label class="{labelCssClass}">{input}{label}</label>';
302
303
		unset($htmlOptions['template'], $htmlOptions['separator'], $htmlOptions['hint']);
304
305
		if ($checkbox && substr($name, -2) !== '[]')
306
			$name .= '[]';
307
308
		unset($htmlOptions['checkAll'], $htmlOptions['checkAllLast']);
309
310
		$labelOptions = isset($htmlOptions['labelOptions']) ? $htmlOptions['labelOptions'] : array();
311
		unset($htmlOptions['labelOptions']);
312
313
		$items = array();
314
		$baseID = CHtml::getIdByName($name);
315
		$id = 0;
316
		$method = $checkbox ? 'checkBox' : 'radioButton';
317
		$labelCssClass = $checkbox ? 'checkbox' : 'radio';
318
319
		if (isset($htmlOptions['inline']))
320
		{
321
			$labelCssClass .= ' inline';
322
			unset($htmlOptions['inline']);
323
		}
324
325
		foreach ($data as $value => $label)
326 2
		{
327
			$checked = !is_array($select) && !strcmp($value, $select) || is_array($select) && in_array($value, $select);
328
			$htmlOptions['value'] = $value;
329
			$htmlOptions['id'] = $baseID.'_'.$id++;
330
			$option = CHtml::$method($name, $checked, $htmlOptions);
331
			$label = CHtml::label($label, $htmlOptions['id'], $labelOptions);
332
			$items[] = strtr($template, array(
333
				'{labelCssClass}' => $labelCssClass,
334
				'{input}' => $option,
335
				'{label}' => $label,
336
			));
337
		}
338
339
		return $hidden.implode('', $items);
340
	}
341
342
	/**
343
	 * Displays a summary of validation errors for one or several models.
344
	 * This method is very similar to {@link CHtml::errorSummary} except that it also works
345
	 * when AJAX validation is performed.
346
	 * @param mixed $models the models whose input errors are to be displayed. This can be either
347
	 * a single model or an array of models.
348
	 * @param string $header a piece of HTML code that appears in front of the errors
349
	 * @param string $footer a piece of HTML code that appears at the end of the errors
350
	 * @param array $htmlOptions additional HTML attributes to be rendered in the container div tag.
351
	 * @return string the error summary. Empty if no errors are found.
352
	 * @see CHtml::errorSummary
353
	 */
354
	public function errorSummary($models, $header = null, $footer = null, $htmlOptions = array())
355
	{
356
		if (!isset($htmlOptions['class']))
357
			$htmlOptions['class'] = 'alert alert-block alert-error'; // Bootstrap error class as default
358
359
		return parent::errorSummary($models, $header, $footer, $htmlOptions);
360
	}
361
362
	/**
363
	 * Displays the first validation error for a model attribute.
364
	 * @param CModel $model the data model
365
	 * @param string $attribute the attribute name
366
	 * @param array $htmlOptions additional HTML attributes to be rendered in the container div tag.
367
	 * @param boolean $enableAjaxValidation whether to enable AJAX validation for the specified attribute.
368
	 * @param boolean $enableClientValidation whether to enable client-side validation for the specified attribute.
369
	 * @return string the validation result (error display or success message).
370
	 */
371 2
	public function error($model, $attribute, $htmlOptions = array(), $enableAjaxValidation = true, $enableClientValidation = true)
372
	{
373 2
		if (!$this->enableAjaxValidation)
374 2
			$enableAjaxValidation = false;
375
376 2
		if (!$this->enableClientValidation)
377 2
			$enableClientValidation = false;
378
379 2
		if (!isset($htmlOptions['class']))
380 2
			$htmlOptions['class'] = $this->errorMessageCssClass;
381
382 2
		if (!$enableAjaxValidation && !$enableClientValidation)
383 2
			return $this->renderError($model, $attribute, $htmlOptions);
384
385 2
		$id = CHtml::activeId($model,$attribute);
386 2
		$inputID = isset($htmlOptions['inputID']) ? $htmlOptions['inputID'] : $id;
387 2
		unset($htmlOptions['inputID']);
388 2
		if (!isset($htmlOptions['id']))
389 2
			$htmlOptions['id'] = $inputID.'_em_';
390
391
		$option = array(
392 2
			'id'=>$id,
393 2
			'inputID'=>$inputID,
394 2
			'errorID'=>$htmlOptions['id'],
395 2
			'model'=>get_class($model),
396 2
			'name'=>CHtml::resolveName($model, $attribute),
397 2
			'enableAjaxValidation'=>$enableAjaxValidation,
398 2
			'inputContainer'=>'div.control-group', // Bootstrap requires this
399 2
		);
400
401
		$optionNames = array(
402 2
			'validationDelay',
403 2
			'validateOnChange',
404 2
			'validateOnType',
405 2
			'hideErrorMessage',
406 2
			'inputContainer',
407 2
			'errorCssClass',
408 2
			'successCssClass',
409 2
			'validatingCssClass',
410 2
			'beforeValidateAttribute',
411 2
			'afterValidateAttribute',
412 2
		);
413
414 2
		foreach ($optionNames as $name)
415
		{
416 2
			if (isset($htmlOptions[$name]))
417 2
			{
418
				$option[$name] = $htmlOptions[$name];
419
				unset($htmlOptions[$name]);
420
			}
421 2
		}
422
423 2
		if ($model instanceof CActiveRecord && !$model->isNewRecord)
424 2
			$option['status'] = 1;
425
426
		if ($enableClientValidation)
427 2
		{
428
			$validators = isset($htmlOptions['clientValidation']) ? array($htmlOptions['clientValidation']) : array();
429
430
			$attributeName = $attribute;
431
			if (($pos = strrpos($attribute, ']')) !== false && $pos !== strlen($attribute) - 1) // e.g. [a]name
432
				$attributeName = substr($attribute, $pos + 1);
433
434
			foreach ($model->getValidators($attributeName) as $validator)
435
			{
436
				if ($validator->enableClientValidation)
437
					if (($js = $validator->clientValidateAttribute($model, $attributeName)) != '')
438
						$validators[] = $js;
439
			}
440
441
			if ($validators !== array())
442
				$option['clientValidation'] = "js:function(value, messages, attribute) {\n".implode("\n", $validators)."\n}";
443
		}
444
445 2
		$html = $this->renderError($model, $attribute, $htmlOptions);
446
447 2
		if ($html === '')
448 2
		{
449 2
			if (isset($htmlOptions['style']))
450 2
				$htmlOptions['style'] = rtrim($htmlOptions['style'], ';').'; display: none';
451
			else
452 2
				$htmlOptions['style'] = 'display: none';
453
454 2
			$html = CHtml::tag('span', $htmlOptions, '');
455 2
		}
456
457 2
		$this->attributes[$inputID] = $option;
458
459 2
		return $html;
460
	}
461
462
	/**
463
	 * Displays the first validation error for a model attribute.
464
	 * @param CModel $model the data model
465
	 * @param string $attribute the attribute name
466
	 * @param array $htmlOptions additional HTML attributes to be rendered in the container div tag.
467
	 * @return string the error display. Empty if no errors are found.
468
	 * @see CModel::getErrors
469
	 * @see errorMessageCss
470
	 */
471 2
	protected static function renderError($model, $attribute, $htmlOptions = array())
472
	{
473 2
		CHtml::resolveName($model, $attribute); // turn [a][b]attr into attr
474 2
		$error = $model->getError($attribute);
475 2
		return $error != '' ? CHtml::tag('span', $htmlOptions, $error) : '';
476
	}
477
478
	/**
479
	 * Creates an input row of a specific type.
480
	 * @param string $type the input type
481
	 * @param CModel $model the data model
482
	 * @param string $attribute the attribute
483
	 * @param array $data the data for list inputs
484
	 * @param array $htmlOptions additional HTML attributes
485
	 * @return string the generated row
486
	 */
487 2
	public function inputRow($type, $model, $attribute, $data = null, $htmlOptions = array())
488
	{
489 2
		ob_start();
490 2
		$this->getOwner()->widget($this->getInputClassName(), array(
491 2
            'form'=>$this,
492 2
            'type'=>$type,
493 2
			'model'=>$model,
494 2
			'attribute'=>$attribute,
495 2
			'data'=>$data,
496 2
			'htmlOptions'=>$htmlOptions,
497 2
		));
498 2
		return ob_get_clean();
499
	}
500
501
	/**
502
	 * Returns the input widget class name suitable for the form.
503
	 * @return string the class name
504
	 */
505
	protected function getInputClassName()
506
	{
507
		if (isset($this->input))
508
			return $this->input;
509
		else
510
		{
511
			switch ($this->type)
512
			{
513
				case self::TYPE_HORIZONTAL:
514
					return self::INPUT_HORIZONTAL;
515
					break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
516
517
				case self::TYPE_INLINE:
518
					return self::INPUT_INLINE;
519
					break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
520
521
				case self::TYPE_SEARCH:
522
					return self::INPUT_SEARCH;
523
					break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
524
525
				case self::TYPE_VERTICAL:
526
				default:
527
					return self::INPUT_VERTICAL;
528
					break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
529
			}
530
		}
531
	}
532
}
533