diff --git a/core/modules/views/src/EventSubscriber/ViewsEntitySchemaSubscriber.php b/core/modules/views/src/EventSubscriber/ViewsEntitySchemaSubscriber.php index 0d53f32..84dcb73 100644 --- a/core/modules/views/src/EventSubscriber/ViewsEntitySchemaSubscriber.php +++ b/core/modules/views/src/EventSubscriber/ViewsEntitySchemaSubscriber.php @@ -16,7 +16,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** - * Reacts to changes on entity types. + * Reacts to changes on entity types to update all views entities. */ class ViewsEntitySchemaSubscriber implements EventSubscriberInterface { @@ -44,6 +44,36 @@ class ViewsEntitySchemaSubscriber implements EventSubscriberInterface { const DATA_TABLE_REMOVAL = 3; /** + * Indicates that a revision table got renamed. + */ + const REVISION_TABLE_RENAME = 4; + + /** + * Indicates that a revision table got added. + */ + const REVISION_TABLE_ADDITION = 5; + + /** + * Indicates that a revision table got removed. + */ + const REVISION_TABLE_REMOVAL = 6; + + /** + * Indicates that a revision data table got renamed. + */ + const REVISION_DATA_TABLE_RENAME = 7; + + /** + * Indicates that a revision data table got added. + */ + const REVISION_DATA_TABLE_ADDITION = 8; + + /** + * Indicates that a revision data table got removed. + */ + const REVISION_DATA_TABLE_REMOVAL = 9; + + /** * The entity manager. * * @var \Drupal\Core\Entity\EntityManagerInterface @@ -78,40 +108,75 @@ public function onEntityTypeCreate(EntityTypeInterface $entity_type) { */ public function onEntityTypeUpdate(EntityTypeInterface $entity_type, EntityTypeInterface $original) { $changes = []; + + // Checks for base tables. if ($entity_type->getBaseTable() != $original->getBaseTable()) { $changes[] = static::BASE_TABLE_RENAME; } + + // Checks for data tables. if ($original->getDataTable() !== NULL && $entity_type->getDataTable() != $original->getDataTable()) { $changes[] = static::DATA_TABLE_RENAME; } - if ($original->getDataTable() === NULL && $entity_type->getDataTable()) { + elseif ($original->getDataTable() === NULL && $entity_type->getDataTable()) { $changes[] = static::DATA_TABLE_ADDITION; } - if ($original->getDataTable() && $entity_type->getDataTable() === NULL) { + elseif ($original->getDataTable() && $entity_type->getDataTable() === NULL) { $changes[] = static::DATA_TABLE_REMOVAL; } + // Checks for revision tables. + if ($original->getRevisionTable() !== NULL && $entity_type->getRevisionTable() != $original->getRevisionTable()) { + $changes[] = static::REVISION_TABLE_RENAME; + } + elseif ($original->getRevisionTable() === NULL && $entity_type->getRevisionTable()) { + $changes[] = static::REVISION_TABLE_ADDITION; + } + elseif ($original->getRevisionTable() && $entity_type->getRevisionTable() === NULL) { + $changes[] = static::REVISION_TABLE_REMOVAL; + } + + // Checks for revision data tables. + if ($original->getRevisionDataTable() !== NULL && $entity_type->getRevisionDataTable() != $original->getRevisionDataTable()) { + $changes[] = static::REVISION_DATA_TABLE_RENAME; + } + elseif ($original->getRevisionDataTable() === NULL && $entity_type->getRevisionDataTable()) { + $changes[] = static::REVISION_DATA_TABLE_ADDITION; + } + elseif ($original->getRevisionDataTable() && $entity_type->getRevisionDataTable() === NULL) { + $changes[] = static::REVISION_DATA_TABLE_REMOVAL; + } + $all_views = $this->entityManager->getStorage('view')->loadMultiple(NULL); foreach ($changes as $change) { switch ($change) { case static::BASE_TABLE_RENAME: - debug("base table rename"); $this->baseTableRename($all_views, $entity_type->id(), $original->getBaseTable(), $entity_type->getBaseTable()); break; case static::DATA_TABLE_RENAME: - debug("data table rename"); $this->baseTableRename($all_views, $entity_type->id(), $original->getBaseTable(), $entity_type->getBaseTable()); $this->dataTableRename($all_views, $entity_type->id(), $original->getDataTable(), $entity_type->getDataTable()); break; case static::DATA_TABLE_ADDITION: - debug("data table addition"); $this->dataTableAddition($all_views, $entity_type, $original, $original->getDataTable()); break; case static::DATA_TABLE_REMOVAL: - debug("data table removal"); $this->dataTableRemoval($all_views, $entity_type->id(), $entity_type->getDataTable(), $entity_type->getBaseTable()); break; + // @TODO Implement / decide about all those revision cases. + case static::REVISION_TABLE_RENAME: + break; + case static::REVISION_TABLE_ADDITION: + break; + case static::REVISION_TABLE_REMOVAL: + break; + case static::REVISION_DATA_TABLE_RENAME: + break; + case static::REVISION_DATA_TABLE_ADDITION: + break; + case static::REVISION_DATA_TABLE_REMOVAL: + break; } } @@ -270,6 +335,8 @@ protected function dataTableAddition($all_views, EntityTypeInterface $entity_typ $data_table_fields = $table_mapping->getFieldNames($entity_type->getDataTable()); $base_table_fields = $table_mapping->getFieldNames($entity_type->getBaseTable()); + $data_table = $entity_type->getDataTable(); + foreach ($all_views as $view) { foreach (array_keys($view->get('display')) as $display_id) { $display = &$view->getDisplay($display_id); @@ -282,7 +349,7 @@ protected function dataTableAddition($all_views, EntityTypeInterface $entity_typ if (isset($handler_config['entity_type']) && isset($handler_config['entity_field']) && $handler_config['entity_type'] == $entity_type_id) { // Move all fields which just exists on the data table. if (in_array($handler_config['entity_field'], $data_table_fields) && !in_array($handler_config['entity_field'], $base_table_fields)) { - $handler_config['table'] = $entity_type->getDataTable(); + $handler_config['table'] = $data_table; } } } @@ -346,6 +413,7 @@ protected function removeFieldStorage($all_views, $entity_type_id, $field_name) foreach ($display['display_options'][$handler_type] as $id => &$handler_config) { // If the removed field matches, remove the handler configuration. if (isset($handler_config['entity_type']) && isset($handler_config['entity_field']) && $handler_config['entity_type'] == $entity_type_id && $handler_config['entity_field'] == $field_name) { + // @todo Should we not instead unset($display['display_options'][$handler_type][$id]); } } diff --git a/core/modules/views/src/Tests/EventSubscriber/ViewsEntitySchemaSubscriberIntegrationTest.php b/core/modules/views/src/Tests/EventSubscriber/ViewsEntitySchemaSubscriberIntegrationTest.php index 36b7840..617fe21 100644 --- a/core/modules/views/src/Tests/EventSubscriber/ViewsEntitySchemaSubscriberIntegrationTest.php +++ b/core/modules/views/src/Tests/EventSubscriber/ViewsEntitySchemaSubscriberIntegrationTest.php @@ -92,39 +92,38 @@ protected function setUp() { $this->installSchema('system', 'key_value_expire'); } + /** + * Tests that views are disabled when an entity type is deleted. + */ public function testDeleteEntityType() { - $entity_manager = \Drupal::entityManager(); - $entity_storage = $entity_manager->getStorage('view'); + $entity_storage = $this->entityManager->getStorage('view'); $views = $entity_storage->loadMultiple(); - // user module provides 3 views for themselves. + // User module provides 3 views for themselves. $this->assertEqual(6, count($views)); - $event = new EntityTypeEvent($entity_manager->getDefinition('entity_test_update')); + $event = new EntityTypeEvent($this->entityManager->getDefinition('entity_test_update')); $this->eventDispatcher->dispatch(EntityTypeEvents::DELETE, $event); - // We expect that views which use 'entity_test_Update' as base tables are + // We expect that views which use 'entity_test_update' as base tables are // disabled. $views = $entity_storage->loadMultiple(); $this->assertEqual(6, count($views)); - $disabled = 0; - array_walk($views, function(View $view) use (&$disabled) { - if (!$view->status()) { - $disabled++; - } - }); - // Ensure that all related views are disabled. - $this->assertEqual(3, $disabled); + $this->assertFalse($views['test_view_entity_test']->status()); + $this->assertFalse($views['test_view_entity_test_data']->status()); + $this->assertFalse($views['test_view_entity_test_additional_base_field']->status()); } + /** + * Tests that renaming base tables adapts the views. + */ public function testBaseTableRename() { $this->renameBaseTable(); $this->entityDefinitionUpdateManager->applyUpdates(); /** @var \Drupal\views\Entity\View $view */ - $entity_manager = \Drupal::entityManager(); - $entity_storage = $entity_manager->getStorage('view'); + $entity_storage = $this->entityManager->getStorage('view'); $view = $entity_storage->load('test_view_entity_test'); // Ensure the base table got renamed, so also the views fields. @@ -134,6 +133,9 @@ public function testBaseTableRename() { $this->assertEqual('entity_test_update_new', $display['display_options']['fields']['name']['table']); } + /** + * Tests that renaming data tables adapts the views. + */ public function testDataTableRename() { $this->updateEntityTypeToTranslatable(); $this->entityDefinitionUpdateManager->applyUpdates(); @@ -142,8 +144,7 @@ public function testDataTableRename() { $this->entityDefinitionUpdateManager->applyUpdates(); /** @var \Drupal\views\Entity\View $view */ - $entity_manager = \Drupal::entityManager(); - $entity_storage = $entity_manager->getStorage('view'); + $entity_storage = $this->entityManager->getStorage('view'); $view = $entity_storage->load('test_view_entity_test_data'); // Ensure the data table got renamed, so also the views fields. @@ -153,13 +154,15 @@ public function testDataTableRename() { $this->assertEqual('entity_test_update_data_new', $display['display_options']['fields']['name']['table']); } + /** + * Tests that adding data tables adapts the views. + */ public function testDataTableAddition() { $this->updateEntityTypeToTranslatable(); $this->entityDefinitionUpdateManager->applyUpdates(); /** @var \Drupal\views\Entity\View $view */ - $entity_manager = \Drupal::entityManager(); - $entity_storage = $entity_manager->getStorage('view'); + $entity_storage = $this->entityManager->getStorage('view'); $view = $entity_storage->load('test_view_entity_test'); // Ensure the data table got renamed, so also the views fields. @@ -169,13 +172,15 @@ public function testDataTableAddition() { $this->assertEqual('entity_test_update_data', $display['display_options']['fields']['name']['table']); } + /** + * Tests that enabling revisions doesn't do anything. + */ public function testRevisionEnabling() { $this->updateEntityTypeToRevisionable(); $this->entityDefinitionUpdateManager->applyUpdates(); /** @var \Drupal\views\Entity\View $view */ - $entity_manager = \Drupal::entityManager(); - $entity_storage = $entity_manager->getStorage('view'); + $entity_storage = $this->entityManager->getStorage('view'); $view = $entity_storage->load('test_view_entity_test'); // Ensure that nothing happens. @@ -185,6 +190,9 @@ public function testRevisionEnabling() { $this->assertEqual('entity_test_update', $display['display_options']['fields']['name']['table']); } + /** + * Tests that removing fields adapts the existing views. + */ public function testRemoveFields() { $this->addBaseField(); $this->entityDefinitionUpdateManager->applyUpdates(); @@ -192,8 +200,7 @@ public function testRemoveFields() { $this->entityDefinitionUpdateManager->applyUpdates(); /** @var \Drupal\views\Entity\View $view */ - $entity_manager = \Drupal::entityManager(); - $entity_storage = $entity_manager->getStorage('view'); + $entity_storage = $this->entityManager->getStorage('view'); $view = $entity_storage->load('test_view_entity_test_additional_base_field'); // Ensure that nothing happens. @@ -202,8 +209,12 @@ public function testRemoveFields() { $this->assertFalse(isset($display['display_options']['fields']['new_base_field'])); } + /** + * Tests a bunch possible entity definition table updates. + */ public function testVariousTableUpdates() { // @fixme ... include a revision field as well. + // @fixme ... Add an explicit test for the langcode. // We want to test the following permutations of entity definition updates: // base <-> base + translation @@ -323,9 +334,11 @@ public function testVariousTableUpdates() { $this->assertEqual('entity_test_update', $display['display_options']['fields']['name']['table']); } + /** + * Gets a view and its display. + */ protected function getUpdatedViewAndDisplay() { - $entity_manager = \Drupal::entityManager(); - $entity_storage = $entity_manager->getStorage('view'); + $entity_storage = $this->entityManager->getStorage('view'); /** @var \Drupal\views\Entity\View $view */ $view = $entity_storage->load('test_view_entity_test'); $display = $view->getDisplay('default');