Commit ea6548bc authored by catch's avatar catch

Issue #2463009 by Wim Leers: Introduce CacheableResponseInterface: consolidate...

Issue #2463009 by Wim Leers: Introduce CacheableResponseInterface: consolidate ways of setting X-Drupal-Cache-Tags/Contexts headers
parent 669fe991
......@@ -949,6 +949,14 @@ services:
tags:
- { name: event_subscriber }
arguments: ['@path.alias_manager', '@path_processor_manager', '@path.current']
route_access_response_subscriber:
class: Drupal\Core\EventSubscriber\RouteAccessResponseSubscriber
tags:
- { name: event_subscriber }
client_error_response_subscriber:
class: Drupal\Core\EventSubscriber\ClientErrorResponseSubscriber
tags:
- { name: event_subscriber }
anonymous_user_response_subscriber:
class: Drupal\Core\EventSubscriber\AnonymousUserResponseSubscriber
tags:
......
......@@ -178,7 +178,10 @@ public static function createFromRenderArray(array $build) {
* Creates a CacheableMetadata object from a depended object.
*
* @param \Drupal\Core\Cache\CacheableDependencyInterface|mixed $object
* The object whose cacheability metadata to retrieve.
* The object whose cacheability metadata to retrieve. If it implements
* CacheableDependencyInterface, its cacheability metadata will be used,
* otherwise, the passed in object must be assumed to be uncacheable, so
* max-age 0 is set.
*
* @return static
*/
......
<?php
/**
* @file
* Contains \Drupal\Core\Cache\CacheableResponse.
*/
namespace Drupal\Core\Cache;
use Symfony\Component\HttpFoundation\Response;
/**
* A response that contains and can expose cacheability metadata.
*
* Supports Drupal's caching concepts: cache tags for invalidation and cache
* contexts for variations.
*
* @see \Drupal\Core\Cache\Cache
* @see \Drupal\Core\Cache\CacheableMetadata
* @see \Drupal\Core\Cache\CacheableResponseTrait
*/
class CacheableResponse extends Response implements CacheableResponseInterface {
use CacheableResponseTrait;
}
<?php
/**
* @file
* Contains \Drupal\Core\Cache\CacheableResponseInterface.
*/
namespace Drupal\Core\Cache;
/**
* Defines an interface for responses that can expose cacheability metadata.
*
* @see \Drupal\Core\Cache\CacheableResponseTrait
*/
interface CacheableResponseInterface {
/**
* Adds a dependency on an object: merges its cacheability metadata.
*
* E.g. when a response depends on some configuration, an entity, or an access
* result, we must make sure their cacheability metadata is present on the
* response. This method makes doing that simple.
*
* @param \Drupal\Core\Cache\CacheableDependencyInterface|mixed $dependency
* The dependency. If the object implements CacheableDependencyInterface,
* then its cacheability metadata will be used. Otherwise, the passed in
* object must be assumed to be uncacheable, so max-age 0 is set.
*
* @return $this
*
* @see \Drupal\Core\Cache\CacheableMetadata::createFromObject()
*/
public function addCacheableDependency($dependency);
/**
* Returns the cacheability metadata for this response.
*
* @return \Drupal\Core\Cache\CacheableMetadata
*/
public function getCacheableMetadata();
}
<?php
namespace Drupal\Core\Cache;
/**
* Provides an implementation of CacheableResponseInterface.
*
* @see \Drupal\Core\Cache\CacheableResponseInterface
*/
trait CacheableResponseTrait {
/**
* The cacheability metadata.
*
* @var \Drupal\Core\Cache\CacheableMetadata
*/
protected $cacheabilityMetadata;
/**
* {@inheritdoc}
*/
public function addCacheableDependency($dependency) {
// A trait doesn't have a constructor, so initialize the cacheability
// metadata if that hasn't happened yet.
if (!isset($this->cacheabilityMetadata)) {
$this->cacheabilityMetadata = new CacheableMetadata();
}
$this->cacheabilityMetadata = $this->cacheabilityMetadata->merge(CacheableMetadata::createFromObject($dependency));
return $this;
}
/**
* {@inheritdoc}
*/
public function getCacheableMetadata() {
// A trait doesn't have a constructor, so initialize the cacheability
// metadata if that hasn't happened yet.
if (!isset($this->cacheabilityMetadata)) {
$this->cacheabilityMetadata = new CacheableMetadata();
}
return $this->cacheabilityMetadata;
}
}
......@@ -169,13 +169,13 @@ public function buildForm(FieldableEntityInterface $entity, array &$form, FormSt
// Associate the cache tags for the field definition & field storage
// definition.
$field_definition = $this->getFieldDefinition($name);
$this->renderer->addDependency($form[$name], $field_definition);
$this->renderer->addDependency($form[$name], $field_definition->getFieldStorageDefinition());
$this->renderer->addCacheableDependency($form[$name], $field_definition);
$this->renderer->addCacheableDependency($form[$name], $field_definition->getFieldStorageDefinition());
}
}
// Associate the cache tags for the form display.
$this->renderer->addDependency($form, $this);
$this->renderer->addCacheableDependency($form, $this);
// Add a process callback so we can assign weights and hide extra fields.
$form['#process'][] = array($this, 'processForm');
......
......@@ -242,7 +242,7 @@ public function buildMultiple(array $entities) {
$field_access = $items->access('view', NULL, TRUE);
$build_list[$id][$name] = $field_access->isAllowed() ? $formatter->view($items) : [];
// Apply the field access cacheability metadata to the render array.
$this->renderer->addDependency($build_list[$id][$name], $field_access);
$this->renderer->addCacheableDependency($build_list[$id][$name], $field_access);
}
}
}
......
......@@ -8,6 +8,8 @@
namespace Drupal\Core\EventSubscriber;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\CacheableResponseInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
......@@ -52,6 +54,9 @@ public function onRespond(FilterResponseEvent $event) {
}
$response = $event->getResponse();
if (!$response instanceof CacheableResponseInterface) {
return;
}
// The 'user.permissions' cache context ensures that if the permissions for
// a role are modified, users are not served stale render cache content.
......@@ -60,14 +65,10 @@ public function onRespond(FilterResponseEvent $event) {
// be invalidated. Therefore, when varying by permissions and the current
// user is the anonymous user, also add the cache tag for the 'anonymous'
// role.
$cache_contexts = $response->headers->get('X-Drupal-Cache-Contexts');
if ($cache_contexts && in_array('user.permissions', explode(' ', $cache_contexts))) {
$cache_tags = ['config:user.role.anonymous'];
if ($response->headers->get('X-Drupal-Cache-Tags')) {
$existing_cache_tags = explode(' ', $response->headers->get('X-Drupal-Cache-Tags'));
$cache_tags = Cache::mergeTags($existing_cache_tags, $cache_tags);
}
$response->headers->set('X-Drupal-Cache-Tags', implode(' ', $cache_tags));
if (in_array('user.permissions', $response->getCacheableMetadata()->getCacheContexts())) {
$per_permissions_response_for_anon = new CacheableMetadata();
$per_permissions_response_for_anon->setCacheTags(['config:user.role.anonymous']);
$response->addCacheableDependency($per_permissions_response_for_anon);
}
}
......@@ -78,7 +79,10 @@ public function onRespond(FilterResponseEvent $event) {
* An array of event listener definitions.
*/
public static function getSubscribedEvents() {
$events[KernelEvents::RESPONSE][] = ['onRespond', -5];
// Priority 5, so that it runs before FinishResponseSubscriber, but after
// event subscribers that add the associated cacheability metadata (which
// have priority 10). This one is conditional, so must run after those.
$events[KernelEvents::RESPONSE][] = ['onRespond', 5];
return $events;
}
......
<?php
/**
* @file
* Contains \Drupal\Core\EventSubscriber\CacheableResponseSubscriber.
*/
namespace Drupal\Core\EventSubscriber;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\CacheableResponseInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Response subscriber to set the '4xx-response' cache tag on 4xx responses.
*/
class ClientErrorResponseSubscriber implements EventSubscriberInterface {
/**
* Sets the '4xx-response' cache tag on 4xx responses.
*
* @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
* The event to process.
*/
public function onRespond(FilterResponseEvent $event) {
if (!$event->isMasterRequest()) {
return;
}
$response = $event->getResponse();
if (!$response instanceof CacheableResponseInterface) {
return;
}
if ($response->isClientError()) {
$http_4xx_response_cacheability = new CacheableMetadata();
$http_4xx_response_cacheability->setCacheTags(['4xx-response']);
$response->addCacheableDependency($http_4xx_response_cacheability);
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
// Priority 10, so that it runs before FinishResponseSubscriber, which will
// expose the cacheability metadata in the form of headers.
$events[KernelEvents::RESPONSE][] = ['onRespond', 10];
return $events;
}
}
......@@ -10,6 +10,8 @@
use Drupal\Component\Datetime\DateTimePlus;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheableDependencyInterface;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\CacheableResponseInterface;
use Drupal\Core\Cache\CacheContextsManager;
use Drupal\Core\Config\Config;
use Drupal\Core\Config\ConfigFactoryInterface;
......@@ -133,19 +135,12 @@ public function onRespond(FilterResponseEvent $event) {
$response->headers->set($name, $value, FALSE);
}
// Apply the request's access result cacheability metadata, if it has any.
$access_result = $request->attributes->get(AccessAwareRouterInterface::ACCESS_RESULT);
if ($access_result instanceof CacheableDependencyInterface) {
$this->updateDrupalCacheHeaders($response, $access_result);
}
// Add a cache tag to any 4xx response.
if ($response->isClientError()) {
$cache_tags = ['4xx-response'];
if ($response->headers->has('X-Drupal-Cache-Tags')) {
$existing_cache_tags = explode(' ', $response->headers->get('X-Drupal-Cache-Tags'));
$cache_tags = Cache::mergeTags($existing_cache_tags, $cache_tags);
}
$response->headers->set('X-Drupal-Cache-Tags', implode(' ', $cache_tags));
// Expose the cache contexts and cache tags associated with this page in a
// X-Drupal-Cache-Contexts and X-Drupal-Cache-Tags header respectively.
if ($response instanceof CacheableResponseInterface) {
$response_cacheability = $response->getCacheableMetadata();
$response->headers->set('X-Drupal-Cache-Tags', implode(' ', $response_cacheability->getCacheTags()));
$response->headers->set('X-Drupal-Cache-Contexts', implode(' ', $this->cacheContextsManager->optimizeTokens($response_cacheability->getCacheContexts())));
}
$is_cacheable = ($this->requestPolicy->check($request) === RequestPolicyInterface::ALLOW) && ($this->responsePolicy->check($response, $request) !== ResponsePolicyInterface::DENY);
......@@ -167,30 +162,6 @@ public function onRespond(FilterResponseEvent $event) {
}
}
/**
* Updates Drupal's cache headers using the route's cacheable access result.
*
* @param \Symfony\Component\HttpFoundation\Response $response
* @param \Drupal\Core\Cache\CacheableDependencyInterface $cacheable_access_result
*/
protected function updateDrupalCacheHeaders(Response $response, CacheableDependencyInterface $cacheable_access_result) {
// X-Drupal-Cache-Tags
$cache_tags = $cacheable_access_result->getCacheTags();
if ($response->headers->has('X-Drupal-Cache-Tags')) {
$existing_cache_tags = explode(' ', $response->headers->get('X-Drupal-Cache-Tags'));
$cache_tags = Cache::mergeTags($existing_cache_tags, $cache_tags);
}
$response->headers->set('X-Drupal-Cache-Tags', implode(' ', $cache_tags));
// X-Drupal-Cache-Contexts
$cache_contexts = $cacheable_access_result->getCacheContexts();
if ($response->headers->has('X-Drupal-Cache-Contexts')) {
$existing_cache_contexts = explode(' ', $response->headers->get('X-Drupal-Cache-Contexts'));
$cache_contexts = Cache::mergeContexts($existing_cache_contexts, $cache_contexts);
}
$response->headers->set('X-Drupal-Cache-Contexts', implode(' ', $this->cacheContextsManager->optimizeTokens($cache_contexts)));
}
/**
* Determine whether the given response has a custom Cache-Control header.
*
......
<?php
/**
* @file
* Contains \Drupal\Core\EventSubscriber\CacheableResponseSubscriber.
*/
namespace Drupal\Core\EventSubscriber;
use Drupal\Core\Cache\CacheableResponseInterface;
use Drupal\Core\Routing\AccessAwareRouterInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Response subscriber to bubble the route's access result's cacheability.
*
* During routing, access checking is performed. The corresponding access result
* is stored in the Request object's attributes, just like the matching route
* object is. In case of a cacheable response, the route's access result also
* determined the content of the response, and therefore the cacheability of the
* route's access result should also be applied to the resulting response.
*
* @see \Drupal\Core\Routing\AccessAwareRouterInterface::ACCESS_RESULT
* @see \Drupal\Core\Routing\AccessAwareRouter::matchRequest()
* @see \Drupal\Core\Routing\AccessAwareRouter::checkAccess()
*/
class RouteAccessResponseSubscriber implements EventSubscriberInterface {
/**
* Bubbles the route's access result' cacheability metadata.
*
* @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
* The event to process.
*/
public function onRespond(FilterResponseEvent $event) {
if (!$event->isMasterRequest()) {
return;
}
$response = $event->getResponse();
if (!$response instanceof CacheableResponseInterface) {
return;
}
$request = $event->getRequest();
$access_result = $request->attributes->get(AccessAwareRouterInterface::ACCESS_RESULT);
$response->addCacheableDependency($access_result);
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
// Priority 10, so that it runs before FinishResponseSubscriber, which will
// expose the cacheability metadata in the form of headers.
$events[KernelEvents::RESPONSE][] = ['onRespond', 10];
return $events;
}
}
......@@ -10,6 +10,8 @@
use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\CacheableResponse;
use Drupal\Core\Cache\CacheContextsManager;
use Drupal\Core\Controller\TitleResolverInterface;
use Drupal\Core\Display\PageVariantInterface;
......@@ -161,27 +163,27 @@ public function renderResponse(array $main_content, Request $request, RouteMatch
}
$content = $this->renderer->render($html);
// Expose the cache contexts and cache tags associated with this page in a
// X-Drupal-Cache-Contexts and X-Drupal-Cache-Tags header respectively. Also
// associate the "rendered" cache tag. This allows us to invalidate the
// entire render cache, regardless of the cache bin.
$cache_contexts = [];
$cache_tags = ['rendered'];
// Set the generator in the HTTP header.
list($version) = explode('.', \Drupal::VERSION, 2);
$response = new CacheableResponse($content, 200,[
'X-Generator' => 'Drupal ' . $version . ' (https://www.drupal.org)'
]);
// Bubble the cacheability metadata associated with the rendered render
// arrays to the response.
foreach (['page_top', 'page', 'page_bottom'] as $region) {
if (isset($html[$region])) {
$cache_contexts = Cache::mergeContexts($cache_contexts, $html[$region]['#cache']['contexts']);
$cache_tags = Cache::mergeTags($cache_tags, $html[$region]['#cache']['tags']);
$response->addCacheableDependency(CacheableMetadata::createFromRenderArray($html[$region]));
}
}
// Set the generator in the HTTP header.
list($version) = explode('.', \Drupal::VERSION, 2);
// Also associate the "rendered" cache tag. This allows us to invalidate the
// entire render cache, regardless of the cache bin.
$default = new CacheableMetadata();
$default->setCacheTags(['rendered']);
$response->addCacheableDependency($default);
$response = new Response($content, 200,[
'X-Drupal-Cache-Tags' => implode(' ', $cache_tags),
'X-Drupal-Cache-Contexts' => implode(' ', $this->cacheContextsManager->optimizeTokens($cache_contexts)),
'X-Generator' => 'Drupal ' . $version . ' (https://www.drupal.org)'
]);
return $response;
}
......
......@@ -497,7 +497,7 @@ public function mergeBubbleableMetadata(array $a, array $b) {
/**
* {@inheritdoc}
*/
public function addDependency(array &$elements, $dependency) {
public function addCacheableDependency(array &$elements, $dependency) {
$meta_a = CacheableMetadata::createFromRenderArray($elements);
$meta_b = CacheableMetadata::createFromObject($dependency);
$meta_a->merge($meta_b)->applyTo($elements);
......
......@@ -334,9 +334,13 @@ public function mergeBubbleableMetadata(array $a, array $b);
* @param array &$elements
* The render array to update.
* @param \Drupal\Core\Cache\CacheableDependencyInterface|mixed $dependency
* The dependency.
* The dependency. If the object implements CacheableDependencyInterface,
* then its cacheability metadata will be used. Otherwise, the passed in
* object must be assumed to be uncacheable, so max-age 0 is set.
*
* @see \Drupal\Core\Cache\CacheableMetadata::createFromObject()
*/
public function addDependency(array &$elements, $dependency);
public function addCacheableDependency(array &$elements, $dependency);
/**
* Merges two attachments arrays (which live under the '#attached' key).
......
......@@ -362,7 +362,7 @@ protected function addParentSelectFormElements(array $book_link) {
'#suffix' => '</div>',
);
}
$this->renderer->addDependency($form, $config);
$this->renderer->addCacheableDependency($form, $config);
return $form;
}
......
......@@ -225,9 +225,9 @@ public function form(array $form, FormStateInterface $form_state) {
'#access' => $is_admin,
);
$this->renderer->addDependency($form, $config);
$this->renderer->addCacheableDependency($form, $config);
// The form depends on the field definition.
$this->renderer->addDependency($form, $field_definition->getConfig($entity->bundle()));
$this->renderer->addCacheableDependency($form, $field_definition->getConfig($entity->bundle()));
return parent::form($form, $form_state, $comment);
}
......
......@@ -89,7 +89,7 @@ public function contactSitePage(ContactFormInterface $contact_form = NULL) {
$form = $this->entityFormBuilder()->getForm($message);
$form['#title'] = SafeMarkup::checkPlain($contact_form->label());
$form['#cache']['contexts'][] = 'user.permissions';
$this->renderer->addDependency($form, $config);
$this->renderer->addCacheableDependency($form, $config);
return $form;
}
......
......@@ -203,7 +203,7 @@ protected function build($forums, TermInterface $term, $topics = array(), $paren
if (empty($term->forum_container->value)) {
$build['#attached']['feed'][] = array('taxonomy/term/' . $term->id() . '/feed', 'RSS - ' . $term->getName());
}
$this->renderer->addDependency($build, $config);
$this->renderer->addCacheableDependency($build, $config);
return [
'action' => $this->buildActionLinks($config->get('vocabulary'), $term),
......
......@@ -55,7 +55,11 @@ public function get(EntityInterface $entity) {
}
}
return new ResourceResponse($entity, 200, ['X-Drupal-Cache-Tags' => implode(' ', $entity->getCacheTags())]);
$response = new ResourceResponse($entity, 200);
// Make the response use the entity's cacheability metadata.
// @todo include access cacheability metadata, for the access checks above.
$response->addCacheableDependency($entity);
return $response;
}
/**
......
......@@ -109,14 +109,8 @@ public function handle(RouteMatchInterface $route_match, Request $request) {
$output = $serializer->serialize($data, $format);
$response->setContent($output);
$response->headers->set('Content-Type', $request->getMimeType($format));
// Add cache tags, but do not overwrite any that exist already on the
// response object.
$cache_tags = $this->container->get('config.factory')->get('rest.settings')->getCacheTags();
if ($response->headers->has('X-Drupal-Cache-Tags')) {
$existing_cache_tags = explode(' ', $response->headers->get('X-Drupal-Cache-Tags'));
$cache_tags = Cache::mergeTags($existing_cache_tags, $cache_tags);
}
$response->headers->set('X-Drupal-Cache-Tags', implode(' ', $cache_tags));
// Add rest settings config's cache tags.
$response->addCacheableDependency($this->container->get('config.factory')->get('rest.settings'));
}
return $response;
}
......
......@@ -7,6 +7,8 @@
namespace Drupal\rest;
use Drupal\Core\Cache\CacheableResponseInterface;
use Drupal\Core\Cache\CacheableResponseTrait;
use Symfony\Component\HttpFoundation\Response;
/**
......@@ -17,7 +19,9 @@
* string or an object with a __toString() method, which is not a requirement
* for data used here.
*/
class ResourceResponse extends Response {
class ResourceResponse extends Response implements CacheableResponseInterface {
use CacheableResponseTrait;
/**
* Response data that should be serialized.
......
......@@ -71,11 +71,21 @@ public function testFinishResponseSubscriber() {
// 3. controller result: Response object, globally cacheable route access.
$this->drupalGet('router_test/test1');
$headers = $this->drupalGetHeaders();
$this->assertEqual($headers['x-drupal-cache-contexts'], '');
$this->assertEqual($headers['x-drupal-cache-tags'], '');
$this->assertFalse(isset($headers['x-drupal-cache-contexts']));
$this->assertFalse(isset($headers['x-drupal-cache-tags']));
// 4. controller result: Response object, per-role cacheable route access.
$this->drupalGet('router_test/test20');
$headers = $this->drupalGetHeaders();
$this->assertFalse(isset($headers['x-drupal-cache-contexts']));
$this->assertFalse(isset($headers['x-drupal-cache-tags']));
// 5. controller result: CacheableResponse object, globally cacheable route access.
$this->drupalGet('router_test/test21');
$headers = $this->drupalGetHeaders();
$this->assertEqual($headers['x-drupal-cache-contexts'], '');
$this->assertEqual($headers['x-drupal-cache-tags'], '');
// 6. controller result: CacheableResponse object, per-role cacheable route access.
$this->drupalGet('router_test/test22');
$headers = $this->drupalGetHeaders();
$this->assertEqual($headers['x-drupal-cache-contexts'], 'user.roles');
$this->assertEqual($headers['x-drupal-cache-tags'], '');
}
......
......@@ -127,6 +127,20 @@ router_test.20:
requirements:
_role: 'anonymous'
router_test.21:
path: '/router_test/test21'
defaults:
_controller: '\Drupal\router_test\TestControllers::test21'
requirements:
_access: 'TRUE'
router_test.22:
path: '/router_test/test22'
defaults:
_controller: '\Drupal\router_test\TestControllers::test21'
requirements:
_role: 'anonymous'
router_test.hierarchy_parent:
path: '/menu-test/parent'
defaults:
......
......@@ -7,6 +7,7 @@
namespace Drupal\router_test;
use Drupal\Core\Cache\CacheableResponse;
use Drupal\Core\ParamConverter\ParamNotConvertedException;
use Drupal\user\UserInterface;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
......@@ -97,6 +98,10 @@ public function test18() {
];
}
public function test21() {
return new CacheableResponse('test21');
}
/**
* Throws an exception.
*
......
......@@ -287,7 +287,7 @@ public function permissionDependentContent() {
// The content depends on the access result.
$access = AccessResult::allowedIfHasPermission($this->currentUser, 'pet llamas');
$this->renderer->addDependency($build, $access);
$this->renderer->addCacheableDependency($build, $access);
// Build the content.
if ($access->isAllowed()) {
......
......@@ -124,7 +124,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
$form['#validate'][] = '::validateAuthentication';
$form['#validate'][] = '::validateFinal';
$this->renderer->addDependency($form, $config);
$this->renderer->addCacheableDependency($form, $config);
return $form;
}
......
......@@ -622,16 +622,16 @@ public function providerTestRenderCacheMaxAge() {
}
/**
* @covers ::addDependency
* @covers ::addCacheableDependency
*
* @dataProvider providerTestAddDependency
* @dataProvider providerTestAddCacheableDependency
*/
public function testAddDependency(array $build, $object, array $expected) {
$this->renderer->addDependency($build, $object);
public function testAddCacheableDependency(array $build, $object, array $expected) {
$this->renderer->addCacheableDependency($build, $object);
$this->assertEquals($build, $expected);
}
public function providerTestAddDependency() {
public function providerTestAddCacheableDependency() {
return [
// Empty render array, typical default cacheability.
[
......
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