Commit b91c1a9e authored by webchick's avatar webchick
Browse files

Issue #2120841 by tim.plunkett: Convert form_options_flatten() to a method on FormBuilder.

parent f17dcbf8
......@@ -735,34 +735,11 @@ function form_set_value($element, $value, &$form_state) {
*
* @return
* An array with all hierarchical elements flattened to a single array.
*/
function form_options_flatten($array) {
// Always reset static var when first entering the recursion.
drupal_static_reset('_form_options_flatten');
return _form_options_flatten($array);
}
/**
* Iterates over an array and returns a flat array with duplicate keys removed.
*
* This function also handles cases where objects are passed as array values.
* @deprecated as of Drupal 8.0. Use \Drupal::formBuilder()->flattenOptions()
*/
function _form_options_flatten($array) {
$return = &drupal_static(__FUNCTION__);
foreach ($array as $key => $value) {
if (is_object($value)) {
_form_options_flatten($value->option);
}
elseif (is_array($value)) {
_form_options_flatten($value);
}
else {
$return[$key] = 1;
}
}
return $return;
function form_options_flatten($array) {
return \Drupal::formBuilder()->flattenOptions($array);
}
/**
......
......@@ -124,6 +124,13 @@ class FormBuilder implements FormBuilderInterface {
*/
protected $validatedForms = array();
/**
* An array of options used for recursive flattening.
*
* @var array
*/
protected $flattenedOptions = array();
/**
* Constructs a new FormBuilder.
*
......@@ -1008,7 +1015,7 @@ protected function doValidateForm(&$elements, &$form_state, $form_id = NULL) {
if (isset($elements['#options']) && isset($elements['#value'])) {
if ($elements['#type'] == 'select') {
$options = form_options_flatten($elements['#options']);
$options = $this->flattenOptions($elements['#options']);
}
else {
$options = $elements['#options'];
......@@ -1651,6 +1658,37 @@ public function setValue($element, $value, &$form_state) {
NestedArray::setValue($form_state['values'], $element['#parents'], $value, TRUE);
}
/**
* {@inheritdoc}
*/
public function flattenOptions(array $array) {
$this->flattenedOptions = array();
$this->doFlattenOptions($array);
return $this->flattenedOptions;
}
/**
* Iterates over an array building a flat array with duplicate keys removed.
*
* This function also handles cases where objects are passed as array values.
*
* @param array $array
* The form options array to process.
*/
protected function doFlattenOptions(array $array) {
foreach ($array as $key => $value) {
if (is_object($value)) {
$this->doFlattenOptions($value->option);
}
elseif (is_array($value)) {
$this->doFlattenOptions($value);
}
else {
$this->flattenedOptions[$key] = 1;
}
}
}
/**
* Triggers kernel.response and sends a form response.
*
......
......@@ -756,6 +756,21 @@ public function doBuildForm($form_id, &$element, &$form_state);
*/
public function setValue($element, $value, &$form_state);
/**
* Allows PHP array processing of multiple select options with the same value.
*
* Used for form select elements which need to validate HTML option groups
* and multiple options which may return the same value. Associative PHP
* arrays cannot handle these structures, since they share a common key.
*
* @param array $array
* The form options array to process.
*
* @return array
* An array with all hierarchical elements flattened to a single array.
*/
public function flattenOptions(array $array);
/**
* Sets the request object to use.
*
......
......@@ -469,6 +469,20 @@ public function testSubmitForm() {
$errors = $this->formBuilder->getErrors();
$this->assertNull($errors);
$form_state = array();
$form_state['values']['test'] = $this->randomName();
$form_state['values']['options'] = array('foo');
$this->formBuilder->submitForm($form_arg, $form_state);
$errors = $this->formBuilder->getErrors();
$this->assertNull($errors);
$form_state = array();
$form_state['values']['test'] = $this->randomName();
$form_state['values']['options'] = array('foo', 'baz');
$this->formBuilder->submitForm($form_arg, $form_state);
$errors = $this->formBuilder->getErrors();
$this->assertNotEmpty($errors['options']);
$form_state = array();
$form_state['values']['test'] = $this->randomName();
$form_state['values']['options'] = $this->randomName();
......@@ -478,6 +492,43 @@ public function testSubmitForm() {
$this->assertNotEmpty($errors['options']);
}
/**
* Tests the flattenOptions() method.
*
* @dataProvider providerTestFlattenOptions
*/
public function testFlattenOptions($options) {
$expected_form = test_form_id();
$expected_form['select']['#required'] = TRUE;
$expected_form['select']['#options'] = $options;
$form_arg = $this->getMock('Drupal\Core\Form\FormInterface');
$form_arg->expects($this->any())
->method('buildForm')
->will($this->returnValue($expected_form));
$form_state = array();
$form_state['values']['select'] = 'foo';
$this->formBuilder->submitForm($form_arg, $form_state);
$errors = $this->formBuilder->getErrors();
$this->assertNull($errors);
}
/**
* Provides test data for the flattenOptions() method.
*
* @return array
*/
public function providerTestFlattenOptions() {
$object = new \stdClass();
$object->option = array('foo' => 'foo');
return array(
array(array('foo' => 'foo')),
array(array(array('foo' => 'foo'))),
array(array($object)),
);
}
/**
* Tests the getCache() method.
*/
......@@ -611,6 +662,11 @@ protected function getElementInfo($type) {
$types['value'] = array(
'#input' => TRUE,
);
$types['select'] = array(
'#input' => TRUE,
'#multiple' => FALSE,
'#empty_value' => '',
);
$types['radios'] = array(
'#input' => TRUE,
);
......@@ -707,6 +763,13 @@ function test_form_id() {
'#type' => 'textfield',
'#title' => 'Test',
);
$form['select'] = array(
'#type' => 'select',
'#options' => array(
'foo' => 'foo',
'bar' => 'bar',
),
);
$form['options'] = array(
'#type' => 'radios',
'#options' => array(
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment