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.

TbInput::ckEditor()
last analyzed

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 1
ccs 0
cts 0
cp 0
nc 1
1
<?php
2
/**
3
 *## TbInput class file.
4
 *
5
 * @author Christoffer Niska <[email protected]>
6
 * @copyright Copyright &copy; Christoffer Niska 2011-
7
 * @license [New BSD License](http://www.opensource.org/licenses/bsd-license.php)
8
 */
9
10
/**
11
 *## Bootstrap input widget.
12
 *
13
 * Used for rendering inputs according to Bootstrap standards.
14
 *
15
 * @package booster.widgets.forms.inputs
16
 */
17
abstract class TbInput extends CInputWidget
18
{
19
	// The different input types.
20
	const TYPE_CHECKBOX = 'checkbox';
21
	const TYPE_CHECKBOXLIST = 'checkboxlist';
22
	const TYPE_CHECKBOXLIST_INLINE = 'checkboxlist_inline';
23
	const TYPE_CHECKBOXGROUPSLIST = 'checkboxgroupslist';
24
	const TYPE_DROPDOWN = 'dropdownlist';
25
	const TYPE_FILE = 'filefield';
26
	const TYPE_PASSWORD = 'password';
27
	const TYPE_PASSFIELD = 'passfield';
28
	const TYPE_RADIO = 'radiobutton';
29
	const TYPE_RADIOLIST = 'radiobuttonlist';
30
	const TYPE_RADIOLIST_INLINE = 'radiobuttonlist_inline';
31
	const TYPE_RADIOBUTTONGROUPSLIST = 'radiobuttongroupslist';
32
	const TYPE_TEXTAREA = 'textarea';
33
	const TYPE_TEXT = 'text';
34
	const TYPE_MASKEDTEXT = 'maskedtextfield';
35
	const TYPE_CAPTCHA = 'captcha';
36
	const TYPE_UNEDITABLE = 'uneditable';
37
	const TYPE_DATEPICKER = 'datepicker';
38
	const TYPE_DATETIMEPICKER = 'datetimepicker';
39
	const TYPE_REDACTOR = 'redactor';
40
	const TYPE_MARKDOWNEDITOR = 'markdowneditor';
41
	const TYPE_HTML5EDITOR = 'wysihtml5';
42
	const TYPE_DATERANGEPICKER = 'daterangepicker';
43
	const TYPE_TOGGLEBUTTON = 'togglebutton';
44
	const TYPE_COLORPICKER = 'colorpicker';
45
	const TYPE_CKEDITOR = 'ckeditor';
46
	const TYPE_TIMEPICKER = 'timepicker';
47
	const TYPE_SELECT2 = 'select2';
48
	const TYPE_TYPEAHEAD = 'typeahead';
49
	const TYPE_NUMBER = 'numberfield';
50
	const TYPE_CUSTOM = 'custom';
51
52
	/**
53
	 * @var TbActiveForm the associated form widget.
54
	 */
55
	public $form;
56
57
	/**
58
	 * @var string the input label text.
59
	 */
60
	public $label;
61
62
	/**
63
	 * @var string the input type.
64
	 *
65
	 * Following types are supported: checkbox, checkboxlist, dropdownlist, filefield, password,
66
	 * radiobutton, radiobuttonlist, textarea, textfield, captcha and uneditable.
67
	 */
68
	public $type;
69
70
	/**
71
	 * @var array the data for list inputs.
72
	 */
73
	public $data = array();
74
75
	/**
76
	 * @var string text to prepend.
77
	 */
78
	public $prependText;
79
80
	/**
81
	 * @var string text to append.
82
	 */
83
	public $appendText;
84
85
	/**
86
	 * @var string the hint text.
87
	 */
88
	public $hintText;
89
90
	/**
91
	 * @var array label html attributes.
92
	 */
93
	public $labelOptions = array();
94
95
	/**
96
	 * @var array prepend html attributes.
97
	 */
98
	public $prependOptions = array();
99
100
	/**
101
	 * @var array append html attributes.
102
	 */
103
	public $appendOptions = array();
104
105
	/**
106
	 * @var array hint html attributes.
107
	 */
108
	public $hintOptions = array();
109
110
	/**
111
	 * @var array error html attributes.
112
	 */
113
	public $errorOptions = array();
114
115
	/**
116
	 * @var array captcha html attributes.
117
	 */
118
	public $captchaOptions = array();
119
120
	/**
121
	 * This property allows you to disable AJAX valiadtion for certain fields within a form.
122
	 * @var boolean the value to be set as fourth parameter to {@link CActiveForm::error}.
123
	 * @see http://www.yiiframework.com/doc/api/1.1/CActiveForm#error-detail
124
	 */
125
	public $enableAjaxValidation = true;
126
127
	/**
128
	 * This property allows you to disable client valiadtion for certain fields within a form.
129
	 * @var boolean the value to be set as fifth parameter to {@link CActiveForm::error}.
130
	 * @see http://www.yiiframework.com/doc/api/1.1/CActiveForm#error-detail
131
	 */
132
	public $enableClientValidation = true;
133
134
	/**
135
	 *### .init()
136
	 *
137
	 * Initializes the widget.
138
	 *
139
	 * @throws CException if the widget could not be initialized.
140
	 */
141
	public function init()
142
	{
143
		if (!isset($this->form)) {
144
			throw new CException(__CLASS__ . ': Failed to initialize widget! Form is not set.');
145
		}
146
147
		if (!isset($this->model)) {
148
			throw new CException(__CLASS__ . ': Failed to initialize widget! Model is not set.');
149
		}
150
151
		if (!isset($this->type)) {
152
			throw new CException(__CLASS__ . ': Failed to initialize widget! Input type is not set.');
153
		}
154
155
		// todo: move this logic elsewhere, it doesn't belong here ...
156
		if ($this->type === self::TYPE_UNEDITABLE) {
157
			if (isset($this->htmlOptions['class'])) {
158
				$this->htmlOptions['class'] .= ' uneditable-input';
159
			} else {
160
				$this->htmlOptions['class'] = 'uneditable-input';
161
			}
162
		}
163
164
		$this->processHtmlOptions();
165
	}
166
167
	/**
168
	 *### .processHtmlOptions()
169
	 *
170
	 * Processes the html options.
171
	 */
172
	protected function processHtmlOptions()
173
	{
174
		if (isset($this->htmlOptions['label'])) {
175
			$this->label = $this->htmlOptions['label'];
176
			unset($this->htmlOptions['label']);
177
		}
178
179
		if (isset($this->htmlOptions['prepend'])) {
180
			$this->prependText = $this->htmlOptions['prepend'];
181
			unset($this->htmlOptions['prepend']);
182
		}
183
184
		if (isset($this->htmlOptions['append'])) {
185
			$this->appendText = $this->htmlOptions['append'];
186
			unset($this->htmlOptions['append']);
187
		}
188
189
		if (isset($this->htmlOptions['hint'])) {
190
			$this->hintText = $this->htmlOptions['hint'];
191
			unset($this->htmlOptions['hint']);
192
		}
193
194
		if (isset($this->htmlOptions['labelOptions'])) {
195
			$this->labelOptions = $this->htmlOptions['labelOptions'];
196
			unset($this->htmlOptions['labelOptions']);
197
		}
198
199
		if (isset($this->htmlOptions['prependOptions'])) {
200
			$this->prependOptions = $this->htmlOptions['prependOptions'];
201
			unset($this->htmlOptions['prependOptions']);
202
		}
203
204
		if (isset($this->htmlOptions['appendOptions'])) {
205
			$this->appendOptions = $this->htmlOptions['appendOptions'];
206
			unset($this->htmlOptions['appendOptions']);
207
		}
208
209
		if (isset($this->htmlOptions['hintOptions'])) {
210
			$this->hintOptions = $this->htmlOptions['hintOptions'];
211
			unset($this->htmlOptions['hintOptions']);
212
		}
213
214
		if (isset($this->htmlOptions['errorOptions'])) {
215
			$this->errorOptions = $this->htmlOptions['errorOptions'];
216
			if (isset($this->htmlOptions['errorOptions']['enableAjaxValidation'])) {
217
				$this->enableAjaxValidation = (boolean)$this->htmlOptions['errorOptions']['enableAjaxValidation'];
218
			}
219
220
			if (isset($this->htmlOptions['errorOptions']['enableClientValidation'])) {
221
				$this->enableClientValidation = (boolean)$this->htmlOptions['errorOptions']['enableClientValidation'];
222
			}
223
			unset($this->htmlOptions['errorOptions']);
224
		}
225
226
		if (isset($this->htmlOptions['captchaOptions'])) {
227
			$this->captchaOptions = $this->htmlOptions['captchaOptions'];
228
			unset($this->htmlOptions['captchaOptions']);
229
		}
230
	}
231
232
	/**
233
	 *### .run()
234
	 *
235
	 * Runs the widget.
236
	 *
237
	 * @throws CException if the widget type is invalid.
238
	 */
239
	public function run()
240
	{
241
		switch ($this->type) {
242
			case self::TYPE_CHECKBOX:
243
				$this->checkBox();
244
				break;
245
246
			case self::TYPE_CHECKBOXLIST:
247
				$this->checkBoxList();
248
				break;
249
250
			case self::TYPE_CHECKBOXLIST_INLINE:
251
				$this->checkBoxListInline();
252
				break;
253
254
			case self::TYPE_CHECKBOXGROUPSLIST:
255
				$this->checkBoxGroupsList();
256
				break;
257
258
			case self::TYPE_DROPDOWN:
259
				$this->dropDownList();
260
				break;
261
262
			case self::TYPE_FILE:
263
				$this->fileField();
264
				break;
265
266
			case self::TYPE_PASSWORD:
267
				$this->passwordField();
268
				break;
269
270
			case self::TYPE_PASSFIELD:
271
				$this->passfieldField();
272
				break;
273
274
			case self::TYPE_RADIO:
275
				$this->radioButton();
276
				break;
277
278
			case self::TYPE_RADIOLIST:
279
				$this->radioButtonList();
280
				break;
281
282
			case self::TYPE_RADIOLIST_INLINE:
283
				$this->radioButtonListInline();
284
				break;
285
286
			case self::TYPE_RADIOBUTTONGROUPSLIST:
287
				$this->radioButtonGroupsList();
288
				break;
289
290
			case self::TYPE_TEXTAREA:
291
				$this->textArea();
292
				break;
293
294
			case 'textfield': // backwards compatibility
295
			case self::TYPE_TEXT:
296
				$this->textField();
297
				break;
298
299
			case self::TYPE_MASKEDTEXT:
300
				$this->maskedTextField();
301
				break;
302
303
			case self::TYPE_CAPTCHA:
304
				$this->captcha();
305
				break;
306
307
			case self::TYPE_UNEDITABLE:
308
				$this->uneditableField();
309
				break;
310
311
			case self::TYPE_DATEPICKER:
312
				$this->datepickerField();
313
				break;
314
315
			case self::TYPE_DATETIMEPICKER:
316
				$this->datetimepickerField();
317
				break;
318
319
			case self::TYPE_REDACTOR:
320
				$this->redactorJs();
321
				break;
322
323
			case self::TYPE_MARKDOWNEDITOR:
324
				$this->markdownEditorJs();
325
				break;
326
327
			case self::TYPE_HTML5EDITOR:
328
				$this->html5Editor();
329
				break;
330
331
			case self::TYPE_DATERANGEPICKER:
332
				$this->dateRangeField();
333
				break;
334
335
			case self::TYPE_TOGGLEBUTTON:
336
				$this->toggleButton();
337
				break;
338
339
			case self::TYPE_COLORPICKER:
340
				$this->colorpickerField();
341
				break;
342
343
			case self::TYPE_CKEDITOR:
344
				$this->ckEditor();
345
				break;
346
347
			case self::TYPE_TIMEPICKER:
348
				$this->timepickerField();
349
				break;
350
351
			case self::TYPE_SELECT2:
352
				$this->select2Field();
353
				break;
354
355
			case self::TYPE_TYPEAHEAD:
356
				$this->typeAheadField();
357
				break;
358
359
			case self::TYPE_NUMBER:
360
				$this->numberField();
361
				break;
362
363
			case self::TYPE_CUSTOM:
364
				$this->customField();
365
				break;
366
367
			default:
368
				throw new CException(__CLASS__ . ': Failed to run widget! Type is invalid.');
369
		}
370
	}
371
372
	/**
373
	 *### .getLabel()
374
	 *
375
	 * Returns the label for the input.
376
	 *
377
	 * @return string the label
378
	 */
379
	protected function getLabel()
380
	{
381
		if ($this->label !== false && !in_array($this->type, array('checkbox', 'radio')) && $this->hasModel()) {
382
			return $this->form->labelEx($this->model, $this->attribute, $this->labelOptions);
383
		} else if ($this->label !== null) {
384
			return $this->label;
385
		} else {
386
			return '';
387
		}
388
	}
389
390
	/**
391
	 *### .getPrepend()
392
	 *
393
	 * Returns the prepend element for the input.
394
	 *
395
	 * @return string the element
396
	 */
397
	protected function getPrepend()
398
	{
399
		if ($this->hasAddOn()) {
400
			$htmlOptions = $this->prependOptions;
401
402
			if (isset($htmlOptions['class'])) {
403
				$htmlOptions['class'] .= ' add-on';
404
			} else {
405
				$htmlOptions['class'] = 'add-on';
406
			}
407
408
			ob_start();
409
			echo '<div class="' . $this->getAddonCssClass() . '">';
410
			if (isset($this->prependText)) {
411
				if (isset($htmlOptions['isRaw']) && $htmlOptions['isRaw']) {
412
					echo $this->prependText;
413
				} else {
414
					echo CHtml::tag('span', $htmlOptions, $this->prependText);
415
				}
416
			}
417
418
			return ob_get_clean();
419
		} else {
420
			return '';
421
		}
422
	}
423
424
	/**
425
	 *### .getAppend()
426
	 *
427
	 * Returns the append element for the input.
428
	 *
429
	 * @return string the element
430
	 */
431
	protected function getAppend()
432
	{
433
		if ($this->hasAddOn()) {
434
			$htmlOptions = $this->appendOptions;
435
436
			if (isset($htmlOptions['class'])) {
437
				$htmlOptions['class'] .= ' add-on';
438
			} else {
439
				$htmlOptions['class'] = 'add-on';
440
			}
441
442
			ob_start();
443
			if (isset($this->appendText)) {
444
				if (isset($htmlOptions['isRaw']) && $htmlOptions['isRaw']) {
445
					echo $this->appendText;
446
				} else {
447
					echo CHtml::tag('span', $htmlOptions, $this->appendText);
448
				}
449
			}
450
451
			echo '</div>';
452
			return ob_get_clean();
453
		} else {
454
			return '';
455
		}
456
	}
457
458
	/**
459
	 *### .getAppend()
460
	 *
461
	 * Returns the id that should be used for the specified attribute
462
	 *
463
	 * @param string $attribute the attribute
464
	 *
465
	 * @return string the id
466
	 */
467
	protected function getAttributeId($attribute)
468
	{
469
		return isset($this->htmlOptions['id'])
470
			? $this->htmlOptions['id']
471
			: CHtml::getIdByName(CHtml::resolveName($this->model, $attribute));
472
	}
473
474
	/**
475
	 *### .getError()
476
	 *
477
	 * Returns the error text for the input.
478
	 *
479
	 * @return string the error text
480
	 */
481
	protected function getError()
482
	{
483
		return $this->form->error(
484
			$this->model,
485
			$this->attribute,
486
			$this->errorOptions,
487
			$this->enableAjaxValidation,
488
			$this->enableClientValidation
489
		);
490
	}
491
492
	/**
493
	 *### .getHint()
494
	 *
495
	 * Returns the hint text for the input.
496
	 *
497
	 * @return string the hint text
498
	 */
499
	protected function getHint()
500
	{
501
		if (isset($this->hintText)) {
502
			$htmlOptions = $this->hintOptions;
503
504
			if (isset($htmlOptions['class'])) {
505
				$htmlOptions['class'] .= ' help-block';
506
			} else {
507
				$htmlOptions['class'] = 'help-block';
508
			}
509
510
			return CHtml::tag('p', $htmlOptions, $this->hintText);
511
		} else {
512
			return '';
513
		}
514
	}
515
516
	/**
517
	 *### .getContainerCssClass()
518
	 *
519
	 * Returns the container CSS class for the input.
520
	 *
521
	 * @return string the CSS class
522
	 */
523
	protected function getContainerCssClass()
524
	{
525
		return $this->model->hasErrors($this->attribute) ? CHtml::$errorCss : '';
526
	}
527
528
	/**
529
	 *### .getAddonCssClass()
530
	 *
531
	 * Returns the input container CSS classes.
532
	 *
533
	 * @return string the CSS class
534
	 */
535
	protected function getAddonCssClass()
536
	{
537
		$classes = array();
538
		if (isset($this->prependText)) {
539
			$classes[] = 'input-prepend';
540
		}
541
		if (isset($this->appendText)) {
542
			$classes[] = 'input-append';
543
		}
544
545
		return implode(' ', $classes);
546
	}
547
548
	/**
549
	 *### .hasAddOn()
550
	 *
551
	 * Returns whether the input has an add-on (prepend and/or append).
552
	 *
553
	 * @return boolean the result
554
	 */
555
	protected function hasAddOn()
556
	{
557
		return isset($this->prependText) || isset($this->appendText);
558
	}
559
560
	/**
561
	 *### .checkBox()
562
	 *
563
	 * Renders a checkbox.
564
	 *
565
	 * @return string the rendered content
566
	 * @abstract
567
	 */
568
	abstract protected function checkBox();
569
570
	/**
571
	 *### .toggleButton()
572
	 *
573
	 * Renders a toggle button.
574
	 *
575
	 * @return string the rendered content
576
	 * @abstract
577
	 */
578
	abstract protected function toggleButton();
579
580
	/**
581
	 *### .checkBoxList()
582
	 *
583
	 * Renders a list of checkboxes.
584
	 *
585
	 * @return string the rendered content
586
	 * @abstract
587
	 */
588
	abstract protected function checkBoxList();
589
590
	/**
591
	 *### .checkBoxListInline()
592
	 *
593
	 * Renders a list of inline checkboxes.
594
	 *
595
	 * @return string the rendered content
596
	 * @abstract
597
	 */
598
	abstract protected function checkBoxListInline();
599
600
	/**
601
	 *### .checkBoxGroupsList()
602
	 *
603
	 * Renders a list of checkboxes using Button Groups.
604
	 *
605
	 * @return string the rendered content
606
	 * @abstract
607
	 */
608
	abstract protected function checkBoxGroupsList();
609
610
	/**
611
	 *### .dropDownList()
612
	 *
613
	 * Renders a drop down list (select).
614
	 *
615
	 * @return string the rendered content
616
	 * @abstract
617
	 */
618
	abstract protected function dropDownList();
619
620
	/**
621
	 *### .fileField()
622
	 *
623
	 * Renders a file field.
624
	 *
625
	 * @return string the rendered content
626
	 * @abstract
627
	 */
628
	abstract protected function fileField();
629
630
	/**
631
	 *### .passwordField()
632
	 *
633
	 * Renders a password field.
634
	 *
635
	 * @return string the rendered content
636
	 * @abstract
637
	 */
638
	abstract protected function passwordField();
639
640
	/**
641
	 *### .passfieldField()
642
	 *
643
	 * Renders a Pass*Field field.
644
	 *
645
	 * @return string the rendered content
646
	 * @abstract
647
	 */
648
	abstract protected function passfieldField();
649
650
	/**
651
	 *### .radioButton()
652
	 *
653
	 * Renders a radio button.
654
	 *
655
	 * @return string the rendered content
656
	 * @abstract
657
	 */
658
	abstract protected function radioButton();
659
660
	/**
661
	 *### .radioButtonList()
662
	 *
663
	 * Renders a list of radio buttons.
664
	 *
665
	 * @return string the rendered content
666
	 * @abstract
667
	 */
668
	abstract protected function radioButtonList();
669
670
	/**
671
	 *### .radioButtonListInline()
672
	 *
673
	 * Renders a list of inline radio buttons.
674
	 *
675
	 * @return string the rendered content
676
	 * @abstract
677
	 */
678
	abstract protected function radioButtonListInline();
679
680
	/**
681
	 *### .radioButtonGroupsList()
682
	 *
683
	 * Renders a list of radio buttons using Button Groups.
684
	 *
685
	 * @return string the rendered content
686
	 * @abstract
687
	 */
688
	abstract protected function radioButtonGroupsList();
689
690
	/**
691
	 *### .textArea()
692
	 *
693
	 * Renders a textarea.
694
	 *
695
	 * @return string the rendered content
696
	 * @abstract
697
	 */
698
	abstract protected function textArea();
699
700
	/**
701
	 *### .textField()
702
	 *
703
	 * Renders a text field.
704
	 *
705
	 * @return string the rendered content
706
	 * @abstract
707
	 */
708
	abstract protected function textField();
709
710
	/**
711
	 *### .maskedTextField()
712
	 *
713
	 * Renders a masked text field.
714
	 *
715
	 * @return string the rendered content
716
	 * @abstract
717
	 */
718
	abstract protected function maskedTextField();
719
720
	/**
721
	 *### .captcha()
722
	 *
723
	 * Renders a CAPTCHA.
724
	 *
725
	 * @return string the rendered content
726
	 * @abstract
727
	 */
728
	abstract protected function captcha();
729
730
	/**
731
	 *### .uneditableField()
732
	 *
733
	 * Renders an uneditable field.
734
	 *
735
	 * @return string the rendered content
736
	 * @abstract
737
	 */
738
	abstract protected function uneditableField();
739
740
	/**
741
	 *### .datepicketField()
742
	 *
743
	 * Renders a datepicker field.
744
	 *
745
	 * @return string the rendered content
746
	 * @abstract
747
	 */
748
	abstract protected function datepickerField();
749
750
	/**
751
	 *### .datetimepicketField()
752
	 *
753
	 * Renders a datetimepicker field.
754
	 *
755
	 * @return string the rendered content
756
	 * @abstract
757
	 */
758
	abstract protected function datetimepickerField();
759
760
	/**
761
	 *### .redactorJs()
762
	 *
763
	 * Renders a redactorJS wysiwyg field.
764
	 *
765
	 * @abstract
766
	 * @return mixed
767
	 */
768
	abstract protected function redactorJs();
769
770
	/**
771
	 *### .markdownEditorJs()
772
	 *
773
	 * Renders a markdownEditorJS wysiwyg field.
774
	 *
775
	 * @abstract
776
	 * @return mixed
777
	 */
778
	abstract protected function markdownEditorJs();
779
780
	/**
781
	 *### .ckEditor()
782
	 *
783
	 * Renders a bootstrap CKEditor wysiwyg editor.
784
	 *
785
	 * @abstract
786
	 * @return mixed
787
	 */
788
	abstract protected function ckEditor();
789
790
	/**
791
	 *### .html5Editor()
792
	 *
793
	 * Renders a bootstrap wysihtml5 editor.
794
	 *
795
	 * @abstract
796
	 * @return mixed
797
	 */
798
	abstract protected function html5Editor();
799
800
	/**
801
	 *### .dateRangeField()
802
	 *
803
	 * Renders a daterange picker field
804
	 *
805
	 * @abstract
806
	 * @return mixed
807
	 */
808
	abstract protected function dateRangeField();
809
810
	/**
811
	 *### .colorpickerField()
812
	 *
813
	 * Renders a colorpicker field.
814
	 *
815
	 * @return string the rendered content
816
	 * @abstract
817
	 */
818
	abstract protected function colorpickerField();
819
820
	/**
821
	 *### .timepickerField()
822
	 *
823
	 * Renders a timepicker field.
824
	 *
825
	 * @return string the rendered content
826
	 * @abstract
827
	 */
828
	abstract protected function timepickerField();
829
830
	/**
831
	 *### .select2Field()
832
	 *
833
	 * Renders a select2 field.
834
	 *
835
	 * @return mixed
836
	 */
837
	abstract protected function select2Field();
838
839
	/**
840
	 * Renders a typeAhead field.
841
	 * @return mixed
842
	 */
843
	abstract protected function typeAheadField();
844
845
	/**
846
	 *### . numberField()
847
	 *
848
	 * Renders a number field.
849
	 *
850
	 * @return string the rendered content
851
	 * @abstract
852
	 */
853
	abstract protected function numberField();
854
855
	/**
856
	 *### . customField()
857
	 *
858
	 * Renders a pre-rendered custom field.
859
	 *
860
	 * @return string the rendered content
861
	 * @abstract
862
	 */
863
	abstract protected function customField();
864
865
	/**
866
	 * Obtain separately hidden and visible field
867
	 * @see TbInputVertical::checkBox
868
	 * @see TbInputHorizontal::checkBox
869
	 * @see TbInputVertical::radioButton
870
	 * @see TbInputHorizontal::radioButton
871
	 * @throws CException
872
	 * @return array
873
	 */
874
	protected function getSeparatedSelectableInput()
875
	{
876
		switch ($this->type)
877
		{
878
			case self::TYPE_CHECKBOX:
879
				$method = 'checkBox';
880
				break;
881
			case self::TYPE_RADIO:
882
				$method = 'radioButton';
883
				break;
884
			default:
885
				throw new CException('This method can be used with only selectable control', E_USER_ERROR);
886
		}
887
888
		$control = $this->form->{$method}($this->model, $this->attribute, $this->htmlOptions);
889
		$hidden  = '';
890
891
		$hasHiddenField = (array_key_exists('uncheckValue', $this->htmlOptions) && $this->htmlOptions['uncheckValue'] === null)
892
			? false
893
			: true;
894
895
		if ($hasHiddenField && preg_match('/\<input .*?type="hidden".*?\/\>/', $control, $matches))
896
		{
897
			$hidden = $matches[0];
898
			$control = str_replace($hidden, '', $control);
899
		}
900
901
		return array($hidden, $control);
902
	}
903
}
904