Browse Source

Merge pull request #2832 from markstory/3.0-radio

3.0 formhelper::radio()
José Lorenzo Rodríguez 12 years ago
parent
commit
4022d3d719

+ 16 - 105
src/View/Helper/FormHelper.php

@@ -173,6 +173,9 @@ class FormHelper extends Helper {
 		'formend' => '</form>',
 		'hiddenblock' => '<div style="display:none;">{{content}}</div>',
 		'input' => '<input type="{{type}}" name="{{name}}"{{attrs}}>',
+		'label' => '<label{{attrs}}>{{text}}</label>',
+		'radio' => '<input type="radio" name="{{name}}" value="{{value}}"{{attrs}}>',
+		'radioContainer' => '{{input}}{{label}}',
 		'textarea' => '<textarea name="{{name}}"{{attrs}}>{{value}}</textarea>',
 	];
 
@@ -1389,16 +1392,11 @@ class FormHelper extends Helper {
 	}
 
 /**
- * Creates a set of radio widgets. Will create a legend and fieldset
- * by default. Use $options to control this
+ * Creates a set of radio widgets.
  *
  * ### Attributes:
  *
- * - `separator` - define the string in between the radio buttons
- * - `between` - the string between legend and input set or array of strings to insert
- *    strings between each input block
- * - `legend` - control whether or not the widget set has a fieldset & legend
- * - `value` - indicate a value that is should be checked
+ * - `value` - Indicate a value that is should be checked
  * - `label` - boolean to indicate whether or not labels for widgets show be displayed
  * - `hiddenField` - boolean to indicate if you want the results of radio() to include
  *    a hidden input with a value of ''. This is useful for creating radio sets that non-continuous
@@ -1412,109 +1410,24 @@ class FormHelper extends Helper {
  * @return string Completed radio widget set.
  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#options-for-select-checkbox-and-radio-inputs
  */
