Example #1
0
 /**
  * Tests post-render cache-integrated 'render_cache_placeholder' child
  * element.
  */
 function testDrupalRenderChildElementRenderCachePlaceholder()
 {
     $container = array('#type' => 'container');
     $context = array('bar' => $this->randomContextValue());
     $callback = 'common_test_post_render_cache_placeholder';
     $placeholder = drupal_render_cache_generate_placeholder($callback, $context);
     $test_element = array('#post_render_cache' => array($callback => array($context)), '#markup' => $placeholder, '#prefix' => '<foo>', '#suffix' => '</foo>');
     $container['test_element'] = $test_element;
     $expected_output = '<div><foo><bar>' . $context['bar'] . '</bar></foo></div>' . "\n";
     // #cache disabled.
     drupal_static_reset('_drupal_add_js');
     $element = $container;
     $output = drupal_render($element);
     $this->assertIdentical($output, $expected_output, 'Placeholder was replaced in output');
     $settings = $this->parseDrupalSettings(drupal_get_js());
     $this->assertIdentical($settings['common_test'], $context, '#attached is modified; JavaScript setting is added to page.');
     // The cache system is turned off for POST requests.
     $request_method = \Drupal::request()->getMethod();
     \Drupal::request()->setMethod('GET');
     // GET request: #cache enabled, cache miss.
     drupal_static_reset('_drupal_add_js');
     $element = $container;
     $element['#cache'] = array('cid' => 'render_cache_placeholder_test_GET');
     $element['test_element']['#cache'] = array('cid' => 'render_cache_placeholder_test_child_GET');
     // Simulate element rendering in a template, where sub-items of a renderable
     // can be sent to drupal_render() before the parent.
     $child =& $element['test_element'];
     $element['#children'] = drupal_render($child, TRUE);
     // Eventually, drupal_render() gets called on the root element.
     $output = drupal_render($element);
     $this->assertIdentical($output, $expected_output, 'Placeholder was replaced in output');
     $this->assertTrue(isset($element['#printed']), 'No cache hit');
     $this->assertIdentical($element['#markup'], $expected_output, 'Placeholder was replaced in #markup.');
     $settings = $this->parseDrupalSettings(drupal_get_js());
     $this->assertIdentical($settings['common_test'], $context, '#attached is modified; JavaScript setting is added to page.');
     // GET request: validate cached data for child element.
     $child_tokens = $element['test_element']['#post_render_cache']['common_test_post_render_cache_placeholder'][0]['token'];
     $parent_tokens = $element['#post_render_cache']['common_test_post_render_cache_placeholder'][0]['token'];
     $expected_token = $child_tokens;
     $element = array('#cache' => array('cid' => 'render_cache_placeholder_test_child_GET'));
     $cached_element = \Drupal::cache('render')->get(drupal_render_cid_create($element))->data;
     // Parse unique token out of the cached markup.
     $dom = Html::load($cached_element['#markup']);
     $xpath = new \DOMXPath($dom);
     $nodes = $xpath->query('//*[@token]');
     $this->assertTrue($nodes->length, 'The token attribute was found in the cached child element markup');
     $token = '';
     if ($nodes->length) {
         $token = $nodes->item(0)->getAttribute('token');
     }
     $this->assertIdentical($token, $expected_token, 'The tokens are identical for the child element');
     // Verify the token is in the cached element.
     $expected_element = array('#markup' => '<foo><drupal-render-cache-placeholder callback="common_test_post_render_cache_placeholder" token="' . $expected_token . '"></drupal-render-cache-placeholder></foo>', '#post_render_cache' => array('common_test_post_render_cache_placeholder' => array($context)), '#cache' => array('tags' => array('rendered' => TRUE)));
     $this->assertIdentical($cached_element, $expected_element, 'The correct data is cached for the child element: the stored #markup and #attached properties are not affected by #post_render_cache callbacks.');
     // GET request: validate cached data (for the parent/entire render array).
     $element = array('#cache' => array('cid' => 'render_cache_placeholder_test_GET'));
     $cached_element = \Drupal::cache('render')->get(drupal_render_cid_create($element))->data;
     // Parse unique token out of the cached markup.
     $dom = Html::load($cached_element['#markup']);
     $xpath = new \DOMXPath($dom);
     $nodes = $xpath->query('//*[@token]');
     $this->assertTrue($nodes->length, 'The token attribute was found in the cached parent element markup');
     $token = '';
     if ($nodes->length) {
         $token = $nodes->item(0)->getAttribute('token');
     }
     $this->assertIdentical($token, $expected_token, 'The tokens are identical for the parent element');
     // Verify the token is in the cached element.
     $expected_element = array('#markup' => '<div><foo><drupal-render-cache-placeholder callback="common_test_post_render_cache_placeholder" token="' . $expected_token . '"></drupal-render-cache-placeholder></foo></div>' . "\n", '#post_render_cache' => array('common_test_post_render_cache_placeholder' => array($context)), '#cache' => array('tags' => array('rendered' => TRUE)));
     $this->assertIdentical($cached_element, $expected_element, 'The correct data is cached for the parent element: the stored #markup and #attached properties are not affected by #post_render_cache callbacks.');
     // GET request: validate cached data.
     // Check the cache of the child element again after the parent has been
     // rendered.
     $element = array('#cache' => array('cid' => 'render_cache_placeholder_test_child_GET'));
     $cached_element = \Drupal::cache('render')->get(drupal_render_cid_create($element))->data;
     // Verify that the child element contains the correct
     // render_cache_placeholder markup.
     $expected_token = $child_tokens;
     $dom = Html::load($cached_element['#markup']);
     $xpath = new \DOMXPath($dom);
     $nodes = $xpath->query('//*[@token]');
     $this->assertTrue($nodes->length, 'The token attribute was found in the cached child element markup');
     $token = '';
     if ($nodes->length) {
         $token = $nodes->item(0)->getAttribute('token');
     }
     $this->assertIdentical($token, $expected_token, 'The tokens are identical for the child element');
     // Verify the token is in the cached element.
     $expected_element = array('#markup' => '<foo><drupal-render-cache-placeholder callback="common_test_post_render_cache_placeholder" token="' . $expected_token . '"></drupal-render-cache-placeholder></foo>', '#post_render_cache' => array('common_test_post_render_cache_placeholder' => array($context)), '#cache' => array('tags' => array('rendered' => TRUE)));
     $this->assertIdentical($cached_element, $expected_element, 'The correct data is cached for the child element: the stored #markup and #attached properties are not affected by #post_render_cache callbacks.');
     // GET request: #cache enabled, cache hit.
     drupal_static_reset('_drupal_add_js');
     $element = $container;
     $element['#cache'] = array('cid' => 'render_cache_placeholder_test_GET');
     // Simulate element rendering in a template, where sub-items of a renderable
     // can be sent to drupal_render before the parent.
     $child =& $element['test_element'];
     $element['#children'] = drupal_render($child, TRUE);
     $output = drupal_render($element);
     $this->assertIdentical($output, $expected_output, 'Placeholder was replaced in output');
     $this->assertFalse(isset($element['#printed']), 'Cache hit');
     $this->assertIdentical($element['#markup'], $expected_output, 'Placeholder was replaced in #markup.');
     $settings = $this->parseDrupalSettings(drupal_get_js());
     $this->assertIdentical($settings['common_test'], $context, '#attached is modified; JavaScript setting is added to page.');
     // Restore the previous request method.
     \Drupal::request()->setMethod($request_method);
 }
 /**
  * Tests entity render cache with references.
  */
 public function testEntityViewBuilderCacheWithReferences()
 {
     // Force a request via GET so we can get drupal_render() cache working.
     $request = \Drupal::request();
     $request_method = $request->server->get('REQUEST_METHOD');
     $request->setMethod('GET');
     // Create an entity reference field and an entity that will be referenced.
     entity_reference_create_instance('entity_test', 'entity_test', 'reference_field', 'Reference', 'entity_test');
     entity_get_display('entity_test', 'entity_test', 'full')->setComponent('reference_field')->save();
     $entity_test_reference = $this->createTestEntity('entity_test');
     $entity_test_reference->save();
     // Get a fully built entity view render array for the referenced entity.
     $build = $this->container->get('entity.manager')->getViewBuilder('entity_test')->view($entity_test_reference, 'full');
     $cid_reference = drupal_render_cid_create($build);
     $bin_reference = $build['#cache']['bin'];
     // Mock the build array to not require the theme registry.
     unset($build['#theme']);
     $build['#markup'] = 'entity_render_test';
     drupal_render($build);
     // Test that a cache entry was created for the referenced entity.
     $this->assertTrue($this->container->get('cache.' . $bin_reference)->get($cid_reference), 'The entity render element for the referenced entity has been cached.');
     // Create another entity that references the first one.
     $entity_test = $this->createTestEntity('entity_test');
     $entity_test->reference_field->entity = $entity_test_reference;
     $entity_test->save();
     // Get a fully built entity view render array.
     $build = $this->container->get('entity.manager')->getViewBuilder('entity_test')->view($entity_test, 'full');
     $cid = drupal_render_cid_create($build);
     $bin = $build['#cache']['bin'];
     // Mock the build array to not require the theme registry.
     unset($build['#theme']);
     $build['#markup'] = 'entity_render_test';
     drupal_render($build);
     // Test that a cache entry is created.
     $this->assertTrue($this->container->get('cache.' . $bin)->get($cid), 'The entity render element has been cached.');
     // Save the entity and verify that both cache entries have been deleted.
     $entity_test->save();
     $this->assertFalse($this->container->get('cache.' . $bin)->get($cid), 'The entity render cache has been cleared when the entity was deleted.');
     $this->assertFalse($this->container->get('cache.' . $bin_reference)->get($cid_reference), 'The entity render cache for the referenced entity has been cleared when the entity was deleted.');
     // Restore the previous request method.
     $request->setMethod($request_method);
 }
 /**
  * Tests block render cache handling with configurable cache contexts.
  *
  * This is only intended to test that an existing block can be configured with
  * additional contexts, not to test that each context works correctly.
  *
  * @see \Drupal\block\Tests\BlockCacheTest
  */
 public function testBlockViewBuilderCacheContexts()
 {
     // Force a request via GET so we can get drupal_render() cache working.
     $request = \Drupal::request();
     $request_method = $request->server->get('REQUEST_METHOD');
     $request->setMethod('GET');
     // First: no cache context.
     $this->setBlockCacheConfig(array('max_age' => 600));
     $build = $this->getBlockRenderArray();
     $cid = drupal_render_cid_create($build);
     drupal_render($build);
     $this->assertTrue($this->container->get('cache.render', $cid), 'The block render element has been cached.');
     // Second: the "per URL" cache context.
     $this->setBlockCacheConfig(array('max_age' => 600, 'contexts' => array('cache_context.url')));
     $old_cid = $cid;
     $build = $this->getBlockRenderArray();
     $cid = drupal_render_cid_create($build);
     drupal_render($build);
     $this->assertTrue($this->container->get('cache.render', $cid), 'The block render element has been cached.');
     $this->assertNotEqual($cid, $old_cid, 'The cache ID has changed.');
     // Third: the same block configuration, but a different URL.
     $original_url_cache_context = $this->container->get('cache_context.url');
     $request_stack = new RequestStack();
     $request_stack->push(Request::create('/foo'));
     $temp_context = new UrlCacheContext($request_stack);
     $this->container->set('cache_context.url', $temp_context);
     $old_cid = $cid;
     $build = $this->getBlockRenderArray();
     $cid = drupal_render_cid_create($build);
     drupal_render($build);
     $this->assertTrue($this->container->get('cache.render', $cid), 'The block render element has been cached.');
     $this->assertNotEqual($cid, $old_cid, 'The cache ID has changed.');
     $this->container->set('cache_context.url', $original_url_cache_context);
     // Restore the previous request method.
     $request->setMethod($request_method);
 }
