diff --git a/core/includes/form.inc b/core/includes/form.inc index 260ffbe..210c7bf 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -12,7 +12,6 @@ use Drupal\Component\Utility\Xss; use Drupal\Core\Database\Database; use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Form\OptGroup; use Drupal\Core\Render\Element; use Drupal\Core\Template\Attribute; use Symfony\Component\HttpFoundation\RedirectResponse; @@ -119,34 +118,10 @@ function form_set_value($element, $value, FormStateInterface $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 - * The form options array to process. - * - * @return - * An array with all hierarchical elements flattened to a single array. - * - * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0. - * Use \Drupal\Core\Form\OptGroup::flattenOptions(). - */ -function form_options_flatten($array) { - return OptGroup::flattenOptions($array); -} - -/** * Prepares variables for select element templates. * * Default template: select.html.twig. * - * It is possible to group options together; to do this, change the format of - * $options to an associative array in which the keys are group labels, and the - * values are associative arrays in the normal $options format. - * * @param $variables * An associative array containing: * - element: An associative array containing the properties of the element. @@ -155,138 +130,43 @@ function form_options_flatten($array) { */ function template_preprocess_select(&$variables) { $element = $variables['element']; - Element::setAttributes($element, array('id', 'name', 'size')); - Element\RenderElement::setAttributes($element, array('form-select')); $variables['attributes'] = $element['#attributes']; - $variables['options'] = form_select_options($element); + $variables['options'] = drupal_render_children($element); } /** - * Converts an array of options into HTML, for use in select list form elements. - * - * This function calls itself recursively to obtain the values for each optgroup - * within the list of options and when the function encounters an object with - * an 'options' property inside $element['#options']. - * - * @param array $element - * An associative array containing the following key-value pairs: - * - #multiple: Optional Boolean indicating if the user may select more than - * one item. - * - #options: An associative array of options to render as HTML. Each array - * value can be a string, an array, or an object with an 'option' property: - * - A string or integer key whose value is a translated string is - * interpreted as a single HTML option element. Do not use placeholders - * that sanitize data: doing so will lead to double-escaping. Note that - * the key will be visible in the HTML and could be modified by malicious - * users, so don't put sensitive information in it. - * - A translated string key whose value is an array indicates a group of - * options. The translated string is used as the label attribute for the - * optgroup. Do not use placeholders to sanitize data: doing so will lead - * to double-escaping. The array should contain the options you wish to - * group and should follow the syntax of $element['#options']. - * - If the function encounters a string or integer key whose value is an - * object with an 'option' property, the key is ignored, the contents of - * the option property are interpreted as $element['#options'], and the - * resulting HTML is added to the output. - * - #value: Optional integer, string, or array representing which option(s) - * to pre-select when the list is first displayed. The integer or string - * must match the key of an option in the '#options' list. If '#multiple' is - * TRUE, this can be an array of integers or strings. - * @param array|null $choices - * (optional) Either an associative array of options in the same format as - * $element['#options'] above, or NULL. This parameter is only used internally - * and is not intended to be passed in to the initial function call. - * - * @return string - * An HTML string of options and optgroups for use in a select form element. + * Prepares variables for option group element templates. + * + * Default template: optgroup.html.twig. + * + * @param $variables + * An associative array containing: + * - element: An associative array containing the properties of the element. + * Properties used: #title, #value, #options, #multiple, #attributes. */ -function form_select_options($element, $choices = NULL) { - if (!isset($choices)) { - if (empty($element['#options'])) { - return ''; - } - $choices = $element['#options']; - } - // array_key_exists() accommodates the rare event where $element['#value'] is NULL. - // isset() fails in this situation. - $value_valid = isset($element['#value']) || array_key_exists('#value', $element); - $value_is_array = $value_valid && is_array($element['#value']); - // Check if the element is multiple select and no value has been selected. - $empty_value = (empty($element['#value']) && !empty($element['#multiple'])); - $options = ''; - foreach ($choices as $key => $choice) { - if (is_array($choice)) { - $options .= ''; - $options .= form_select_options($element, $choice); - $options .= ''; - } - elseif (is_object($choice) && isset($choice->option)) { - $options .= form_select_options($element, $choice->option); - } - else { - $key = (string) $key; - $empty_choice = $empty_value && $key == '_none'; - if ($value_valid && ((!$value_is_array && (string) $element['#value'] === $key || ($value_is_array && in_array($key, $element['#value']))) || $empty_choice)) { - $selected = ' selected="selected"'; - } - else { - $selected = ''; - } - $options .= ''; - } - } - return SafeMarkup::set($options); +function template_preprocess_optgroup(&$variables) { + $element = $variables['element']; + + $variables['attributes'] = $element['#attributes']; + $variables['options'] = drupal_render_children($element); } /** - * Returns the indexes of a select element's options matching a given key. - * - * This function is useful if you need to modify the options that are - * already in a form element; for example, to remove choices which are - * not valid because of additional filters imposed by another module. - * One example might be altering the choices in a taxonomy selector. - * To correctly handle the case of a multiple hierarchy taxonomy, - * #options arrays can now hold an array of objects, instead of a - * direct mapping of keys to labels, so that multiple choices in the - * selector can have the same key (and label). This makes it difficult - * to manipulate directly, which is why this helper function exists. - * - * This function does not support optgroups (when the elements of the - * #options array are themselves arrays), and will return FALSE if - * arrays are found. The caller must either flatten/restore or - * manually do their manipulations in this case, since returning the - * index is not sufficient, and supporting this would make the - * "helper" too complicated and cumbersome to be of any help. - * - * As usual with functions that can return array() or FALSE, do not - * forget to use === and !== if needed. - * - * @param $element - * The select element to search. - * @param $key - * The key to look for. + * Prepares variables for option element templates. * - * @return - * An array of indexes that match the given $key. Array will be - * empty if no elements were found. FALSE if optgroups were found. + * Default template: option.html.twig. + * + * @param $variables + * An associative array containing: + * - element: An associative array containing the properties of the element. + * Properties used: #title, #value, #attributes. */ -function form_get_options($element, $key) { - $keys = array(); - foreach ($element['#options'] as $index => $choice) { - if (is_array($choice)) { - return FALSE; - } - elseif (is_object($choice)) { - if (isset($choice->option[$key])) { - $keys[] = $index; - } - } - elseif ($index == $key) { - $keys[] = $index; - } - } - return $keys; +function template_preprocess_option(&$variables) { + $element = $variables['element']; + + $variables['attributes'] = $element['#attributes']; + $variables['label'] = $element['#title']; } /** diff --git a/core/includes/theme.inc b/core/includes/theme.inc index d7387a2..c6cd375 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -2355,6 +2355,14 @@ function drupal_common_theme() { 'render element' => 'element', 'template' => 'select', ), + 'option' => array( + 'render element' => 'element', + 'template' => 'option', + ), + 'optgroup' => array( + 'render element' => 'element', + 'template' => 'optgroup', + ), 'fieldset' => array( 'render element' => 'element', 'template' => 'fieldset', diff --git a/core/lib/Drupal/Core/Form/FormValidator.php b/core/lib/Drupal/Core/Form/FormValidator.php index ee2da65..51dd3fc 100644 --- a/core/lib/Drupal/Core/Form/FormValidator.php +++ b/core/lib/Drupal/Core/Form/FormValidator.php @@ -316,7 +316,7 @@ protected function performRequiredValidation(&$elements, FormStateInterface &$fo if (isset($elements['#options']) && isset($elements['#value'])) { if ($elements['#type'] == 'select') { - $options = OptGroup::flattenOptions($elements['#options']); + $options = Element\Select::getFlattenedOptions($elements); } else { $options = $elements['#options']; diff --git a/core/lib/Drupal/Core/Form/OptGroup.php b/core/lib/Drupal/Core/Form/OptGroup.php deleted file mode 100644 index 21e9855..0000000 --- a/core/lib/Drupal/Core/Form/OptGroup.php +++ /dev/null @@ -1,58 +0,0 @@ - $value) { - if (is_object($value) && isset($value->option)) { - static::doFlattenOptions($value->option, $options); - } - elseif (is_array($value)) { - static::doFlattenOptions($value, $options); - } - else { - $options[$key] = 1; - } - } - } - -} diff --git a/core/lib/Drupal/Core/Render/Element/OptGroup.php b/core/lib/Drupal/Core/Render/Element/OptGroup.php new file mode 100644 index 0000000..a2f7cab --- /dev/null +++ b/core/lib/Drupal/Core/Render/Element/OptGroup.php @@ -0,0 +1,153 @@ + array( + array($class, 'processOptGroup'), + array($class, 'processAjaxForm'), + ), + '#pre_render' => array( + array($class, 'preRenderOptGroup'), + ), + '#theme' => 'optgroup', + '#options' => array(), + ); + } + + /** + * Processes an option group form element. + * + * This expands the #options property of option groups into proper option + * elements. + * + * @param array $element + * The form element to process. Properties used: + * - #options: (optional) An array of options for this option group where + * the keys are the option values and the values are the respective + * labels. Instead of specifying the options in this way, respective + * option elements can be created as child elements of an option group + * element. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current state of the form. + * @param array $complete_form + * The complete form structure. + * + * @return array + * The processed element. + * + * @see _form_validate() + */ + public static function processOptGroup(&$element, FormStateInterface $form_state, &$complete_form) { + // @TODO This is ported from form_select_options(). But instead of + // checking #value, #default_value should be used here and below, right? + $value_valid = isset($element['#value']) || array_key_exists('#value', $element); + $value_is_array = $value_valid && is_array($element['#value']); + // Check if the element is multiple select and no value has been selected. + $empty_value = (empty($element['#value']) && !empty($element['#multiple'])); + + $weight = 0; + foreach ($element['#options'] as $original_key => $choice) { + $key = (string) $original_key; + + // 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; + + $empty_choice = $empty_value && $key == '_none'; + + $element += array($key => array()); + $element[$key] += array( + '#type' => 'option', + '#title' => $choice, + // The key is sanitized in Drupal\Core\Template\Attribute during output + // from the theme function. + '#return_value' => $key, + '#selected' => $value_valid && ((!$value_is_array && (string) $element['#value'] === $key || ($value_is_array && in_array($key, $element['#value']))) || $empty_choice), + '#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL, + '#weight' => $weight, + ); + + unset($element['#options'][$original_key]); + } + + return $element; + } + + /** + * Prepares an option group render element. + */ + public static function preRenderOptGroup($element) { + $element['#attributes']['label'] = $element['#title']; + return $element; + } + + /** + * Returns a list of options for an option group element. + * + * This function assumes that the passed element has been processed by + * OptGroup::processOptgroup() prior to calling this function. + */ + public static function getOptions($element) { + $options = []; + + foreach (Element::children($element, TRUE) as $child) { + if ($element[$child]['#type'] == 'option') { + $options[$child] = $element[$child]['#title']; + } + } + + return $options; + } + + /** + * Iterates over an array building a flat array with duplicate keys removed. + * + * 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 static function flattenOptions(array $array) { + $options = []; + foreach ($array as $key => $value) { + if (is_array($value)) { + $options += static::flattenOptions($value); + } + else { + $options[$key] = TRUE; + } + } + return $options; + } + +} diff --git a/core/lib/Drupal/Core/Render/Element/Option.php b/core/lib/Drupal/Core/Render/Element/Option.php new file mode 100644 index 0000000..0c6b6b6 --- /dev/null +++ b/core/lib/Drupal/Core/Render/Element/Option.php @@ -0,0 +1,51 @@ + array( + array($class, 'processAjaxForm'), + ), + '#pre_render' => array( + array($class, 'preRenderOption'), + ), + '#theme' => 'option', + '#selected' => FALSE, + '#return_value' => NULL, + ); + } + + /** + * Prepares an option render element. + */ + public static function preRenderOption($element) { + $element['#attributes']['value'] = $element['#return_value']; + if ($element['#selected']) { + $element['#attributes']['selected'] = 'selected'; + } + return $element; + } + +} diff --git a/core/lib/Drupal/Core/Render/Element/Select.php b/core/lib/Drupal/Core/Render/Element/Select.php index 70f14d6..91fd942 100644 --- a/core/lib/Drupal/Core/Render/Element/Select.php +++ b/core/lib/Drupal/Core/Render/Element/Select.php @@ -17,6 +17,9 @@ * a select element, including behavior if #required is TRUE or FALSE. * * @FormElement("select") + * + * @see \Drupal\Core\Render\Element\Option + * @see \Drupal\Core\Render\Element\Optgroup */ class Select extends FormElement { @@ -113,6 +116,50 @@ public static function processSelect(&$element, FormStateInterface $form_state, $element['#options'] = $empty_option + $element['#options']; } } + + // If there are option group elements, pass the '#value' and '#multiple' + // keys down so they can properly set the selected option. + // @see \Drupal\Core\Render\Element\OptGroup::processOptgroup() + foreach (Element::children($element) as $child) { + if ($element[$child]['#type'] == 'optgroup') { + $element[$child]['#value'] = $element['#value']; + $element[$child]['#multiple'] = $element['#multiple']; + } + } + + // Process options and option groups. + $weight = 0; + foreach ($element['#options'] as $original_key => $choice) { + $key = (string) $original_key; + + // Maintain order of options as defined in #options, in case both + // options and option groups are defined or the element defines custom + // option sub-elements, but does not define all option sub-elements. + $weight += 0.001; + $element[$key]['#weight'] = $weight; + + // Expand option groups into proper elements. + if (is_array($choice)) { + $element += array($key => array()); + $element[$key] += array( + '#type' => 'optgroup', + '#title' => $key, + // The key is sanitized in Drupal\Core\Template\Attribute during output + // from the theme function. + '#options' => $choice, + '#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL, + '#value' => $element['#value'], + ); + OptGroup::processOptGroup($element[$key], $form_state, $complete_form); + + unset($element['#options'][$original_key]); + } + } + + // Process the '#options' element in the same way that option groups do. + OptGroup::processOptGroup($element, $form_state, $complete_form); + // At this point '#options' should be an empty array. + return $element; } @@ -156,4 +203,25 @@ public static function preRenderSelect($element) { return $element; } + /** + * Returns a list of flattened options for a select element. + * + * This function assumes that the passed element has been processed by + * Select::processSelect() prior to calling this function. + */ + public static function getFlattenedOptions($element) { + $options = []; + + foreach (Element::children($element, TRUE) as $child) { + if ($element[$child]['#type'] == 'optgroup') { + $options += OptGroup::getOptions($element[$child]); + } + elseif ($element[$child]['#type'] == 'option') { + $options[$child] = $element[$child]['#title']; + } + } + + return $options; + } + } diff --git a/core/lib/Drupal/Core/Render/Element/Weight.php b/core/lib/Drupal/Core/Render/Element/Weight.php index ffcda6b..7b4d088 100644 --- a/core/lib/Drupal/Core/Render/Element/Weight.php +++ b/core/lib/Drupal/Core/Render/Element/Weight.php @@ -52,6 +52,7 @@ public static function processWeight(&$element, FormStateInterface $form_state, } $element['#options'] = $weights; $element += $element_info_manager->getInfo('select'); + Select::processSelect($element, $form_state, $complete_form); } // Otherwise, use a text field. else { diff --git a/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php b/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php index 98ddf9b..633b647 100644 --- a/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php +++ b/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php @@ -11,7 +11,7 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem; use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Form\OptGroup; +use Drupal\Core\Render\Element\OptGroup; use Drupal\Core\Session\AccountInterface; use Drupal\Core\TypedData\OptionsProviderInterface; use Drupal\Core\TypedData\DataDefinition; diff --git a/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php index 05ec40d..0f11fd6 100644 --- a/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php +++ b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php @@ -11,7 +11,7 @@ use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemBase; use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Form\OptGroup; +use Drupal\Core\Render\Element\OptGroup; use Drupal\Core\Session\AccountInterface; use Drupal\Core\TypedData\OptionsProviderInterface; diff --git a/core/modules/system/src/Tests/Render/Element/SelectTest.php b/core/modules/system/src/Tests/Render/Element/SelectTest.php new file mode 100644 index 0000000..d2e57a6 --- /dev/null +++ b/core/modules/system/src/Tests/Render/Element/SelectTest.php @@ -0,0 +1,377 @@ +formBuilder = $this->container->get('form_builder'); + + /** @var \Drupal\Core\Extension\ThemeHandler $theme_handler */ + $theme_handler = $this->container->get('theme_handler'); + $theme_handler->enable(['stark']); + $theme_handler->setDefault('stark'); + } + + /** + * Tests the rendering of a select element. + */ + public function testSelect() { + foreach ($this->providerTestSelect() as $test_case) { + $element = $test_case['element']; + // In order to avoid calling FormBuilderInterface::prepareForm() we have + // to supply some default values. + $element += [ + '#id' => 'edit-select', + '#parents' => [], + '#array_parents' => [], + '#tree' => FALSE, + // Avoid the form builder trying to handle the (non-existent) input. + '#input' => FALSE, + ]; + + $output = $test_case['output']; + // The wrapper element never changes, so avoid having to specify it every + // time. + $output = '
' . $output . '
'; + + $form_id = 'select'; + $form_state = new FormState(); + $this->formBuilder->processForm($form_id, $element, $form_state); + $this->assertMarkupEquals($output, drupal_render($element)); + } + } + + /** + * Provides test data for SelectTest::testSelect(). + * + * @return array + * An array of test cases where each test case is an array with the + * following keys: + * - element: The select element to be rendered as part of the test. The + * element may or may not contain additional option or option group + * sub-elements. + * - output: The markup that the rendering of the element is expected to + * yield. + */ + public function providerTestSelect() { + $test_case = []; + $test_cases = []; + + // Test an empty select element. + $test_case['element'] = [ + '#type' => 'select', + '#title' => 'Test select', + ]; + $test_case['output'] = <<Test select + +HTML; + $test_cases[] = $test_case; + + // Test a simple select element. + $test_case['element'] = [ + '#type' => 'select', + '#title' => 'Test select', + '#options' => [ + 'spring' => 'Spring', + 'summer' => 'Summer', + 'fall' => 'Fall', + 'winter' => 'Winter', + ], + '#value' => NULL, + ]; + $test_case['output'] = <<Test select + +HTML; + $test_cases[] = $test_case; + + // Test a select element with a default value. + // Re-use the information from the previous test case. + $test_case['element']['#value'] = 'summer'; + $test_case['output'] = str_replace( + ' diff --git a/core/modules/taxonomy/src/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php b/core/modules/taxonomy/src/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php index a2965c9..17f6900 100644 --- a/core/modules/taxonomy/src/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php +++ b/core/modules/taxonomy/src/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php @@ -10,7 +10,7 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem; use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Form\OptGroup; +use Drupal\Core\Render\Element\OptGroup; use Drupal\Core\Session\AccountInterface; use Drupal\Core\TypedData\OptionsProviderInterface; diff --git a/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php b/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php index 439c8e6..07591eb 100644 --- a/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php +++ b/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php @@ -137,9 +137,7 @@ protected function valueForm(&$form, FormStateInterface $form_state) { if ($tree) { foreach ($tree as $term) { - $choice = new \stdClass(); - $choice->option = array($term->id() => str_repeat('-', $term->depth) . String::checkPlain(\Drupal::entityManager()->getTranslationFromContext($term)->label())); - $options[] = $choice; + $options[$term->id()] = str_repeat('-', $term->depth) . String::checkPlain(\Drupal::entityManager()->getTranslationFromContext($term)->label()); } } } diff --git a/core/modules/views/src/Plugin/views/filter/InOperator.php b/core/modules/views/src/Plugin/views/filter/InOperator.php index 4d442b8..a6a3f4a 100644 --- a/core/modules/views/src/Plugin/views/filter/InOperator.php +++ b/core/modules/views/src/Plugin/views/filter/InOperator.php @@ -10,6 +10,7 @@ use Drupal\Component\Utility\String as UtilityString; use Drupal\Component\Utility\Unicode; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Render\Element\OptGroup; use Drupal\views\Plugin\views\display\DisplayPluginBase; use Drupal\views\ViewExecutable; @@ -428,7 +429,7 @@ public function validate() { } // Some filter_in_operator usage uses optgroups forms, so flatten it. - $flat_options = form_options_flatten($this->value_options, TRUE); + $flat_options = OptGroup::flattenOptions($this->value_options); // Remove every element which is not known. foreach ($this->value as $value) { diff --git a/core/tests/Drupal/Tests/Core/Form/OptGroupTest.php b/core/tests/Drupal/Tests/Core/Render/Element/OptGroupTest.php similarity index 48% rename from core/tests/Drupal/Tests/Core/Form/OptGroupTest.php rename to core/tests/Drupal/Tests/Core/Render/Element/OptGroupTest.php index 6f353b9..5553f29 100644 --- a/core/tests/Drupal/Tests/Core/Form/OptGroupTest.php +++ b/core/tests/Drupal/Tests/Core/Render/Element/OptGroupTest.php @@ -2,13 +2,13 @@ /** * @file - * Contains \Drupal\Tests\Core\Form\OptGroupTest. + * Contains \Drupal\Tests\Core\Render\Element\OptGroupTest. */ -namespace Drupal\Tests\Core\Form; +namespace Drupal\Tests\Core\Render\Element; +use Drupal\Core\Render\Element\OptGroup; use Drupal\Tests\UnitTestCase; -use Drupal\Core\Form\OptGroup; /** * @coversDefaultClass \Drupal\Core\Form\OptGroup @@ -22,7 +22,7 @@ class OptGroupTest extends UnitTestCase { * @dataProvider providerTestFlattenOptions */ public function testFlattenOptions($options) { - $this->assertSame(array('foo' => 1), OptGroup::flattenOptions($options)); + $this->assertSame(array('foo' => TRUE), OptGroup::flattenOptions($options)); } /** @@ -31,19 +31,12 @@ public function testFlattenOptions($options) { * @return array */ public function providerTestFlattenOptions() { - $object1 = new \stdClass(); - $object1->option = array('foo' => 'foo'); - $object2 = new \stdClass(); - $object2->option = array(array('foo' => 'foo'), array('foo' => 'foo')); - $object3 = new \stdClass(); + $object = new \stdClass(); return array( array(array('foo' => 'foo')), array(array(array('foo' => 'foo'))), - array(array($object1)), - array(array($object2)), - array(array($object1, $object2)), - array(array('foo' => $object3)), - array(array('foo' => $object3, $object1, array('foo' => 'foo'))), + array(array('foo' => $object)), + array(array('foo' => $object, array('foo' => 'foo'))), ); }