-	public function radio($fieldName, $options = array(), $attributes = array()) {
+	public function radio($fieldName, $options = [], $attributes = []) {
 		$attributes = $this->_initInputField($fieldName, $attributes);
 
-		$showEmpty = $this->_extractOption('empty', $attributes);
-		if ($showEmpty) {
-			$showEmpty = ($showEmpty === true) ? __d('cake', 'empty') : $showEmpty;
-			$options = array('' => $showEmpty) + $options;
-		}
-		unset($attributes['empty']);
-
-		$legend = false;
-		if (isset($attributes['legend'])) {
-			$legend = $attributes['legend'];
-			unset($attributes['legend']);
-		} elseif (count($options) > 1) {
-			$legend = __(Inflector::humanize($this->field()));
-		}
-
-		$label = true;
-		if (isset($attributes['label'])) {
-			$label = $attributes['label'];
-			unset($attributes['label']);
-		}
-
-		$separator = null;
-		if (isset($attributes['separator'])) {
-			$separator = $attributes['separator'];
-			unset($attributes['separator']);
-		}
-
-		$between = null;
-		if (isset($attributes['between'])) {
-			$between = $attributes['between'];
-			unset($attributes['between']);
-		}
-
-		$value = null;
-		if (isset($attributes['value'])) {
-			$value = $attributes['value'];
-		} else {
-			$value = $this->value($fieldName);
-		}
-
-		$disabled = array();
-		if (isset($attributes['disabled'])) {
-			$disabled = $attributes['disabled'];
-		}
-
-		$out = array();
-
+		$out = [];
 		$hiddenField = isset($attributes['hiddenField']) ? $attributes['hiddenField'] : true;
 		unset($attributes['hiddenField']);
 
-		if (isset($value) && is_bool($value)) {
-			$value = $value ? 1 : 0;
+		$value = $attributes['val'];
+		$hidden = '';
+		if ($hiddenField && (!isset($value) || $value === '')) {
+			$hidden = $this->hidden($fieldName, [
+				'value' => '',
+				'name' => $attributes['name']
+			]);
 		}
+		$attributes['options'] = $options;
 
-		$this->_domIdSuffixes = array();
-		foreach ($options as $optValue => $optTitle) {
-			$optionsHere = array('value' => $optValue, 'disabled' => false);
-
-			if (isset($value) && strval($optValue) === strval($value)) {
-				$optionsHere['checked'] = 'checked';
-			}
-			$isNumeric = is_numeric($optValue);
-			if ($disabled && (!is_array($disabled) || in_array((string)$optValue, $disabled, !$isNumeric))) {
-				$optionsHere['disabled'] = true;
-			}
-			$tagName = $attributes['id'] . $this->domIdSuffix($optValue);
-
-			if ($label) {
-				$labelOpts = is_array($label) ? $label : array();
-				$labelOpts += array('for' => $tagName);
-				$optTitle = $this->label($tagName, $optTitle, $labelOpts);
-			}
-
-			if (is_array($between)) {
-				$optTitle .= array_shift($between);
-			}
-			$allOptions = array_merge($attributes, $optionsHere);
-			$out[] = $this->Html->useTag('radio', $attributes['name'], $tagName,
-				array_diff_key($allOptions, array('name' => null, 'type' => null, 'id' => null)),
-				$optTitle
-			);
-		}
-		$hidden = null;
-
-		if ($hiddenField) {
-			if (!isset($value) || $value === '') {
-				$hidden = $this->hidden($fieldName, array(
-					'id' => $attributes['id'] . '_', 'value' => '', 'name' => $attributes['name']
-				));
-			}
-		}
-		$out = $hidden . implode($separator, $out);
-
-		if (is_array($between)) {
-			$between = '';
-		}
-		if ($legend) {
-			$out = $this->Html->useTag('fieldset', '', $this->Html->useTag('legend', $legend) . $between . $out);
-		}
-		return $out;
+		return $hidden . $this->widget('radio', $attributes);
 	}
 
 /**
@@ -2879,8 +2792,6 @@ class FormHelper extends Helper {
 			unset($options['default']);
 		}
 
-		$options += (array)$context->attributes($field);
-
 		if ($context->hasError($field)) {
 			$options = $this->addClass($options, $this->settings['errorClass']);
 		}

+ 7 - 3
src/View/Helper/PaginatorHelper.php

@@ -426,9 +426,13 @@ class PaginatorHelper extends Helper {
 		if (!empty($url['page']) && $url['page'] == 1) {
 			$url['page'] = null;
 		}
-		if (isset($paging['sortDefault'], $paging['directionDefault'], $url['sort'], $url['direction']) && $url['sort'] === $paging['sortDefault'] && $url['direction'] === $paging['directionDefault'] ) {
-  			$url['sort'] = $url['direction'] = null;
-  		}
+		if (
+			isset($paging['sortDefault'], $paging['directionDefault'], $url['sort'], $url['direction']) &&
+			$url['sort'] === $paging['sortDefault'] &&
+			$url['direction'] === $paging['directionDefault']
+		) {
+			$url['sort'] = $url['direction'] = null;
+		}
 		return parent::url($url);
 	}
 

+ 38 - 1
src/View/Widget/Radio.php

@@ -41,6 +41,13 @@ class Radio implements WidgetInterface {
 	protected $_label;
 
 /**
+ * A list of id suffixes used in the current rendering.
+ *
+ * @var array
+ */
+	protected $_idSuffixes = [];
+
+/**
  * Constructor
  *
  * This class uses a few templates:
@@ -71,6 +78,8 @@ class Radio implements WidgetInterface {
  * - `val` - A string of the option to mark as selected.
  * - `label` - Either false to disable label generation, or
  *   an array of attributes for all labels.
+ * - `required` - Set to true to add the required attribute
+ *   on all generated radios.
  *
  * @param array $data The data to build radio buttons with.
  * @return string
@@ -97,6 +106,7 @@ class Radio implements WidgetInterface {
 		}
 		unset($data['empty']);
 
+		$this->_idSuffixes = [];
 		$opts = [];
 		foreach ($options as $val => $text) {
 			$opts[] = $this->_renderInput($val, $text, $data);
@@ -141,7 +151,11 @@ class Radio implements WidgetInterface {
 		$radio['name'] = $data['name'];
 
 		if (empty($radio['id'])) {
-			$radio['id'] = mb_strtolower(Inflector::slug($radio['name'] . '_' . $radio['value'], '-'));
+			$radio['id'] = $this->_id($radio);
+		}
+
+		if (isset($data['val']) && is_bool($data['val'])) {
+			$data['val'] = $data['val'] ? 1 : 0;
 		}
 
 		if (isset($data['val']) && strval($data['val']) === strval($radio['value'])) {
@@ -151,6 +165,9 @@ class Radio implements WidgetInterface {
 		if ($this->_isDisabled($radio, $data['disabled'])) {
 			$radio['disabled'] = true;
 		}
+		if (!empty($data['required'])) {
+			$radio['required'] = true;
+		}
 
 		$input = $this->_templates->format('radio', [
 			'name' => $radio['name'],
@@ -197,4 +214,24 @@ class Radio implements WidgetInterface {
 		return $this->_label->render($labelAttrs);
 	}
 
+/**
+ * Generate an ID attribute for a radio button.
+ *
+ * Ensures that id's for a given set of fields are unique.
+ *
+ * @param array $radio The radio properties.
+ * @return string Generated id.
+ */
+	protected function _id($radio) {
+		$value = mb_strtolower(Inflector::slug($radio['name'], '-'));
+		$idSuffix = mb_strtolower(str_replace(array('@', '<', '>', ' ', '"', '\''), '-', $radio['value']));
+		$count = 1;
+		$check = $idSuffix;
+		while (in_array($check, $this->_idSuffixes)) {
+			$check = $idSuffix . $count++;
+		}
+		$this->_idSuffixes[] = $check;
+		return trim($value . '-' . $check, '-');
+	}
+
 }

+ 21 - 647
tests/TestCase/View/Helper/FormHelperTest.php

@@ -4234,554 +4234,55 @@ class FormHelperTest extends TestCase {
  * @return void
  */
 	public function testRadio() {
-		$this->markTestIncomplete('Need to revisit once models work again.');
 		$result = $this->Form->radio('Model.field', array('option A'));
 		$expected = array(
-			'input' => array('type' => 'hidden', 'name' => 'Model[field]', 'value' => '', 'id' => 'ModelField_'),
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'ModelField0')),
-			'label' => array('for' => 'ModelField0'),
+			'input' => array('type' => 'hidden', 'name' => 'Model[field]', 'value' => ''),
+			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'model-field-0')),
+			'label' => array('for' => 'model-field-0'),
 			'option A',
 			'/label'
 		);
 		$this->assertTags($result, $expected);
 
