summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--includes/form.inc75
-rw-r--r--modules/comment/comment.module15
-rw-r--r--modules/simpletest/tests/form.test60
-rw-r--r--modules/simpletest/tests/form_test.module71
4 files changed, 174 insertions, 47 deletions
diff --git a/includes/form.inc b/includes/form.inc
index 8bf2ba072..e3a217bda 100644
--- a/includes/form.inc
+++ b/includes/form.inc
@@ -2786,22 +2786,28 @@ function weight_value(&$form) {
*/
function form_process_radios($element) {
if (count($element['#options']) > 0) {
+ $weight = 0;
foreach ($element['#options'] as $key => $choice) {
- if (!isset($element[$key])) {
- // Generate the parents as the autogenerator does, so we will have a
- // unique id for each radio button.
- $parents_for_id = array_merge($element['#parents'], array($key));
- $element[$key] = array(
- '#type' => 'radio',
- '#title' => $choice,
- '#return_value' => check_plain($key),
- '#default_value' => isset($element['#default_value']) ? $element['#default_value'] : NULL,
- '#attributes' => $element['#attributes'],
- '#parents' => $element['#parents'],
- '#id' => drupal_html_id('edit-' . implode('-', $parents_for_id)),
- '#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL,
- );
- }
+ // Maintain order of options as defined in #options, in case the element
+ // defines custom option sub-elements, but does not define all option
+ // sub-elements.
+ $weight += 0.001;
+
+ $element += array($key => array());
+ // Generate the parents as the autogenerator does, so we will have a
+ // unique id for each radio button.
+ $parents_for_id = array_merge($element['#parents'], array($key));
+ $element[$key] += array(
+ '#type' => 'radio',
+ '#title' => $choice,
+ '#return_value' => check_plain($key),
+ '#default_value' => isset($element['#default_value']) ? $element['#default_value'] : NULL,
+ '#attributes' => $element['#attributes'],
+ '#parents' => $element['#parents'],
+ '#id' => drupal_html_id('edit-' . implode('-', $parents_for_id)),
+ '#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL,
+ '#weight' => $weight,
+ );
}
}
return $element;
@@ -2911,25 +2917,30 @@ function form_process_checkboxes($element) {
if (!isset($element['#default_value']) || $element['#default_value'] == 0) {
$element['#default_value'] = array();
}
+ $weight = 0;
foreach ($element['#options'] as $key => $choice) {
- if (!isset($element[$key])) {
- // Integer 0 is not a valid #return_value, so use '0' instead.
- // @see form_type_checkbox_value().
- // @todo For Drupal 8, cast all integer keys to strings for consistency
- // with form_process_radios().
- if ($key === 0) {
- $key = '0';
- }
- $element[$key] = array(
- '#type' => 'checkbox',
- '#processed' => TRUE,
- '#title' => $choice,
- '#return_value' => $key,
- '#default_value' => isset($value[$key]) ? $key : NULL,
- '#attributes' => $element['#attributes'],
- '#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL,
- );
+ // Integer 0 is not a valid #return_value, so use '0' instead.
+ // @see form_type_checkbox_value().
+ // @todo For Drupal 8, cast all integer keys to strings for consistency
+ // with form_process_radios().
+ if ($key === 0) {
+ $key = '0';
}
+ // Maintain order of options as defined in #options, in case the element
+ // defines custom option sub-elements, but does not define all option
+ // sub-elements.
+ $weight += 0.001;
+
+ $element += array($key => array());
+ $element[$key] += array(
+ '#type' => 'checkbox',
+ '#title' => $choice,
+ '#return_value' => $key,
+ '#default_value' => isset($value[$key]) ? $key : NULL,
+ '#attributes' => $element['#attributes'],
+ '#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL,
+ '#weight' => $weight,
+ );
}
}
return $element;
diff --git a/modules/comment/comment.module b/modules/comment/comment.module
index 03c274c83..c0058f40f 100644
--- a/modules/comment/comment.module
+++ b/modules/comment/comment.module
@@ -1190,28 +1190,13 @@ function comment_form_node_form_alter(&$form, $form_state) {
COMMENT_NODE_HIDDEN => t('Hidden'),
),
COMMENT_NODE_OPEN => array(
- '#type' => 'radio',
- '#title' => t('Open'),
'#description' => t('Users with the "Post comments" permission can post comments.'),
- '#return_value' => COMMENT_NODE_OPEN,
- '#default_value' => $comment_settings,
- '#parents' => array('comment'),
),
COMMENT_NODE_CLOSED => array(
- '#type' => 'radio',
- '#title' => t('Closed'),
'#description' => t('Users cannot post comments, but existing comments will be displayed.'),
- '#return_value' => COMMENT_NODE_CLOSED,
- '#default_value' => $comment_settings,
- '#parents' => array('comment'),
),
COMMENT_NODE_HIDDEN => array(
- '#type' => 'radio',
- '#title' => t('Hidden'),
'#description' => t('Comments are hidden from view.'),
- '#return_value' => COMMENT_NODE_HIDDEN,
- '#default_value' => $comment_settings,
- '#parents' => array('comment'),
),
);
// If the node doesn't have any comments, the "hidden" option makes no
diff --git a/modules/simpletest/tests/form.test b/modules/simpletest/tests/form.test
index 1f76318f5..a0df09052 100644
--- a/modules/simpletest/tests/form.test
+++ b/modules/simpletest/tests/form.test
@@ -370,6 +370,66 @@ class FormsTestCase extends DrupalWebTestCase {
}
/**
+ * Tests building and processing of core form elements.
+ */
+class FormElementTestCase extends DrupalWebTestCase {
+ protected $profile = 'testing';
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'Element processing',
+ 'description' => 'Tests building and processing of core form elements.',
+ 'group' => 'Form API',
+ );
+ }
+
+ function setUp() {
+ parent::setUp(array('form_test'));
+ }
+
+ /**
+ * Tests expansion of #options for #type checkboxes and radios.
+ */
+ function testOptions() {
+ $this->drupalGet('form-test/checkboxes-radios');
+
+ // Verify that all options appear in their defined order.
+ foreach (array('checkbox', 'radio') as $type) {
+ $elements = $this->xpath('//input[@type=:type]', array(':type' => $type));
+ $expected_values = array('0', 'foo', '1', 'bar');
+ foreach ($elements as $element) {
+ $expected = array_shift($expected_values);
+ $this->assertIdentical((string) $element['value'], $expected);
+ }
+ }
+
+ // Enable customized option sub-elements.
+ $this->drupalGet('form-test/checkboxes-radios/customize');
+
+ // Verify that all options appear in their defined order, taking a custom
+ // #weight into account.
+ foreach (array('checkbox', 'radio') as $type) {
+ $elements = $this->xpath('//input[@type=:type]', array(':type' => $type));
+ $expected_values = array('0', 'foo', 'bar', '1');
+ foreach ($elements as $element) {
+ $expected = array_shift($expected_values);
+ $this->assertIdentical((string) $element['value'], $expected);
+ }
+ }
+ // Verify that custom #description properties are output.
+ foreach (array('checkboxes', 'radios') as $type) {
+ $elements = $this->xpath('//input[@name=:name]/following-sibling::div[@class=:class]', array(
+ ':name' => $type . '[foo]',
+ ':class' => 'description',
+ ));
+ $this->assertTrue(count($elements), t('Custom %type option description found.', array(
+ '%type' => $type,
+ )));
+ }
+ }
+}
+
+/**
* Test form alter hooks.
*/
class FormAlterTestCase extends DrupalWebTestCase {
diff --git a/modules/simpletest/tests/form_test.module b/modules/simpletest/tests/form_test.module
index 4d717c04b..abaae06c1 100644
--- a/modules/simpletest/tests/form_test.module
+++ b/modules/simpletest/tests/form_test.module
@@ -98,6 +98,12 @@ function form_test_menu() {
'page arguments' => array('form_test_select'),
'access callback' => TRUE,
);
+ $items['form-test/checkboxes-radios'] = array(
+ 'title' => t('Checkboxes, Radios'),
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('form_test_checkboxes_radios'),
+ 'access callback' => TRUE,
+ );
$items['form-test/disabled-elements'] = array(
'title' => t('Form test'),
@@ -187,6 +193,14 @@ function form_test_menu() {
}
/**
+ * Form submit handler to return form values as JSON.
+ */
+function _form_test_submit_values_json($form, &$form_state) {
+ drupal_json_output($form_state['values']);
+ drupal_exit();
+}
+
+/**
* Form builder for testing hook_form_alter() and hook_form_FORM_ID_alter().
*/
function form_test_alter_form($form, &$form_state) {
@@ -893,6 +907,63 @@ function form_test_select_submit($form, &$form_state) {
}
/**
+ * Form constructor to test expansion of #type checkboxes and radios.
+ */
+function form_test_checkboxes_radios($form, &$form_state, $customize = FALSE) {
+ $form['#submit'] = array('_form_test_submit_values_json');
+
+ // Expand #type checkboxes, setting custom element properties for some but not
+ // all options.
+ $form['checkboxes'] = array(
+ '#type' => 'checkboxes',
+ '#title' => 'Checkboxes',
+ '#options' => array(
+ 0 => 'Zero',
+ 'foo' => 'Foo',
+ 1 => 'One',
+ 'bar' => 'Bar',
+ ),
+ );
+ if ($customize) {
+ $form['checkboxes'] += array(
+ 'foo' => array(
+ '#description' => 'Enable to foo.',
+ ),
+ 1 => array(
+ '#weight' => 10,
+ ),
+ );
+ }
+
+ // Expand #type radios, setting custom element properties for some but not
+ // all options.
+ $form['radios'] = array(
+ '#type' => 'radios',
+ '#title' => 'Radios',
+ '#options' => array(
+ 0 => 'Zero',
+ 'foo' => 'Foo',
+ 1 => 'One',
+ 'bar' => 'Bar',
+ ),
+ );
+ if ($customize) {
+ $form['radios'] += array(
+ 'foo' => array(
+ '#description' => 'Enable to foo.',
+ ),
+ 1 => array(
+ '#weight' => 10,
+ ),
+ );
+ }
+
+ $form['submit'] = array('#type' => 'submit', '#value' => 'Submit');
+
+ return $form;
+}
+
+/**
* Build a form to test disabled elements.
*/
function _form_test_disabled_elements($form, &$form_state) {