core/lib/Drupal/Core/Ajax/AjaxResponse.php | 6 ++-- .../Drupal/Core/Render/BareHtmlPageRenderer.php | 4 +-- .../Core/Render/MainContent/HtmlRenderer.php | 10 +++---- core/lib/Drupal/Core/Render/Renderer.php | 21 ++++++++++---- .../block/src/Tests/BlockViewBuilderTest.php | 33 ++++++++++++++-------- .../src/Tests/BlockContentCacheTagsTest.php | 2 +- .../ckeditor/src/Plugin/Editor/CKEditor.php | 18 ++++++++++-- .../Tests/CommentDefaultFormatterCacheTagsTest.php | 16 +++++++++-- .../contextual/src/ContextualController.php | 2 +- core/modules/field/field.module | 2 +- .../EntityReferenceFormatterTest.php | 8 ++++-- .../simpletest/src/Form/SimpletestResultsForm.php | 10 +++---- .../simpletest/src/Form/SimpletestTestForm.php | 32 +++++++++++++++++++-- .../simpletest/src/Tests/KernelTestBaseTest.php | 5 ++-- .../src/Plugin/views/style/StylePluginBase.php | 2 +- .../src/Tests/Handler/FieldFieldAccessTestBase.php | 4 +-- core/modules/views/src/Tests/ViewElementTest.php | 10 ++++--- core/modules/views/src/Tests/ViewRenderTest.php | 2 +- .../Tests/Core/Render/RendererBubblingTest.php | 22 +++++++-------- .../Drupal/Tests/Core/Render/RendererTest.php | 22 +++++++-------- 20 files changed, 154 insertions(+), 77 deletions(-) diff --git a/core/lib/Drupal/Core/Ajax/AjaxResponse.php b/core/lib/Drupal/Core/Ajax/AjaxResponse.php index a83898d..7d67454 100644 --- a/core/lib/Drupal/Core/Ajax/AjaxResponse.php +++ b/core/lib/Drupal/Core/Ajax/AjaxResponse.php @@ -198,15 +198,15 @@ protected function ajaxRender(Request $request) { $renderer = $this->getRenderer(); if (!empty($css_assets)) { $css_render_array = \Drupal::service('asset.css.collection_renderer')->render($css_assets); - $resource_commands[] = new AddCssCommand($renderer->render($css_render_array)); + $resource_commands[] = new AddCssCommand($renderer->renderPlain($css_render_array)); } if (!empty($js_assets_header)) { $js_header_render_array = \Drupal::service('asset.js.collection_renderer')->render($js_assets_header); - $resource_commands[] = new PrependCommand('head', $renderer->render($js_header_render_array)); + $resource_commands[] = new PrependCommand('head', $renderer->renderPlain($js_header_render_array)); } if (!empty($js_assets_footer)) { $js_footer_render_array = \Drupal::service('asset.js.collection_renderer')->render($js_assets_footer); - $resource_commands[] = new AppendCommand('body', $renderer->render($js_footer_render_array)); + $resource_commands[] = new AppendCommand('body', $renderer->renderPlain($js_footer_render_array)); } foreach (array_reverse($resource_commands) as $resource_command) { $this->addCommand($resource_command, TRUE); diff --git a/core/lib/Drupal/Core/Render/BareHtmlPageRenderer.php b/core/lib/Drupal/Core/Render/BareHtmlPageRenderer.php index c8012c6..58c5507 100644 --- a/core/lib/Drupal/Core/Render/BareHtmlPageRenderer.php +++ b/core/lib/Drupal/Core/Render/BareHtmlPageRenderer.php @@ -59,12 +59,12 @@ public function renderBarePage(array $content, $title, $page_theme_property, arr // \Drupal\Core\Render\MainContent\HtmlRenderer::renderResponse() for more // information about this; the exact same pattern is used there and // explained in detail there. - $this->renderer->render($html['page'], TRUE); + $this->renderer->renderRoot($html['page']); // Add the bare minimum of attachments from the system module and the // current maintenance theme. system_page_attachments($html['page']); - return $this->renderer->render($html); + return $this->renderer->renderPlain($html); } } diff --git a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php index d61bb24..05e38ec 100644 --- a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php +++ b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php @@ -126,14 +126,14 @@ public function renderResponse(array $main_content, Request $request, RouteMatch // and hence may not replace any placeholders (because they might add yet // more assets to be attached), and therefore it must be rendered with // drupal_render(), not drupal_render_root(). - $this->renderer->render($html['page'], TRUE); + $this->renderer->renderRoot($html['page']); if (isset($html['page_top'])) { - $this->renderer->render($html['page_top'], TRUE); + $this->renderer->renderRoot($html['page_top']); } if (isset($html['page_bottom'])) { - $this->renderer->render($html['page_bottom'], TRUE); + $this->renderer->renderRoot($html['page_bottom']); } - $content = $this->renderer->render($html); + $content = $this->renderer->renderPlain($html, FALSE); $response = new CacheableResponse($content, 200,[ 'Content-Type' => 'text/html; charset=UTF-8', @@ -197,7 +197,7 @@ protected function prepare(array $main_content, Request $request, RouteMatchInte // ::renderResponse(). // @todo Remove this once https://www.drupal.org/node/2359901 lands. if (!empty($main_content)) { - $this->renderer->render($main_content, FALSE); + $this->renderer->renderPlain($main_content, FALSE); $main_content = $this->renderCache->getCacheableRenderArray($main_content) + [ '#title' => isset($main_content['#title']) ? $main_content['#title'] : NULL ]; diff --git a/core/lib/Drupal/Core/Render/Renderer.php b/core/lib/Drupal/Core/Render/Renderer.php index a91b14b..76153bd 100644 --- a/core/lib/Drupal/Core/Render/Renderer.php +++ b/core/lib/Drupal/Core/Render/Renderer.php @@ -89,16 +89,27 @@ public function __construct(ControllerResolverInterface $controller_resolver, Th * {@inheritdoc} */ public function renderRoot(&$elements) { - return $this->render($elements, TRUE); + if (isset(static::$stack)) { + throw new \LogicException('A stray renderRoot() invocation is causing bubbling of attached assets to break.'); + } + static::$stack = new \SplStack(); + $output = $this->render($elements, TRUE); + $this->resetStack(); + + return $output; } /** * {@inheritdoc} + * + * @todo Rename to ::renderInIsolation() */ - public function renderPlain(&$elements) { + public function renderPlain(&$elements, $is_root_call = TRUE) { $current_stack = static::$stack; - $this->resetStack(); - $output = $this->renderRoot($elements); + + static::$stack = new \SplStack(); + $output = $this->render($elements, $is_root_call); + static::$stack = $current_stack; return $output; } @@ -186,7 +197,7 @@ protected function doRender(&$elements, $is_root_call = FALSE) { } if (!isset(static::$stack)) { - static::$stack = new \SplStack(); + throw new \LogicException("Render Stack is empty, because render() was called outside of a renderRoot() or renderPlain() call. Use renderPlain() / renderRoot() or #pre_render pattern instead."); } static::$stack->push(new BubbleableMetadata()); diff --git a/core/modules/block/src/Tests/BlockViewBuilderTest.php b/core/modules/block/src/Tests/BlockViewBuilderTest.php index 7a7aa64..ccb53e4 100644 --- a/core/modules/block/src/Tests/BlockViewBuilderTest.php +++ b/core/modules/block/src/Tests/BlockViewBuilderTest.php @@ -44,6 +44,13 @@ class BlockViewBuilderTest extends KernelTestBase { protected $controller; /** + * The renderer. + * + * @var \Drupal\Core\Render\RendererInterface + */ + protected $renderer; + + /** * {@inheritdoc} */ protected function setUp() { @@ -64,6 +71,8 @@ protected function setUp() { $this->block->save(); $this->container->get('cache.render')->deleteAll(); + + $this->renderer = $this->container->get('renderer'); } /** @@ -90,7 +99,7 @@ public function testBasicRendering() { $expected[] = ' '; $expected[] = ''; $expected_output = implode("\n", $expected); - $this->assertEqual(drupal_render($output), $expected_output); + $this->assertEqual($this->renderer->renderRoot($output), $expected_output); // Reset the HTML IDs so that the next render is not affected. Html::resetSeenIds(); @@ -115,7 +124,7 @@ public function testBasicRendering() { $expected[] = ' '; $expected[] = ''; $expected_output = implode("\n", $expected); - $this->assertEqual(drupal_render($output), $expected_output); + $this->assertEqual($this->renderer->renderRoot($output), $expected_output); } /** @@ -144,7 +153,7 @@ public function testBlockViewBuilderCache() { * @see ::testBlockViewBuilderCache() */ protected function verifyRenderCacheHandling() { - // Force a request via GET so we can get drupal_render() cache working. + // Force a request via GET so we can test the render cache. $request = \Drupal::request(); $request_method = $request->server->get('REQUEST_METHOD'); $request->setMethod('GET'); @@ -152,7 +161,7 @@ protected function verifyRenderCacheHandling() { // Test that a cache entry is created. $build = $this->getBlockRenderArray(); $cid = 'entity_view:block:test_block:en:core'; - drupal_render($build); + $this->renderer->renderRoot($build); $this->assertTrue($this->container->get('cache.render')->get($cid), 'The block render element has been cached.'); // Re-save the block and check that the cache entry has been deleted. @@ -166,7 +175,7 @@ protected function verifyRenderCacheHandling() { // removes it. $build['#block'] = $this->block; - drupal_render($build); + $this->renderer->renderRoot($build); $this->assertTrue($this->container->get('cache.render')->get($cid), 'The block render element has been cached.'); $this->block->delete(); $this->assertFalse($this->container->get('cache.render')->get($cid), 'The block render cache entry has been cleared when the block was deleted.'); @@ -181,17 +190,17 @@ protected function verifyRenderCacheHandling() { public function testBlockViewBuilderAlter() { // Establish baseline. $build = $this->getBlockRenderArray(); - $this->assertIdentical(drupal_render($build), 'Llamas > unicorns!'); + $this->assertIdentical($this->renderer->renderRoot($build), 'Llamas > unicorns!'); // Enable the block view alter hook that adds a suffix, for basic testing. \Drupal::state()->set('block_test_view_alter_suffix', TRUE); Cache::invalidateTags($this->block->getCacheTags()); $build = $this->getBlockRenderArray(); $this->assertTrue(isset($build['#suffix']) && $build['#suffix'] === '
Goodbye!', 'A block with content is altered.'); - $this->assertIdentical(drupal_render($build), 'Llamas > unicorns!
Goodbye!'); + $this->assertIdentical($this->renderer->renderRoot($build), 'Llamas > unicorns!
Goodbye!'); \Drupal::state()->set('block_test_view_alter_suffix', FALSE); - // Force a request via GET so we can get drupal_render() cache working. + // Force a request via GET so we can test the render cache. $request = \Drupal::request(); $request_method = $request->server->get('REQUEST_METHOD'); $request->setMethod('GET'); @@ -209,7 +218,7 @@ public function testBlockViewBuilderAlter() { $expected_keys = array_merge($default_keys, array($alter_add_key)); $build = $this->getBlockRenderArray(); $this->assertIdentical($expected_keys, $build['#cache']['keys'], 'An altered cacheable block has the expected cache keys.'); - $this->assertIdentical(drupal_render($build), ''); + $this->assertIdentical($this->renderer->renderRoot($build), ''); $cache_entry = $this->container->get('cache.render')->get($cid); $this->assertTrue($cache_entry, 'The block render element has been cached with the expected cache ID.'); $expected_tags = array_merge($default_tags, ['rendered']); @@ -224,7 +233,7 @@ public function testBlockViewBuilderAlter() { $build = $this->getBlockRenderArray(); sort($build['#cache']['tags']); $this->assertIdentical($expected_tags, $build['#cache']['tags'], 'An altered cacheable block has the expected cache tags.'); - $this->assertIdentical(drupal_render($build), ''); + $this->assertIdentical($this->renderer->renderRoot($build), ''); $cache_entry = $this->container->get('cache.render')->get($cid); $this->assertTrue($cache_entry, 'The block render element has been cached with the expected cache ID.'); $expected_tags = array_merge($default_tags, [$alter_add_tag, 'rendered']); @@ -236,8 +245,8 @@ public function testBlockViewBuilderAlter() { // alter the eventual content. \Drupal::state()->set('block_test_view_alter_append_pre_render_prefix', TRUE); $build = $this->getBlockRenderArray(); - $this->assertFalse(isset($build['#prefix']), 'The appended #pre_render callback has not yet run before calling drupal_render().'); - $this->assertIdentical(drupal_render($build), 'Hiya!
'); + $this->assertFalse(isset($build['#prefix']), 'The appended #pre_render callback has not yet run before rendering.'); + $this->assertIdentical($this->renderer->renderRoot($build), 'Hiya!
'); $this->assertTrue(isset($build['#prefix']) && $build['#prefix'] === 'Hiya!
', 'A cached block without content is altered.'); // Restore the previous request method. diff --git a/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php b/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php index 582d832..fe2c789 100644 --- a/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php +++ b/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php @@ -84,7 +84,7 @@ public function testBlock() { // Drupal\Core\Render\Renderer. $request_stack = $this->container->get('request_stack'); $request_stack->push(new Request()); - $this->container->get('renderer')->render($build); + $this->container->get('renderer')->renderRoot($build); $request_stack->pop(); // Expected keys, contexts, and tags for the block. diff --git a/core/modules/ckeditor/src/Plugin/Editor/CKEditor.php b/core/modules/ckeditor/src/Plugin/Editor/CKEditor.php index 949c8e5..0e237b1 100644 --- a/core/modules/ckeditor/src/Plugin/Editor/CKEditor.php +++ b/core/modules/ckeditor/src/Plugin/Editor/CKEditor.php @@ -13,6 +13,7 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Language\LanguageManagerInterface; use Drupal\Core\Render\Element; +use Drupal\Core\Render\RendererInterface; use Drupal\editor\Plugin\EditorBase; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\editor\Entity\Editor as EditorEntity; @@ -56,6 +57,13 @@ class CKEditor extends EditorBase implements ContainerFactoryPluginInterface { protected $ckeditorPluginManager; /** + * The renderer. + * + * @var \Drupal\Core\Render\RendererInterface + */ + protected $renderer; + + /** * Constructs a Drupal\Component\Plugin\PluginBase object. * * @param array $configuration @@ -70,12 +78,15 @@ class CKEditor extends EditorBase implements ContainerFactoryPluginInterface { * The module handler to invoke hooks on. * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager * The language manager. + * @param \Drupal\Core\Render\RendererInterface $renderer + * The renderer. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, CKEditorPluginManager $ckeditor_plugin_manager, ModuleHandlerInterface $module_handler, LanguageManagerInterface $language_manager) { + public function __construct(array $configuration, $plugin_id, $plugin_definition, CKEditorPluginManager $ckeditor_plugin_manager, ModuleHandlerInterface $module_handler, LanguageManagerInterface $language_manager, RendererInterface $renderer) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->ckeditorPluginManager = $ckeditor_plugin_manager; $this->moduleHandler = $module_handler; $this->languageManager = $language_manager; + $this->renderer = $renderer; } /** @@ -88,7 +99,8 @@ public static function create(ContainerInterface $container, array $configuratio $plugin_definition, $container->get('plugin.manager.ckeditor.plugin'), $container->get('module_handler'), - $container->get('language_manager') + $container->get('language_manager'), + $container->get('renderer') ); } @@ -145,7 +157,7 @@ public function settingsForm(array $form, FormStateInterface $form_state, Editor 'library' => array('ckeditor/drupal.ckeditor.admin'), 'drupalSettings' => [ 'ckeditor' => [ - 'toolbarAdmin' => drupal_render($ckeditor_settings_toolbar), + 'toolbarAdmin' => $this->renderer->renderPlain($ckeditor_settings_toolbar), ], ], ), diff --git a/core/modules/comment/src/Tests/CommentDefaultFormatterCacheTagsTest.php b/core/modules/comment/src/Tests/CommentDefaultFormatterCacheTagsTest.php index 342765f..884bc03 100644 --- a/core/modules/comment/src/Tests/CommentDefaultFormatterCacheTagsTest.php +++ b/core/modules/comment/src/Tests/CommentDefaultFormatterCacheTagsTest.php @@ -57,6 +57,8 @@ protected function setUp() { * Tests the bubbling of cache tags. */ public function testCacheTags() { + $renderer = $this->container->get('renderer'); + // Create the entity that will be commented upon. $commented_entity = entity_create('entity_test', array('name' => $this->randomMachineName())); $commented_entity->save(); @@ -65,11 +67,16 @@ public function testCacheTags() { $build = \Drupal::entityManager() ->getViewBuilder('entity_test') ->view($commented_entity); - drupal_render($build); + $renderer->renderRoot($build); $expected_cache_tags = array( 'entity_test_view', 'entity_test:' . $commented_entity->id(), 'comment_list', + 'config:core.entity_form_display.comment.comment.default', + 'config:field.field.comment.comment.comment_body', + 'config:field.field.entity_test.entity_test.comment', + 'config:field.storage.comment.comment_body', + 'config:user.settings', ); sort($expected_cache_tags); $this->assertEqual($build['#cache']['tags'], $expected_cache_tags, 'The test entity has the expected cache tags before it has comments.'); @@ -102,7 +109,7 @@ public function testCacheTags() { $build = \Drupal::entityManager() ->getViewBuilder('entity_test') ->view($commented_entity); - drupal_render($build); + $renderer->renderRoot($build); $expected_cache_tags = array( 'entity_test_view', 'entity_test:' . $commented_entity->id(), @@ -112,6 +119,11 @@ public function testCacheTags() { 'config:filter.format.plain_text', 'user_view', 'user:2', + 'config:core.entity_form_display.comment.comment.default', + 'config:field.field.comment.comment.comment_body', + 'config:field.field.entity_test.entity_test.comment', + 'config:field.storage.comment.comment_body', + 'config:user.settings', ); sort($expected_cache_tags); $this->assertEqual($build['#cache']['tags'], $expected_cache_tags, 'The test entity has the expected cache tags when it has comments.'); diff --git a/core/modules/contextual/src/ContextualController.php b/core/modules/contextual/src/ContextualController.php index aeee4a6..975113d 100644 --- a/core/modules/contextual/src/ContextualController.php +++ b/core/modules/contextual/src/ContextualController.php @@ -44,7 +44,7 @@ public function render(Request $request) { '#type' => 'contextual_links', '#contextual_links' => _contextual_id_to_links($id), ); - $rendered[$id] = drupal_render($element); + $rendered[$id] = $this->container->get('renderer')->renderRoot($element); } return new JsonResponse($rendered); diff --git a/core/modules/field/field.module b/core/modules/field/field.module index 88ccff9..7e52327 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -121,7 +121,7 @@ function field_help($route_name, RouteMatchInterface $route_match) { '#theme' => 'item_list', '#items' => $items, ); - $output .= drupal_render($item_list); + $output .= \Drupal::service('renderer')->render($item_list); $output .= ''; } diff --git a/core/modules/field/src/Tests/EntityReference/EntityReferenceFormatterTest.php b/core/modules/field/src/Tests/EntityReference/EntityReferenceFormatterTest.php index 52fdc08..022ec5c 100644 --- a/core/modules/field/src/Tests/EntityReference/EntityReferenceFormatterTest.php +++ b/core/modules/field/src/Tests/EntityReference/EntityReferenceFormatterTest.php @@ -179,6 +179,7 @@ public function testIdFormatter() { * Tests the entity formatter. */ public function testEntityFormatter() { + $renderer = $this->container->get('renderer'); $formatter = 'entity_reference_entity_view'; $build = $this->buildRenderArray([$this->referencedEntity, $this->unsavedReferencedEntity], $formatter); @@ -196,7 +197,7 @@ public function testEntityFormatter() { '; - drupal_render($build[0]); + $renderer->renderRoot($build[0]); $this->assertEqual($build[0]['#markup'], 'default | ' . $this->referencedEntity->label() . $expected_rendered_name_field_1 . $expected_rendered_body_field_1, sprintf('The markup returned by the %s formatter is correct for an item with a saved entity.', $formatter)); $expected_cache_tags = Cache::mergeTags( \Drupal::entityManager()->getViewBuilder($this->entityType)->getCacheTags(), @@ -206,7 +207,7 @@ public function testEntityFormatter() { $this->assertEqual($build[0]['#cache']['tags'], $expected_cache_tags, format_string('The @formatter formatter has the expected cache tags.', array('@formatter' => $formatter))); // Test the second field item. - drupal_render($build[1]); + $renderer->renderRoot($build[1]); $this->assertEqual($build[1]['#markup'], $this->unsavedReferencedEntity->label(), sprintf('The markup returned by the %s formatter is correct for an item with a unsaved entity.', $formatter)); } @@ -214,6 +215,7 @@ public function testEntityFormatter() { * Tests the label formatter. */ public function testLabelFormatter() { + $renderer = $this->container->get('renderer'); $formatter = 'entity_reference_label'; // The 'link' settings is TRUE by default. @@ -237,7 +239,7 @@ public function testLabelFormatter() { 'tags' => $this->referencedEntity->getCacheTags(), ), ); - $this->assertEqual(drupal_render($build[0]), drupal_render($expected_item_1), sprintf('The markup returned by the %s formatter is correct for an item with a saved entity.', $formatter)); + $this->assertEqual($renderer->renderRoot($build[0]), $renderer->renderRoot($expected_item_1), sprintf('The markup returned by the %s formatter is correct for an item with a saved entity.', $formatter)); $this->assertEqual(CacheableMetadata::createFromRenderArray($build[0]), CacheableMetadata::createFromRenderArray($expected_item_1)); // The second referenced entity is "autocreated", therefore not saved and diff --git a/core/modules/simpletest/src/Form/SimpletestResultsForm.php b/core/modules/simpletest/src/Form/SimpletestResultsForm.php index d41654f..a1b97ba 100644 --- a/core/modules/simpletest/src/Form/SimpletestResultsForm.php +++ b/core/modules/simpletest/src/Form/SimpletestResultsForm.php @@ -94,10 +94,10 @@ protected static function buildStatusImageMap() { '#alt' => 'Debug', ); return array( - 'pass' => drupal_render($image_pass), - 'fail' => drupal_render($image_fail), - 'exception' => drupal_render($image_exception), - 'debug' => drupal_render($image_debug), + 'pass' => $image_pass, + 'fail' => $image_fail, + 'exception' => $image_exception, + 'debug' => $image_debug, ); } @@ -205,7 +205,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { // Under normal circumstances, a form object's submitForm() should never be // called directly, FormBuilder::submitForm() should be called instead. // However, it calls $form_state->setProgrammed(), which disables the Batch API. - $simpletest_test_form = new SimpletestTestForm(); + $simpletest_test_form = SimpletestTestForm::create(\Drupal::getContainer()); $simpletest_test_form->buildForm($form_execute, $form_state_execute); $simpletest_test_form->submitForm($form_execute, $form_state_execute); if ($redirect = $form_state_execute->getRedirect()) { diff --git a/core/modules/simpletest/src/Form/SimpletestTestForm.php b/core/modules/simpletest/src/Form/SimpletestTestForm.php index 92c8a54..f6d0367 100644 --- a/core/modules/simpletest/src/Form/SimpletestTestForm.php +++ b/core/modules/simpletest/src/Form/SimpletestTestForm.php @@ -11,6 +11,8 @@ use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Render\RendererInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * List tests arranged in groups that can be selected and run. @@ -18,6 +20,32 @@ class SimpletestTestForm extends FormBase { /** + * The renderer. + * + * @var \Drupal\Core\Render\RendererInterface + */ + protected $renderer; + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('renderer') + ); + } + + /** + * Constructs a new SimpletestTestForm. + * + * @param \Drupal\Core\Render\RendererInterface $renderer + * The renderer. + */ + public function __construct(RendererInterface $renderer) { + $this->renderer = $renderer; + } + + /** * {@inheritdoc} */ public function getFormId() { @@ -99,8 +127,8 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#suffix' => '(' . $this->t('Collapse') . ')', ); $form['tests']['#attached']['drupalSettings']['simpleTest']['images'] = [ - drupal_render($image_collapsed), - drupal_render($image_extended), + $this->renderer->renderPlain($image_collapsed), + $this->renderer->renderPlain($image_extended), ]; // Generate the list of tests arranged by group. diff --git a/core/modules/simpletest/src/Tests/KernelTestBaseTest.php b/core/modules/simpletest/src/Tests/KernelTestBaseTest.php index 2e8a8c2..4ae7ef0 100644 --- a/core/modules/simpletest/src/Tests/KernelTestBaseTest.php +++ b/core/modules/simpletest/src/Tests/KernelTestBaseTest.php @@ -284,6 +284,7 @@ function testEnableModulesFixedList() { * Tests that _theme() works right after loading a module. */ function testEnableModulesTheme() { + $renderer = $this->container->get('renderer'); $original_element = $element = array( '#type' => 'container', '#markup' => 'Foo', @@ -291,11 +292,11 @@ function testEnableModulesTheme() { ); $this->enableModules(array('system')); // _theme() throws an exception if modules are not loaded yet. - $this->assertTrue(drupal_render($element)); + $this->assertTrue($renderer->renderRoot($element)); $element = $original_element; $this->disableModules(array('entity_test')); - $this->assertTrue(drupal_render($element)); + $this->assertTrue($renderer->renderRoot($element)); } /** diff --git a/core/modules/views/src/Plugin/views/style/StylePluginBase.php b/core/modules/views/src/Plugin/views/style/StylePluginBase.php index 8fa4617..af10867 100644 --- a/core/modules/views/src/Plugin/views/style/StylePluginBase.php +++ b/core/modules/views/src/Plugin/views/style/StylePluginBase.php @@ -678,7 +678,7 @@ protected function renderFields(array $result) { '#cache_properties' => $field_ids, ]; $renderer->addCacheableDependency($data, $this->view->storage); - $renderer->render($data); + $renderer->renderPlain($data); // Extract field output from the render array and post process it. $fields = $this->view->field; diff --git a/core/modules/views/src/Tests/Handler/FieldFieldAccessTestBase.php b/core/modules/views/src/Tests/Handler/FieldFieldAccessTestBase.php index 5554a8a..09b397d 100644 --- a/core/modules/views/src/Tests/Handler/FieldFieldAccessTestBase.php +++ b/core/modules/views/src/Tests/Handler/FieldFieldAccessTestBase.php @@ -125,7 +125,7 @@ protected function assertFieldAccess($entity_type_id, $field_name, $field_conten $account_switcher->switchTo($this->userWithAccess); $executable = Views::getView($view_id); $build = $executable->preview(); - $this->setRawContent($renderer->render($build)); + $this->setRawContent($renderer->renderRoot($build)); $this->assertText($field_content); $this->assertTrue(isset($executable->field[$field_name])); @@ -133,7 +133,7 @@ protected function assertFieldAccess($entity_type_id, $field_name, $field_conten $account_switcher->switchTo($this->userWithoutAccess); $executable = Views::getView($view_id); $build = $executable->preview(); - $this->setRawContent($renderer->render($build)); + $this->setRawContent($renderer->renderRoot($build)); $this->assertNoText($field_content); $this->assertFalse(isset($executable->field[$field_name])); diff --git a/core/modules/views/src/Tests/ViewElementTest.php b/core/modules/views/src/Tests/ViewElementTest.php index bd17747..5b53c57 100644 --- a/core/modules/views/src/Tests/ViewElementTest.php +++ b/core/modules/views/src/Tests/ViewElementTest.php @@ -52,12 +52,13 @@ protected function setUp() { * Tests the rendered output and form output of a view element. */ public function testViewElement() { + $renderer = $this->container->get('renderer'); $view = Views::getView('test_view_embed'); $view->setDisplay(); // Set the content as our rendered array. $render = $this->render; - $this->setRawContent(drupal_render($render)); + $this->setRawContent($renderer->renderRoot($render)); $xpath = $this->xpath('//div[@class="views-element-container"]'); $this->assertTrue($xpath, 'The view container has been found in the rendered output.'); @@ -102,7 +103,7 @@ public function testViewElement() { // Test the render array again. $render = $this->render; - $this->setRawContent(drupal_render($render)); + $this->setRawContent($renderer->renderRoot($render)); // There should be 1 row in the results, 'John' arg 25. $xpath = $this->xpath('//div[@class="view-content"]/div'); $this->assertEqual(count($xpath), 1); @@ -118,13 +119,14 @@ public function testViewElement() { * embed display plugin. */ public function testViewElementEmbed() { + $renderer = $this->container->get('renderer'); $view = Views::getView('test_view_embed'); $view->setDisplay('embed_1'); // Set the content as our rendered array. $render = $this->render; $render['#embed'] = TRUE; - $this->setRawContent(drupal_render($render)); + $this->setRawContent($renderer->renderRoot($render)); $xpath = $this->xpath('//div[@class="views-element-container"]'); $this->assertTrue($xpath, 'The view container has been found in the rendered output.'); @@ -170,7 +172,7 @@ public function testViewElementEmbed() { // Test the render array again. $render = $this->render; $render['#embed'] = TRUE; - $this->setRawContent(drupal_render($render)); + $this->setRawContent($renderer->renderRoot($render)); // There should be 1 row in the results, 'John' arg 25. $xpath = $this->xpath('//div[@class="view-content"]/div'); $this->assertEqual(count($xpath), 1); diff --git a/core/modules/views/src/Tests/ViewRenderTest.php b/core/modules/views/src/Tests/ViewRenderTest.php index ac60e6a..bbf3fe1 100644 --- a/core/modules/views/src/Tests/ViewRenderTest.php +++ b/core/modules/views/src/Tests/ViewRenderTest.php @@ -40,7 +40,7 @@ public function testRender() { // Make sure that the rendering just calls the preprocess function once. $view = Views::getView('test_view_render'); $output = $view->preview(); - drupal_render($output); + $this->container->get('renderer')->renderRoot($output); $this->assertEqual(\Drupal::state()->get('views_render.test'), 1); } diff --git a/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php b/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php index e0c7ff4..2037588 100644 --- a/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php +++ b/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php @@ -66,14 +66,14 @@ public function testBubblingWithoutPreRender() { ]; // Render the element and verify the presence of #attached JavaScript. - $this->renderer->render($element); + $this->renderer->renderRoot($element); $expected_libraries = ['test/parent', 'test/child', 'test/subchild']; $this->assertEquals($element['#attached']['library'], $expected_libraries, 'The element, child and subchild #attached libraries are included.'); // Load the element from cache and verify the presence of the #attached // JavaScript. $element = ['#cache' => ['keys' => ['simpletest', 'drupal_render', 'children_attached']]]; - $this->assertTrue(strlen($this->renderer->render($element)) > 0, 'The element was retrieved from cache.'); + $this->assertTrue(strlen($this->renderer->renderRoot($element)) > 0, 'The element was retrieved from cache.'); $this->assertEquals($element['#attached']['library'], $expected_libraries, 'The element, child and subchild #attached libraries are included.'); } @@ -116,7 +116,7 @@ public function testContextBubblingCustomCacheBin() { ], ], ]; - $this->renderer->render($build); + $this->renderer->renderRoot($build); $this->assertRenderCacheItem('parent:foo', [ '#cache_redirect' => TRUE, @@ -143,7 +143,7 @@ public function testContextBubblingEdgeCases(array $element, array $expected_top ->method('convertTokensToKeys') ->willReturnArgument(0); - $this->renderer->render($element); + $this->renderer->renderRoot($element); $this->assertEquals($expected_top_level_contexts, $element['#cache']['contexts'], 'Expected cache contexts found.'); foreach ($expected_cache_items as $cid => $expected_cache_item) { @@ -345,7 +345,7 @@ public function testConditionalCacheContextBubblingSelfHealing() { // contexts: user.roles. $element = $test_element; $current_user_role = 'A'; - $this->renderer->render($element); + $this->renderer->renderRoot($element); $this->assertRenderCacheItem('parent', [ '#cache_redirect' => TRUE, '#cache' => [ @@ -369,7 +369,7 @@ public function testConditionalCacheContextBubblingSelfHealing() { // contexts: foo, user.roles. $element = $test_element; $current_user_role = 'B'; - $this->renderer->render($element); + $this->renderer->renderRoot($element); $this->assertRenderCacheItem('parent', [ '#cache_redirect' => TRUE, '#cache' => [ @@ -401,7 +401,7 @@ public function testConditionalCacheContextBubblingSelfHealing() { // and 'user.roles' cache contexts, resulting in a cache miss every time.) $element = $test_element; $current_user_role = 'A'; - $this->renderer->render($element); + $this->renderer->renderRoot($element); $this->assertRenderCacheItem('parent', [ '#cache_redirect' => TRUE, '#cache' => [ @@ -425,7 +425,7 @@ public function testConditionalCacheContextBubblingSelfHealing() { // accessible => bubbled cache contexts: foo, bar, user.roles. $element = $test_element; $current_user_role = 'C'; - $this->renderer->render($element); + $this->renderer->renderRoot($element); $final_parent_cache_item = [ '#cache_redirect' => TRUE, '#cache' => [ @@ -449,7 +449,7 @@ public function testConditionalCacheContextBubblingSelfHealing() { // Request 5: role A again, verifying the merging like we did for request 3. $element = $test_element; $current_user_role = 'A'; - $this->renderer->render($element); + $this->renderer->renderRoot($element); $this->assertRenderCacheItem('parent', $final_parent_cache_item); $this->assertRenderCacheItem('parent:bar:foo:r.A', [ '#attached' => [], @@ -464,7 +464,7 @@ public function testConditionalCacheContextBubblingSelfHealing() { // Request 6: role B again, verifying the merging like we did for request 3. $element = $test_element; $current_user_role = 'B'; - $this->renderer->render($element); + $this->renderer->renderRoot($element); $this->assertRenderCacheItem('parent', $final_parent_cache_item); $this->assertRenderCacheItem('parent:bar:foo:r.B', [ '#attached' => [], @@ -570,7 +570,7 @@ public function testOverWriteCacheKeys() { ], '#pre_render' => [__NAMESPACE__ . '\\BubblingTest::bubblingCacheOverwritePrerender'], ]; - $this->renderer->render($data); + $this->renderer->renderRoot($data); } } diff --git a/core/tests/Drupal/Tests/Core/Render/RendererTest.php b/core/tests/Drupal/Tests/Core/Render/RendererTest.php index a2f91ea..3e3e3bd 100644 --- a/core/tests/Drupal/Tests/Core/Render/RendererTest.php +++ b/core/tests/Drupal/Tests/Core/Render/RendererTest.php @@ -43,7 +43,7 @@ public function testRenderBasic($build, $expected, callable $setup_code = NULL) $setup_code(); } - $this->assertSame($expected, $this->renderer->render($build)); + $this->assertSame($expected, $this->renderer->renderRoot($build)); } /** @@ -322,7 +322,7 @@ public function testRenderSorting() { '#markup' => $first, ], ]; - $output = $this->renderer->render($elements); + $output = $this->renderer->renderRoot($elements); // The lowest weight element should appear last in $output. $this->assertTrue(strpos($output, $second) > strpos($output, $first), 'Elements were sorted correctly by weight.'); @@ -357,7 +357,7 @@ public function testRenderSortingWithSetHashSorted() { ), '#sorted' => TRUE, ); - $output = $this->renderer->render($elements); + $output = $this->renderer->renderRoot($elements); // The elements should appear in output in the same order as the array. $this->assertTrue(strpos($output, $second) < strpos($output, $first), 'Elements were not sorted.'); @@ -439,11 +439,11 @@ public function testRenderTwice() { '#markup' => 'test', ]; - $this->assertEquals('test', $this->renderer->render($build)); + $this->assertEquals('test', $this->renderer->renderRoot($build)); $this->assertTrue($build['#printed']); // We don't want to reprint already printed render arrays. - $this->assertEquals('', $this->renderer->render($build)); + $this->assertEquals('', $this->renderer->renderRoot($build)); } /** @@ -470,10 +470,10 @@ protected function assertAccess($build, $access) { $sensitive_content = $this->randomContextValue(); $build['#markup'] = $sensitive_content; if ($access) { - $this->assertSame($sensitive_content, $this->renderer->render($build)); + $this->assertSame($sensitive_content, $this->renderer->renderRoot($build)); } else { - $this->assertSame('', $this->renderer->render($build)); + $this->assertSame('', $this->renderer->renderRoot($build)); } } @@ -565,13 +565,13 @@ public function testRenderCache() { // Render the element and confirm that it goes through the rendering // process (which will set $element['#printed']). $element = $test_element; - $this->renderer->render($element); + $this->renderer->renderRoot($element); $this->assertTrue(isset($element['#printed']), 'No cache hit'); // Render the element again and confirm that it is retrieved from the cache // instead (so $element['#printed'] will not be set). $element = $test_element; - $this->renderer->render($element); + $this->renderer->renderRoot($element); $this->assertFalse(isset($element['#printed']), 'Cache hit'); // Test that cache tags are correctly collected from the render element, @@ -608,7 +608,7 @@ public function testRenderCacheMaxAge($max_age, $is_render_cached, $render_cache ], '#markup' => '', ]; - $this->renderer->render($element); + $this->renderer->renderRoot($element); $cache_item = $this->cacheFactory->get('render')->get('render_cache_test:en:stark'); if (!$is_render_cached) { @@ -657,7 +657,7 @@ public function testRenderCacheProperties(array $expected_results) { 'child2' => ['#markup' => 2], '#custom_property' => ['custom_value'], ]; - $this->renderer->render($element); + $this->renderer->renderRoot($element); $cache = $this->cacheFactory->get('render'); $data = $cache->get('render_cache_test:en:stark')->data;