-		$result = $this->Form->radio('Model.field', array('1/2' => 'half'));
-		$expected = array(
-			'input' => array('type' => 'hidden', 'name' => 'Model[field]', 'value' => '', 'id' => 'ModelField_'),
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '1/2', 'id' => 'ModelField1/2')),
-			'label' => array('for' => 'ModelField1/2'),
-			'half',
-			'/label'
-		);
-		$this->assertTags($result, $expected);
-
 		$result = $this->Form->radio('Model.field', array('option A', 'option B'));
 		$expected = array(
-			'fieldset' => array(),
-			'legend' => array(),
-			'Field',
-			'/legend',
-			'input' => array('type' => 'hidden', 'name' => 'Model[field]', 'value' => '', 'id' => 'ModelField_'),
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'ModelField0')),
-			array('label' => array('for' => 'ModelField0')),
-			'option A',
-			'/label',
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'ModelField1')),
-			array('label' => array('for' => 'ModelField1')),
-			'option B',
-			'/label',
-			'/fieldset'
-		);
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->radio('Model.field', array('option A', 'option B'), array('separator' => '<br/>'));
-		$expected = array(
-			'fieldset' => array(),
-			'legend' => array(),
-			'Field',
-			'/legend',
-			'input' => array('type' => 'hidden', 'name' => 'Model[field]', 'value' => '', 'id' => 'ModelField_'),
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'ModelField0')),
-			array('label' => array('for' => 'ModelField0')),
+			'input' => array('type' => 'hidden', 'name' => 'Model[field]', 'value' => ''),
+			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'model-field-0')),
+			array('label' => array('for' => 'model-field-0')),
 			'option A',
 			'/label',
-			'br' => array(),
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'ModelField1')),
-			array('label' => array('for' => 'ModelField1')),
+			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'model-field-1')),
+			array('label' => array('for' => 'model-field-1')),
 			'option B',
 			'/label',
