Issue #2099105 by Berdir, andypost, amateescu, larowlan: Clean-up render cache when permission changes.

8.0.x
Nathaniel Catchpole 2014-01-10 11:30:55 +00:00
parent 2a839b7d01
commit 667ec43270
9 changed files with 35 additions and 28 deletions

View File

@ -37,14 +37,6 @@ class EntityViewBuilder implements EntityControllerInterface, EntityViewBuilderI
*/ */
protected $entityManager; protected $entityManager;
/**
* An array of view mode info for the type of entities for which this
* controller is instantiated.
*
* @var array
*/
protected $viewModesInfo;
/** /**
* The cache bin used to store the render cache. * The cache bin used to store the render cache.
* *
@ -67,7 +59,6 @@ class EntityViewBuilder implements EntityControllerInterface, EntityViewBuilderI
$this->entityType = $entity_info->id(); $this->entityType = $entity_info->id();
$this->entityInfo = $entity_info; $this->entityInfo = $entity_info;
$this->entityManager = $entity_manager; $this->entityManager = $entity_manager;
$this->viewModesInfo = entity_get_view_modes($this->entityType);
} }
/** /**
@ -136,10 +127,8 @@ class EntityViewBuilder implements EntityControllerInterface, EntityViewBuilderI
); );
// Cache the rendered output if permitted by the view mode and global entity // Cache the rendered output if permitted by the view mode and global entity
// type configuration. The isset() checks below are necessary because // type configuration.
// 'default' is not an actual view mode. if ($this->isViewModeCacheable($view_mode) && !$entity->isNew() && !isset($entity->in_preview) && $this->entityInfo->isRenderCacheable()) {
$view_mode_is_cacheable = !isset($this->viewModesInfo[$view_mode]) || (isset($this->viewModesInfo[$view_mode]) && $this->viewModesInfo[$view_mode]['cache']);
if ($view_mode_is_cacheable && !$entity->isNew() && !isset($entity->in_preview) && $this->entityInfo->isRenderCacheable()) {
$return['#cache'] = array( $return['#cache'] = array(
'keys' => array('entity_view', $this->entityType, $entity->id(), $view_mode), 'keys' => array('entity_view', $this->entityType, $entity->id(), $view_mode),
'granularity' => DRUPAL_CACHE_PER_ROLE, 'granularity' => DRUPAL_CACHE_PER_ROLE,
@ -265,4 +254,23 @@ class EntityViewBuilder implements EntityControllerInterface, EntityViewBuilderI
\Drupal::cache($this->cacheBin)->deleteTags(array($this->entityType . '_view' => TRUE)); \Drupal::cache($this->cacheBin)->deleteTags(array($this->entityType . '_view' => TRUE));
} }
} }
/**
* Returns TRUE if the view mode is cacheable.
*
* @param string $view_mode
* Name of the view mode that should be rendered.
*
* @return bool
* TRUE if the view mode can be cached, FALSE otherwise.
*/
protected function isViewModeCacheable($view_mode) {
if ($view_mode == 'default') {
// The 'default' is not an actual view mode.
return TRUE;
}
$view_modes_info = entity_get_view_modes($this->entityType);
return !empty($view_modes_info[$view_mode]['cache']);
}
} }

View File

@ -305,9 +305,6 @@ class CommentNonNodeTest extends WebTestBase {
'view test entity' => TRUE, 'view test entity' => TRUE,
'skip comment approval' => FALSE, 'skip comment approval' => FALSE,
)); ));
// We've changed role permissions, so need to reset render cache.
// @todo Revisit after https://drupal.org/node/2099105
\Drupal::entityManager()->getViewBuilder('entity_test')->resetCache(array($this->entity));
$this->drupalGet('entity_test/' . $this->entity->id()); $this->drupalGet('entity_test/' . $this->entity->id());
$this->assertPattern('@<h2[^>]*>Comments</h2>@', 'Comments were displayed.'); $this->assertPattern('@<h2[^>]*>Comments</h2>@', 'Comments were displayed.');
$this->assertLink('Log in', 0, 'Link to log in was found.'); $this->assertLink('Log in', 0, 'Link to log in was found.');
@ -324,9 +321,6 @@ class CommentNonNodeTest extends WebTestBase {
'skip comment approval' => TRUE, 'skip comment approval' => TRUE,
'view test entity' => TRUE, 'view test entity' => TRUE,
)); ));
// We've changed role permissions, so need to reset render cache.
// @todo Revisit after https://drupal.org/node/2099105
\Drupal::entityManager()->getViewBuilder('entity_test')->resetCache(array($this->entity));
$this->drupalGet('entity_test/' . $this->entity->id()); $this->drupalGet('entity_test/' . $this->entity->id());
$this->assertNoPattern('@<h2[^>]*>Comments</h2>@', 'Comments were not displayed.'); $this->assertNoPattern('@<h2[^>]*>Comments</h2>@', 'Comments were not displayed.');
$this->assertFieldByName('subject', '', 'Subject field found.'); $this->assertFieldByName('subject', '', 'Subject field found.');

View File