Example #4
0
 /**
  * Tests child element that uses #post_render_cache but that is rendered via a
  * template.
  */
 function testDrupalRenderChildElementRenderCachePlaceholder()
 {
     $context = array('bar' => $this->randomContextValue());
     $callback = 'common_test_post_render_cache_placeholder';
     $placeholder = drupal_render_cache_generate_placeholder($callback, $context);
     $test_element = ['#theme' => 'common_test_render_element', 'foo' => ['#post_render_cache' => [$callback => [$context]], '#markup' => $placeholder, '#prefix' => '<pre>', '#suffix' => '</pre>']];
     $expected_output = '<pre><bar>' . $context['bar'] . '</bar></pre>' . "\n";
     // #cache disabled.
     $element = $test_element;
     $output = drupal_render_root($element);
     $this->assertIdentical($output, $expected_output, 'Placeholder was replaced in output');
     $expected_js = [['type' => 'setting', 'data' => ['common_test' => $context]]];
     $this->assertIdentical($element['#attached']['js'], $expected_js, '#attached is modified; JavaScript setting is added to page.');
     // The cache system is turned off for POST requests.
     $request_method = \Drupal::request()->getMethod();
     \Drupal::request()->setMethod('GET');
     // GET request: #cache enabled, cache miss.
     $element = $test_element;
     $element['#cache'] = array('cid' => 'render_cache_placeholder_test_GET');
     $element['foo']['#cache'] = array('cid' => 'render_cache_placeholder_test_child_GET');
     // Render, which will use the common-test-render-element.html.twig template.
     $output = drupal_render_root($element);
     $this->assertIdentical($output, $expected_output);
     //, 'Placeholder was replaced in output');
     $this->assertTrue(isset($element['#printed']), 'No cache hit');
     $this->assertIdentical($element['#markup'], $expected_output, 'Placeholder was replaced in #markup.');
     $this->assertIdentical($element['#attached']['js'], $expected_js, '#attached is modified; JavaScript setting is added to page.');
     // GET request: validate cached data for child element.
     $child_tokens = $element['foo']['#post_render_cache']['common_test_post_render_cache_placeholder'][0]['token'];
     $parent_tokens = $element['#post_render_cache']['common_test_post_render_cache_placeholder'][0]['token'];
     $expected_token = $child_tokens;
     $element = array('#cache' => array('cid' => 'render_cache_placeholder_test_child_GET'));
     $cached_element = \Drupal::cache('render')->get(drupal_render_cid_create($element))->data;
     // Parse unique token out of the cached markup.
     $dom = Html::load($cached_element['#markup']);
     $xpath = new \DOMXPath($dom);
     $nodes = $xpath->query('//*[@token]');
     $this->assertTrue($nodes->length, 'The token attribute was found in the cached child element markup');
     $token = '';
     if ($nodes->length) {
         $token = $nodes->item(0)->getAttribute('token');
     }
     $this->assertIdentical($token, $expected_token, 'The tokens are identical for the child element');
     // Verify the token is in the cached element.
     $expected_element = array('#markup' => '<pre><drupal-render-cache-placeholder callback="common_test_post_render_cache_placeholder" token="' . $expected_token . '"></drupal-render-cache-placeholder></pre>', '#attached' => array(), '#post_render_cache' => array('common_test_post_render_cache_placeholder' => array($context)), '#cache' => array('tags' => array('rendered')));
     $this->assertIdentical($cached_element, $expected_element, 'The correct data is cached for the child element: the stored #markup and #attached properties are not affected by #post_render_cache callbacks.');
     // GET request: validate cached data (for the parent/entire render array).
     $element = array('#cache' => array('cid' => 'render_cache_placeholder_test_GET'));
     $cached_element = \Drupal::cache('render')->get(drupal_render_cid_create($element))->data;
     // Parse unique token out of the cached markup.
     $dom = Html::load($cached_element['#markup']);
     $xpath = new \DOMXPath($dom);
     $nodes = $xpath->query('//*[@token]');
     $this->assertTrue($nodes->length, 'The token attribute was found in the cached parent element markup');
     $token = '';
     if ($nodes->length) {
         $token = $nodes->item(0)->getAttribute('token');
     }
     $this->assertIdentical($token, $expected_token, 'The tokens are identical for the parent element');
     // Verify the token is in the cached element.
     $expected_element = array('#markup' => '<pre><drupal-render-cache-placeholder callback="common_test_post_render_cache_placeholder" token="' . $expected_token . '"></drupal-render-cache-placeholder></pre>' . "\n", '#attached' => array(), '#post_render_cache' => array('common_test_post_render_cache_placeholder' => array($context)), '#cache' => array('tags' => array('rendered')));
     $this->assertIdentical($cached_element, $expected_element);
     //, 'The correct data is cached for the parent element: the stored #markup and #attached properties are not affected by #post_render_cache callbacks.');
     // GET request: validate cached data.
     // Check the cache of the child element again after the parent has been
     // rendered.
     $element = array('#cache' => array('cid' => 'render_cache_placeholder_test_child_GET'));
     $cached_element = \Drupal::cache('render')->get(drupal_render_cid_create($element))->data;
     // Verify that the child element contains the correct
     // render_cache_placeholder markup.
     $expected_token = $child_tokens;
     $dom = Html::load($cached_element['#markup']);
     $xpath = new \DOMXPath($dom);
     $nodes = $xpath->query('//*[@token]');
     $this->assertTrue($nodes->length, 'The token attribute was found in the cached child element markup');
     $token = '';
     if ($nodes->length) {
         $token = $nodes->item(0)->getAttribute('token');
     }
     $this->assertIdentical($token, $expected_token, 'The tokens are identical for the child element');
     // Verify the token is in the cached element.
     $expected_element = array('#markup' => '<pre><drupal-render-cache-placeholder callback="common_test_post_render_cache_placeholder" token="' . $expected_token . '"></drupal-render-cache-placeholder></pre>', '#attached' => array(), '#post_render_cache' => array('common_test_post_render_cache_placeholder' => array($context)), '#cache' => array('tags' => array('rendered')));
     $this->assertIdentical($cached_element, $expected_element, 'The correct data is cached for the child element: the stored #markup and #attached properties are not affected by #post_render_cache callbacks.');
     // GET request: #cache enabled, cache hit.
     $element = $test_element;
     $element['#cache'] = array('cid' => 'render_cache_placeholder_test_GET');
     // Render, which will use the common-test-render-element.html.twig template.
     $output = drupal_render_root($element);
     $this->assertIdentical($output, $expected_output, 'Placeholder was replaced in output');
     $this->assertFalse(isset($element['#printed']), 'Cache hit');
     $this->assertIdentical($element['#markup'], $expected_output, 'Placeholder was replaced in #markup.');
     $this->assertIdentical($element['#attached']['js'], $expected_js, '#attached is modified; JavaScript setting is added to page.');
     // Restore the previous request method.
     \Drupal::request()->setMethod($request_method);
 }