-			'/fieldset'
 		);
 		$this->assertTags($result, $expected);
 
 		$result = $this->Form->radio('Employee.gender', array('male' => 'Male', 'female' => 'Female'));
 		$expected = array(
-			'fieldset' => array(),
-			'legend' => array(),
-			'Gender',
-			'/legend',
-			'input' => array('type' => 'hidden', 'name' => 'Employee[gender]', 'value' => '', 'id' => 'EmployeeGender_'),
-			array('input' => array('type' => 'radio', 'name' => 'Employee[gender]', 'value' => 'male', 'id' => 'EmployeeGenderMale')),
-			array('label' => array('for' => 'EmployeeGenderMale')),
-			'Male',
-			'/label',
-			array('input' => array('type' => 'radio', 'name' => 'Employee[gender]', 'value' => 'female', 'id' => 'EmployeeGenderFemale')),
-			array('label' => array('for' => 'EmployeeGenderFemale')),
-			'Female',
-			'/label',
-			'/fieldset',
-		);
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->radio('Officer.gender', array('male' => 'Male', 'female' => 'Female'));
-		$expected = array(
-			'fieldset' => array(),
-			'legend' => array(),
-			'Gender',
-			'/legend',
-			'input' => array('type' => 'hidden', 'name' => 'Officer[gender]', 'value' => '', 'id' => 'OfficerGender_'),
-			array('input' => array('type' => 'radio', 'name' => 'Officer[gender]', 'value' => 'male', 'id' => 'OfficerGenderMale')),
-			array('label' => array('for' => 'OfficerGenderMale')),
+			'input' => array('type' => 'hidden', 'name' => 'Employee[gender]', 'value' => ''),
+			array('input' => array('type' => 'radio', 'name' => 'Employee[gender]', 'value' => 'male', 'id' => 'employee-gender-male')),
+			array('label' => array('for' => 'employee-gender-male')),
 			'Male',
 			'/label',
-			array('input' => array('type' => 'radio', 'name' => 'Officer[gender]', 'value' => 'female', 'id' => 'OfficerGenderFemale')),
-			array('label' => array('for' => 'OfficerGenderFemale')),
+			array('input' => array('type' => 'radio', 'name' => 'Employee[gender]', 'value' => 'female', 'id' => 'employee-gender-female')),
+			array('label' => array('for' => 'employee-gender-female')),
 			'Female',
 			'/label',
-			'/fieldset',
-		);
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->radio('Contact.1.imrequired', array('option A'));
-		$expected = array(
-			'input' => array('type' => 'hidden', 'name' => 'Contact[1][imrequired]', 'value' => '', 'id' => 'Contact1Imrequired_'),
-			array('input' => array('type' => 'radio', 'name' => 'Contact[1][imrequired]', 'value' => '0', 'id' => 'Contact1Imrequired0', 'required' => 'required')),
-			'label' => array('for' => 'Contact1Imrequired0'),
-			'option A',
-			'/label'
-		);
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->radio('Model.1.field', array('option A'));
-		$expected = array(
-			'input' => array('type' => 'hidden', 'name' => 'Model[1][field]', 'value' => '', 'id' => 'Model1Field_'),
-			array('input' => array('type' => 'radio', 'name' => 'Model[1][field]', 'value' => '0', 'id' => 'Model1Field0')),
-			'label' => array('for' => 'Model1Field0'),
-			'option A',
-			'/label'
 		);
 		$this->assertTags($result, $expected);
 
 		$result = $this->Form->radio('Model.field', array('option A', 'option B'), array('name' => 'Model[custom]'));
 		$expected = array(
-			'fieldset' => array(),
-			'legend' => array(),
-			'Field',
-			'/legend',
-			'input' => array('type' => 'hidden', 'name' => 'Model[custom]', 'value' => '', 'id' => 'ModelField_'),
-			array('input' => array('type' => 'radio', 'name' => 'Model[custom]', 'value' => '0', 'id' => 'ModelField0')),
-			array('label' => array('for' => 'ModelField0')),
-			'option A',
-			'/label',
-			array('input' => array('type' => 'radio', 'name' => 'Model[custom]', 'value' => '1', 'id' => 'ModelField1')),
-			array('label' => array('for' => 'ModelField1')),
-			'option B',
-			'/label',
-			'/fieldset'
-		);
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->radio(
-			'Model.field',
-			array('a>b' => 'first', 'a<b' => 'second', 'a"b' => 'third')
-		);
-		$expected = array(
-			'fieldset' => array(),
-			'legend' => array(),
-			'Field',
-			'/legend',
-			'input' => array(
-				'type' => 'hidden', 'name' => 'data[Model][field]',
-				'id' => 'ModelField_', 'value' => '',
-			),
-			array('input' => array('type' => 'radio', 'name' => 'data[Model][field]',
-				'id' => 'ModelFieldAB', 'value' => 'a&gt;b')),
-			array('label' => array('for' => 'ModelFieldAB')),
-			'first',
-			'/label',
-			array('input' => array('type' => 'radio', 'name' => 'data[Model][field]',
-				'id' => 'ModelFieldAB1', 'value' => 'a&lt;b')),
-			array('label' => array('for' => 'ModelFieldAB1')),
-			'second',
-			'/label',
-			array('input' => array('type' => 'radio', 'name' => 'data[Model][field]',
-				'id' => 'ModelFieldAB2', 'value' => 'a&quot;b')),
-			array('label' => array('for' => 'ModelFieldAB2')),
-			'third',
-			'/label',
-			'/fieldset'
-		);
-		$this->assertTags($result, $expected);
-	}
-
-/**
- * Test radio inputs with between as string or array. Also ensure
- * that an array with less between elements works.
- *
- * @return void
- */
-	public function testRadioBetween() {
-		$this->markTestIncomplete('Need to revisit once models work again.');
-		$result = $this->Form->radio(
-			'Model.field',
-			array('option A', 'option B'),
-			array('between' => 'I am between')
-		);
-		$expected = array(
-			'fieldset' => array(),
-			'legend' => array(),
-			'Field',
-			'/legend',
-			'I am between',
-			'input' => array(
-				'type' => 'hidden', 'name' => 'Model[field]',
-				'value' => '', 'id' => 'ModelField_'
-			),
-			array('input' => array(
-				'type' => 'radio', 'name' => 'Model[field]',
-				'value' => '0', 'id' => 'ModelField0'
-			)),
-			array('label' => array('for' => 'ModelField0')),
-			'option A',
-			'/label',
-			array('input' => array(
-				'type' => 'radio', 'name' => 'Model[field]',
-				'value' => '1', 'id' => 'ModelField1'
-			)),
-			array('label' => array('for' => 'ModelField1')),
-			'option B',
-			'/label',
-			'/fieldset'
-		);
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->radio(
-			'Model.field',
-			array('option A', 'option B', 'option C'),
-			array('separator' => '--separator--', 'between' => array('between A', 'between B', 'between C'))
-		);
-
-		$expected = array(
-			'fieldset' => array(),
-			'legend' => array(),
-			'Field',
-			'/legend',
-			'input' => array(
-				'type' => 'hidden', 'name' => 'Model[field]',
-				'value' => '', 'id' => 'ModelField_'
-			),
-			array('input' => array(
-				'type' => 'radio', 'name' => 'Model[field]',
-				'value' => '0', 'id' => 'ModelField0'
-			)),
-			array('label' => array('for' => 'ModelField0')),
-			'option A',
-			'/label',
-			'between A',
-			'--separator--',
-			array('input' => array(
-				'type' => 'radio', 'name' => 'Model[field]',
-				'value' => '1', 'id' => 'ModelField1'
-			)),
-			array('label' => array('for' => 'ModelField1')),
-			'option B',
-			'/label',
-			'between B',
-			'--separator--',
-			array('input' => array(
-				'type' => 'radio', 'name' => 'Model[field]',
-				'value' => '2', 'id' => 'ModelField2'
-			)),
-			array('label' => array('for' => 'ModelField2')),
-			'option C',
-			'/label',
-			'between C',
-			'/fieldset'
-		);
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->input('Model.field', array(
-			'options' => array('1' => 'first', '2' => 'second'),
-			'type' => 'radio',
-			'before' => '--before--',
-			'after' => '--after--',
-			'separator' => '--separator--',
-			'between' => array('--between first--', '--between second--')
-		));
-
-		$expected = array(
-			'div' => array('class' => 'input radio'),
-			'--before--',
-			'fieldset' => array(),
-			'legend' => array(),
-			'Field',
-			'/legend',
-			array('input' => array('type' => 'hidden', 'name' => 'Model[field]', 'id' => 'ModelField_', 'value' => '')),
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'ModelField1')),
-			array('label' => array('for' => 'ModelField1')),
-			'first',
-			'/label',
-			'--between first--',
-			'--separator--',
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '2', 'id' => 'ModelField2')),
-			array('label' => array('for' => 'ModelField2')),
-			'second',
-			'/label',
-			'--between second--',
-			'/fieldset',
-			'--after--',
-			'/div'
-		);
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->input('Model.field', array(
-			'options' => array('1' => 'first', '2' => 'second'),
-			'type' => 'radio',
-			'before' => '--before--',
-			'after' => '--after--',
-			'separator' => '--separator--',
-			'between' => array('--between first--')
-		));
-
-		$expected = array(
-			'div' => array('class' => 'input radio'),
-			'--before--',
-			'fieldset' => array(),
-			'legend' => array(),
-			'Field',
-			'/legend',
-			array('input' => array('type' => 'hidden', 'name' => 'Model[field]', 'id' => 'ModelField_', 'value' => '')),
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'ModelField1')),
-			array('label' => array('for' => 'ModelField1')),
-			'first',
-			'/label',
-			'--between first--',
-			'--separator--',
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '2', 'id' => 'ModelField2')),
-			array('label' => array('for' => 'ModelField2')),
-			'second',
-			'/label',
-			'/fieldset',
-			'--after--',
-			'/div'
-		);
-		$this->assertTags($result, $expected);
-	}
-
-/**
- * Test that radios with a 0 value are selected under the correct conditions.
- * Also ensure that values that are booleanish are handled correctly.
- *
- * @return void
- */
-	public function testRadioOptionWithBooleanishValues() {
-		$this->markTestIncomplete('Need to revisit once models work again.');
-		$expected = array(
-			'fieldset' => array(),
-			'legend' => array(),
-			'Field',
-			'/legend',
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'ModelField1')),
-			array('label' => array('for' => 'ModelField1')),
-			'Yes',
-			'/label',
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'ModelField0', 'checked' => 'checked')),
-			array('label' => array('for' => 'ModelField0')),
-			'No',
-			'/label',
-			'/fieldset'
-		);
-		$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => '0'));
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => 0));
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => false));
-		$this->assertTags($result, $expected);
-
-		$expected = array(
-			'fieldset' => array(),
-			'legend' => array(),
-			'Field',
-			'/legend',
-			'input' => array('type' => 'hidden', 'name' => 'Model[field]', 'value' => '', 'id' => 'ModelField_'),
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'ModelField1')),
-			array('label' => array('for' => 'ModelField1')),
-			'Yes',
-			'/label',
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'ModelField0')),
-			array('label' => array('for' => 'ModelField0')),
-			'No',
-			'/label',
-			'/fieldset'
-		);
-		$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => null));
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => ''));
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'));
-		$this->assertTags($result, $expected);
-
-		$expected = array(
-			'fieldset' => array(),
-			'legend' => array(),
-			'Field',
-			'/legend',
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'checked' => 'checked', 'value' => '1', 'id' => 'ModelField1')),
-			array('label' => array('for' => 'ModelField1')),
-			'Yes',
-			'/label',
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'ModelField0')),
-			array('label' => array('for' => 'ModelField0')),
-			'No',
-			'/label',
-			'/fieldset'
-		);
-		$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => 1));
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => '1'));
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => true));
-		$this->assertTags($result, $expected);
-	}
-
-/**
- * test disabled radio options
- *
- * @return void
- */
-	public function testRadioDisabled() {
-		$this->markTestIncomplete('Need to revisit once models work again.');
-		$result = $this->Form->radio(
-			'Model.field',
-			array('option A', 'option B'),
-			array('disabled' => array(0), 'value' => '0')
-		);
-		$expected = array(
-			'fieldset' => array(),
-			'legend' => array(),
-			'Field',
-			'/legend',
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'ModelField0', 'disabled' => 'disabled', 'checked' => 'checked')),
-			array('label' => array('for' => 'ModelField0')),
-			'option A',
-			'/label',
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'ModelField1')),
-			array('label' => array('for' => 'ModelField1')),
-			'option B',
-			'/label',
-			'/fieldset'
-		);
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->radio(
-			'Model.field',
-			array('option A', 'option B'),
-			array('disabled' => true, 'value' => '0')
-		);
-		$expected = array(
-			'fieldset' => array(),
-			'legend' => array(),
-			'Field',
-			'/legend',
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'ModelField0', 'disabled' => 'disabled', 'checked' => 'checked')),
-			array('label' => array('for' => 'ModelField0')),
-			'option A',
-			'/label',
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'ModelField1', 'disabled' => 'disabled')),
-			array('label' => array('for' => 'ModelField1')),
-			'option B',
-			'/label',
-			'/fieldset'
-		);
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->radio(
-			'Model.field',
-			array('option A', 'option B'),
-			array('disabled' => 'disabled', 'value' => '0')
-		);
-		$expected = array(
-			'fieldset' => array(),
-			'legend' => array(),
-			'Field',
-			'/legend',
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'ModelField0', 'disabled' => 'disabled', 'checked' => 'checked')),
-			array('label' => array('for' => 'ModelField0')),
+			array('input' => array('type' => 'hidden', 'name' => 'Model[custom]', 'value' => '')),
+			array('input' => array('type' => 'radio', 'name' => 'Model[custom]', 'value' => '0', 'id' => 'model-custom-0')),
+			array('label' => array('for' => 'model-custom-0')),
 			'option A',
 			'/label',
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'ModelField1', 'disabled' => 'disabled')),
-			array('label' => array('for' => 'ModelField1')),
+			array('input' => array('type' => 'radio', 'name' => 'Model[custom]', 'value' => '1', 'id' => 'model-custom-1')),
+			array('label' => array('for' => 'model-custom-1')),
 			'option B',
 			'/label',