@ -109,6 +109,10 @@ abstract class EntityDisplayModeFormBase extends EntityFormController {
* TRUE if the display mode exists, FALSE otherwise. * TRUE if the display mode exists, FALSE otherwise.
*/ */
public function exists($entity_id, array $element, array $form_state) { public function exists($entity_id, array $element, array $form_state) {
// Do not allow to add internal 'default' view mode.
if ($entity_id == 'default') {
return TRUE;
}
return (bool) $this->queryFactory return (bool) $this->queryFactory
->get($this->entity->entityType()) ->get($this->entity->entityType())
->condition('id', $element['#field_prefix'] . $entity_id) ->condition('id', $element['#field_prefix'] . $entity_id)

View File

@ -14,7 +14,7 @@ use Drupal\simpletest\DrupalUnitTestBase;
*/ */
class FilterDefaultConfigTest extends DrupalUnitTestBase { class FilterDefaultConfigTest extends DrupalUnitTestBase {
public static $modules = array('system', 'user', 'filter', 'filter_test'); public static $modules = array('system', 'user', 'filter', 'filter_test', 'entity');
public static function getInfo() { public static function getInfo() {
return array( return array(

View File

@ -169,7 +169,7 @@ class RdfMapping extends ConfigEntityBase implements RdfMappingInterface {
public function postSave(EntityStorageControllerInterface $storage_controller, $update = TRUE) { public function postSave(EntityStorageControllerInterface $storage_controller, $update = TRUE) {
parent::postSave($storage_controller, $update); parent::postSave($storage_controller, $update);
if (\Drupal::entityManager()->hasController($this->targetEntityType, 'render')) { if (\Drupal::entityManager()->hasController($this->targetEntityType, 'view_builder')) {
\Drupal::entityManager()->getViewBuilder($this->targetEntityType)->resetCache(); \Drupal::entityManager()->getViewBuilder($this->targetEntityType)->resetCache();
} }
} }

View File

@ -19,7 +19,7 @@ class DrupalUnitTestBaseTest extends DrupalUnitTestBase {
* *
* @var array * @var array
*/ */
public static $modules = array('entity_test'); public static $modules = array('entity', 'entity_test');
public static function getInfo() { public static function getInfo() {
return array( return array(
@ -33,14 +33,14 @@ class DrupalUnitTestBaseTest extends DrupalUnitTestBase {
* Tests expected behavior of setUp(). * Tests expected behavior of setUp().
*/ */
function testSetUp() { function testSetUp() {
$module = 'entity_test'; $modules = array('entity', 'entity_test');
$table = 'entity_test'; $table = 'entity_test';
// Verify that specified $modules have been loaded. // Verify that specified $modules have been loaded.
$this->assertTrue(function_exists('entity_test_permission'), "$module.module was loaded."); $this->assertTrue(function_exists('entity_test_permission'), 'entity_test.module was loaded.');
// Verify that there is a fixed module list. // Verify that there is a fixed module list.
$this->assertIdentical(array_keys(\Drupal::moduleHandler()->getModuleList()), array($module)); $this->assertIdentical(array_keys(\Drupal::moduleHandler()->getModuleList()), $modules);
$this->assertIdentical(\Drupal::moduleHandler()->getImplementations('permission'), array($module)); $this->assertIdentical(\Drupal::moduleHandler()->getImplementations('permission'), $modules);
// Verify that no modules have been installed. // Verify that no modules have been installed.
$this->assertFalse(db_table_exists($table), "'$table' database table not found."); $this->assertFalse(db_table_exists($table), "'$table' database table not found.");

View File

@ -101,7 +101,6 @@ class EntityViewControllerTest extends WebTestBase {
))->save(); ))->save();
// Browse to the entity and verify that the attributes from both modules // Browse to the entity and verify that the attributes from both modules
// are rendered in the field item HTML markup. // are rendered in the field item HTML markup.
\Drupal::entityManager()->getViewBuilder('entity_test')->resetCache(array($entity));
$this->drupalGet('entity_test/' . $entity->id()); $this->drupalGet('entity_test/' . $entity->id());
$xpath = $this->xpath('//div[@data-field-item-attr="foobar" and @property="schema:text" and text()=:value]', array(':value' => $test_value)); $xpath = $this->xpath('//div[@data-field-item-attr="foobar" and @property="schema:text" and text()=:value]', array(':value' => $test_value));
$this->assertTrue($xpath, 'The field item attributes from both modules have been found in the rendered output of the field.'); $this->assertTrue($xpath, 'The field item attributes from both modules have been found in the rendered output of the field.');

View File

@ -141,6 +141,8 @@ class Role extends ConfigEntityBase implements RoleInterface {
parent::postSave($storage_controller, $update); parent::postSave($storage_controller, $update);
Cache::invalidateTags(array('role' => $this->id())); Cache::invalidateTags(array('role' => $this->id()));
// Clear render cache.
entity_render_cache_clear();
} }
/** /**

View File

@ -23,7 +23,7 @@ class UserEntityTest extends DrupalUnitTestBase {
* *
* @var array * @var array
*/ */
public static $modules = array('system', 'user', 'field'); public static $modules = array('system', 'user', 'field', 'entity');
public static function getInfo() { public static function getInfo() {
return array( return array(