diff --git a/core/includes/common.inc b/core/includes/common.inc index ee399a4..f5d1ff9 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -3633,7 +3633,7 @@ function drupal_render_cache_get(array $elements) { * * @see drupal_render_cache_get() */ -function drupal_render_cache_set(&$markup, array $elements) { +function drupal_render_cache_set(&$markup, $elements) { // Create the cache ID for the element. if (!\Drupal::request()->isMethodSafe() || !$cid = drupal_render_cid_create($elements)) { return FALSE; @@ -3729,7 +3729,7 @@ function drupal_render_cache_generate_placeholder($callback, array &$context) { * @see drupal_render() * @see drupal_render_collect_post_render_cache */ -function _drupal_render_process_post_render_cache(array &$elements) { +function _drupal_render_process_post_render_cache(&$elements) { if (isset($elements['#post_render_cache'])) { /** @var \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver */ $controller_resolver = \Drupal::service('controller_resolver'); @@ -3787,7 +3787,7 @@ function _drupal_render_process_post_render_cache(array &$elements) { * @see drupal_render() * @see _drupal_render_process_post_render_cache() */ -function drupal_render_collect_post_render_cache(array &$elements, array $callbacks = array(), $is_root_element = TRUE) { +function drupal_render_collect_post_render_cache(&$elements, array $callbacks = array(), $is_root_element = TRUE) { // Try to fetch the prerendered element from cache, to determine // #post_render_cache callbacks for this element and all its children. If we // don't do this, then the #post_render_cache tokens will be re-generated, but diff --git a/core/lib/Drupal/Core/Render/Element.php b/core/lib/Drupal/Core/Render/Element.php index 501f2de..f4993c2 100644 --- a/core/lib/Drupal/Core/Render/Element.php +++ b/core/lib/Drupal/Core/Render/Element.php @@ -68,7 +68,7 @@ public static function child($key) { * @return array * The array keys of the element's children. */ - public static function children(array &$elements, $sort = FALSE) { + public static function children(&$elements, $sort = FALSE) { // Do not attempt to sort elements which have already been sorted. $sort = isset($elements['#sorted']) ? !$elements['#sorted'] : $sort; @@ -77,7 +77,7 @@ public static function children(array &$elements, $sort = FALSE) { $sortable = FALSE; foreach ($elements as $key => $value) { if ($key === '' || $key[0] !== '#') { - if (is_array($value)) { + if (is_array($value) || is_object($value)) { $children[$key] = $value; if (isset($value['#weight'])) { $sortable = TRUE; diff --git a/core/modules/system/src/Tests/Common/RenderTest.php b/core/modules/system/src/Tests/Common/RenderTest.php index 7587af6..bf43051 100644 --- a/core/modules/system/src/Tests/Common/RenderTest.php +++ b/core/modules/system/src/Tests/Common/RenderTest.php @@ -11,6 +11,7 @@ use Drupal\Component\Utility\Html; use Drupal\Core\Render\Element; use Drupal\simpletest\DrupalUnitTestBase; +use Drupal\common_test\RenderableArray; /** * Tests drupal_render(). @@ -282,6 +283,40 @@ function testDrupalRenderBasics() { } /** + * Tests the output drupal_render() using objects instead of arrays. + */ + function testDrupalRenderArrayObjects() { + // Simplest case, a single object. + $types[] = array( + 'name' => 'Simple renderable object', + 'value' => new RenderableArray(array('#markup' => 'Hello World')), + 'expected' => 'Hello World', + ); + // Two renderable objects + $types[] = array( + 'name' => 'Array with two renderable objects', + 'value' => array( + 'hello' => new RenderableArray(array('#markup' => 'Hello', '#suffix' => ' ')), + 'world' => new RenderableArray(array('#markup' => 'World')), + ), + 'expected' => 'Hello World', + ); + // More complex, mixed nested objects and arrays + $render = new RenderableArray(); + $render['hello'] = new RenderableArray(array('#markup' => 'Hello', '#suffix' => ' ')); + $render['world'] = array('#markup' => 'World'); + $types[] = array( + 'name' => 'Nested renderable objects', + 'value' => $render, + 'expected' => 'Hello World', + ); + foreach($types as $type) { + $this->assertIdentical(drupal_render($type['value']), $type['expected'], '"' . $type['name'] . '" input rendered correctly by drupal_render().'); + } + } + + + /** * Tests sorting by weight. */ function testDrupalRenderSorting() { diff --git a/core/modules/system/tests/modules/common_test/src/RenderableArray.php b/core/modules/system/tests/modules/common_test/src/RenderableArray.php new file mode 100644 index 0000000..e8d1d17 --- /dev/null +++ b/core/modules/system/tests/modules/common_test/src/RenderableArray.php @@ -0,0 +1,64 @@ +elements = $elements; + } + + /** + * Implements ArrayAccess::offsetExists(). + */ + public function offsetExists($offset) { + return isset($this->elements[$offset]); + } + + /** + * Implements ArrayAccess::offsetGet(). + */ + public function &offsetGet($offset) { + return $this->elements[$offset]; + } + + /** + * Implements ArrayAccess::offsetSet(). + */ + public function offsetSet($offset, $value) { + $this->elements[$offset] = $value; + } + + /** + * Implements ArrayAccess::offsetUnset(). + */ + public function offsetUnset($offset) { + unset($this->elements[$offset]); + } + + /** + * Implements IteratorAggregate::getIterator(); + */ + public function getIterator() { + return new \ArrayIterator($this->elements); + } + +}