-			'/fieldset'
-		);
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->input('Model.field', array(
-			'options' => array(1 => 'first', 2 => 'second', '2x' => '2x', '3' => 'third', '3x' => '3x'),
-			'type' => 'radio',
-			'disabled' => array(2, '3x'),
-		));
-
-		$expected = array(
-			'div' => array('class' => 'input radio'),
-			'fieldset' => array(),
-			'legend' => array(),
-			'Field',
-			'/legend',
-			array('input' => array('type' => 'hidden', 'name' => 'Model[field]', 'id' => 'ModelField_', 'value' => '')),
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'ModelField1')),
-			array('label' => array('for' => 'ModelField1')),
-			'first',
-			'/label',
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'disabled' => 'disabled', 'value' => '2', 'id' => 'ModelField2')),
-			array('label' => array('for' => 'ModelField2')),
-			'second',
-			'/label',
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '2x', 'id' => 'ModelField2x')),
-			array('label' => array('for' => 'ModelField2x')),
-			'2x',
-			'/label',
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '3', 'id' => 'ModelField3')),
-			array('label' => array('for' => 'ModelField3')),
-			'third',
-			'/label',
-			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'disabled' => 'disabled', 'value' => '3x', 'id' => 'ModelField3x')),
-			array('label' => array('for' => 'ModelField3x')),
-			'3x',
-			'/label',
-			'/fieldset',
-			'/div'
-		);
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->input('Model.field', array(
-			'type' => 'radio',
-			'options' => array(
-				1 => 'A',
-				2 => 'B',
-				3 => 'C'
-			),
-			'disabled' => array(1)
-		));
-
-		$expected = array(
-			'div' => array('class' => 'input radio'),
-			'fieldset' => array(),
-			'legend' => array(),
-			'Field',
-			'/legend',
-			array('input' => array('type' => 'hidden', 'name' => 'data[Model][field]', 'id' => 'ModelField_', 'value' => '')),
-			array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'id' => 'ModelField1', 'disabled' => 'disabled', 'value' => '1')),
-			array('label' => array('for' => 'ModelField1')),
-			'A',
-			'/label',
-			array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'id' => 'ModelField2', 'value' => '2')),
-			array('label' => array('for' => 'ModelField2')),
-			'B',
-			'/label',
-			array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'id' => 'ModelField3', 'value' => '3')),
-			array('label' => array('for' => 'ModelField3')),
-			'C',
-			'/label',
-			'/fieldset',
-			'/div'
 		);
 		$this->assertTags($result, $expected);
 	}
@@ -4792,27 +4293,10 @@ class FormHelperTest extends TestCase {
  * @return void
  */
 	public function testRadioHiddenInputDisabling() {
-		$this->markTestIncomplete('Need to revisit once models work again.');
-		$result = $this->Form->input('Model.1.field', array(
-				'type' => 'radio',
-				'options' => array('option A'),
-				'hiddenField' => false
-			)
-		);
-		$expected = array(
-			'div' => array('class' => 'input radio'),
-			'input' => array('type' => 'radio', 'name' => 'Model[1][field]', 'value' => '0', 'id' => 'Model1Field0'),
-			'label' => array('for' => 'Model1Field0'),
-			'option A',
-			'/label',
-			'/div'
-		);
-		$this->assertTags($result, $expected);
-
 		$result = $this->Form->radio('Model.1.field', array('option A'), array('hiddenField' => false));
 		$expected = array(
-			'input' => array('type' => 'radio', 'name' => 'Model[1][field]', 'value' => '0', 'id' => 'Model1Field0'),
-			'label' => array('for' => 'Model1Field0'),
+			'input' => array('type' => 'radio', 'name' => 'Model[1][field]', 'value' => '0', 'id' => 'model-1-field-0'),
+			'label' => array('for' => 'model-1-field-0'),
 			'option A',
 			'/label'
 		);
@@ -4820,116 +4304,6 @@ class FormHelperTest extends TestCase {
 	}
 
 /**
- * test adding an empty option for radio buttons
- *
- * @return void
- */
-	public function testRadioAddEmptyOption() {
-		$this->markTestIncomplete('Need to revisit once models work again.');
-		$result = $this->Form->input('Model.1.field', array(
-			'type' => 'radio',
-			'options' => array('option A'),
-			'empty' => true,
-			'hiddenField' => false
-		));
-		$expected = array(
-			'div' => array('class' => 'input radio'),
-				'fieldset' => array(),
-					'legend' => array(),
-						'Field',
-					'/legend',
-					array('input' => array('type' => 'radio', 'name' => 'Model[1][field]', 'value' => '', 'id' => 'Model1Field')),
-					array('label' => array('for' => 'Model1Field')),
-						__('empty'),
-					'/label',
-					array('input' => array('type' => 'radio', 'name' => 'Model[1][field]', 'value' => '0', 'id' => 'Model1Field0')),
-					array('label' => array('for' => 'Model1Field0')),
-						'option A',
-					'/label',
-				'/fieldset',
-			'/div'
-		);
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->input('Model.1.field', array(
-			'type' => 'radio',
-			'options' => array('option A'),
-			'empty' => 'CustomEmptyLabel',
-			'hiddenField' => false
-		));
-		$expected = array(
-			'div' => array('class' => 'input radio'),
-				'fieldset' => array(),
-					'legend' => array(),
-						'Field',
-					'/legend',
-					array('input' => array('type' => 'radio', 'name' => 'Model[1][field]', 'value' => '', 'id' => 'Model1Field')),
-					array('label' => array('for' => 'Model1Field')),
-						'CustomEmptyLabel',
-					'/label',
-					array('input' => array('type' => 'radio', 'name' => 'Model[1][field]', 'value' => '0', 'id' => 'Model1Field0')),
-					array('label' => array('for' => 'Model1Field0')),
-						'option A',
-					'/label',
-				'/fieldset',
-			'/div'
-		);
-
-		$this->assertTags($result, $expected);
-
-		$result = $this->Form->input('Model.1.field', array(
-			'type' => 'radio',
-			'options' => array('option A'),
-			'empty' => false,
-			'hiddenField' => false
-		));
-		$this->assertTextNotContains('"Model1Field"', $result);
-	}
-
-/**
- * Test that radio() accepts an array for label
- *
- * @return void
- */
-	public function testRadioLabelArray() {
-		$this->markTestIncomplete('Need to revisit once models work again.');
-		$result = $this->Form->input('Model.field', array(
-			'type' => 'radio',
-			'legend' => false,
-			'label' => array(
-				'class' => 'checkbox float-left',
-			),
-			'options' => array('1' => 'Option A', '2' => 'Option B.')
-		));
-		$this->assertTextContains(
-			'<label for="ModelField1" class="checkbox float-left">Option A</label>',
-			$result
-		);
-	}
-
-/**
- * Test that label id's match the input element id's when radio is called after create().
- *
- * @return void
- */
-	public function testRadioWithCreate() {
-		$this->markTestIncomplete('Need to revisit once models work again.');
-		$this->Form->create('Model');
-		$result = $this->Form->radio('recipient',
-			array('1' => '1', '2' => '2', '3' => '3'),
-			array('legend' => false, 'value' => '1')
-		);
-		$this->assertTextNotContains(
-			'<label for="ModelModelRecipient1">1</label>',
-			$result
-		);
-		$this->assertTextContains(
-			'<label for="ModelRecipient1">1</label>',
-			$result
-		);
-	}
-
-/**
  * testDomIdSuffix method
  *
  * @return void
@@ -9595,7 +8969,7 @@ class FormHelperTest extends TestCase {
 	}
 
 /**
- * Test accessing htm5 inputs through input().
+ * Test accessing html5 inputs through input().
  *
  * @return void
  */

+ 138 - 0
tests/TestCase/View/Widget/RadioTest.php

@@ -124,6 +124,144 @@ class RadioTest extends TestCase {
 	}
 
 /**
+ * Test that id suffixes are generated to not collide
+ *
+ * @return void
+ */
+	public function testRenderIdSuffixGeneration() {
+		$label = new Label($this->templates);
+		$radio = new Radio($this->templates, $label);
+		$data = [
+			'name' => 'Thing[value]',
+			'options' => ['a>b' => 'First', 'a<b' => 'Second']
+		];
+		$result = $radio->render($data);
+		$expected = [
+			['input' => [
+				'type' => 'radio',
+				'name' => 'Thing[value]',
+				'value' => 'a&gt;b',
+				'id' => 'thing-value-a-b'
+			]],
+			['label' => ['for' => 'thing-value-a-b']],
+			'First',
+			'/label',
+			['input' => [
+				'type' => 'radio',
+				'name' => 'Thing[value]',
+				'value' => 'a&lt;b',
+				'id' => 'thing-value-a-b1',
+			]],
+			['label' => ['for' => 'thing-value-a-b1']],
+			'Second',
+			'/label',
+		];
+		$this->assertTags($result, $expected);
+	}
+
+/**
+ * Test rendering checks the right option with booleanish values.
+ *
+ * @return void
+ */
+	public function testRenderBooleanishValues() {
+		$label = new Label($this->templates);
+		$radio = new Radio($this->templates, $label);
+		$data = [
+			'name' => 'Model[field]',
+			'options' => ['1' => 'Yes', '0' => 'No'],
+			'val' => '0'
+		];
+		$result = $radio->render($data);
+		$expected = array(
+			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'model-field-1')),
+			array('label' => array('for' => 'model-field-1')),
+			'Yes',
+			'/label',
+			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'model-field-0', 'checked' => 'checked')),
+			array('label' => array('for' => 'model-field-0')),
+			'No',
+			'/label',
+		);
+		$this->assertTags($result, $expected);
+
+		$data['val'] = 0;
+		$result = $radio->render($data);
+		$this->assertTags($result, $expected);
+
+		$data['val'] = false;
+		$result = $radio->render($data);
+		$this->assertTags($result, $expected);
+
+		$expected = array(
+			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'model-field-1')),
+			array('label' => array('for' => 'model-field-1')),
+			'Yes',
+			'/label',
+			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'model-field-0')),
+			array('label' => array('for' => 'model-field-0')),
+			'No',
+			'/label',
+		);
+		$data['val'] = null;
+		$result = $radio->render($data);
+		$this->assertTags($result, $expected);
+
+		$data['val'] = '';
+		$result = $radio->render($data);
+		$this->assertTags($result, $expected);
+
+		$expected = array(
+			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '1', 'id' => 'model-field-1', 'checked' => 'checked')),
+			array('label' => array('for' => 'model-field-1')),
+			'Yes',
+			'/label',
+			array('input' => array('type' => 'radio', 'name' => 'Model[field]', 'value' => '0', 'id' => 'model-field-0')),
+			array('label' => array('for' => 'model-field-0')),
+			'No',
+			'/label',
+		);
+		$data['val'] = '1';
+		$result = $radio->render($data);
+		$this->assertTags($result, $expected);
+
+		$data['val'] = 1;
+		$result = $radio->render($data);
+		$this->assertTags($result, $expected);
+
+		$data['val'] = true;
+		$result = $radio->render($data);
+		$this->assertTags($result, $expected);
+	}
+
+/**
+ * Test that render() works with the required attribute.
+ *
+ * @return void
+ */
+	public function testRenderRequired() {
+		$label = new Label($this->templates);
+		$radio = new Radio($this->templates, $label);
+		$data = [
+			'name' => 'published',
+			'options' => ['option A', 'option B'],
+			'required' => true
+		];
+		$result = $radio->render($data);
+		$expected = [
+			['input' => ['type' => 'radio', 'name' => 'published', 'value' => '0', 'id' => 'published-0', 'required' => 'required']],
+			['label' => ['for' => 'published-0']],
+			'option A',
+			'/label',
+			['input' => ['type' => 'radio', 'name' => 'published', 'value' => '1', 'id' => 'published-1', 'required' => 'required']],
+			['label' => ['for' => 'published-1']],
+			'option B',
+			'/label',
+		];
+		$this->assertTags($result, $expected);
+	}
+
+/**
  * Test rendering the empty option.
  *
  * @return void