diff --git a/core/lib/Drupal/Core/Entity/ContentEntityNullStorage.php b/core/lib/Drupal/Core/Entity/ContentEntityNullStorage.php index 12aeca3..f31b80e 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityNullStorage.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityNullStorage.php @@ -138,4 +138,11 @@ public function countFieldData($storage_definition, $as_bool = FALSE) { return $as_bool ? FALSE : 0; } + /** + * {@inheritdoc} + */ + public function hasData() { + return FALSE; + } + } diff --git a/core/lib/Drupal/Core/Entity/DynamicallyFieldableEntityStorageInterface.php b/core/lib/Drupal/Core/Entity/DynamicallyFieldableEntityStorageInterface.php index 6d12c98..1d20217 100644 --- a/core/lib/Drupal/Core/Entity/DynamicallyFieldableEntityStorageInterface.php +++ b/core/lib/Drupal/Core/Entity/DynamicallyFieldableEntityStorageInterface.php @@ -85,6 +85,13 @@ public function purgeFieldData(FieldDefinitionInterface $field_definition, $batc public function countFieldData($storage_definition, $as_bool = FALSE); /** + * Determines if the storage contains any data. + * + * @return bool + */ + public function hasData(); + + /** * Performs final cleanup after all data of a field has been purged. * * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $storage_definition diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php index 8368694..450fce9 100644 --- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php +++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php @@ -1765,6 +1765,17 @@ public function countFieldData($storage_definition, $as_bool = FALSE) { } /** + * {@inheritdoc} + */ + public function hasData() { + return (bool) $this->database->select($this->getBaseTable(), 'base') + ->fields('base') + ->countQuery() + ->execute() + ->fetchField(); + } + + /** * Returns whether the passed field has been already deleted. * * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $storage_definition diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php index dac6584..229dad1 100644 --- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php +++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php @@ -178,23 +178,19 @@ public function requiresFieldStorageSchemaChanges(FieldStorageDefinitionInterfac * {@inheritdoc} */ public function requiresEntityDataMigration(EntityTypeInterface $entity_type, EntityTypeInterface $original) { - // If we're updating from NULL storage, then there's no stored data that - // requires migration. - // @todo Remove in https://www.drupal.org/node/2335879. $original_storage_class = $original->getStorageClass(); - $null_storage_class = 'Drupal\Core\Entity\ContentEntityNullStorage'; - if ($original_storage_class == $null_storage_class || is_subclass_of($original_storage_class, $null_storage_class)) { - return FALSE; - } - return - // If the original storage class is different, then there might be - // existing entities in that storage even if the new storage's base - // table is empty. - // @todo Ask the old storage handler rather than assuming: - // https://www.drupal.org/node/2335879. - $entity_type->getStorageClass() != $original_storage_class || - !$this->isTableEmpty($this->storage->getBaseTable()); + // If the original storage class is different, then there might be + // existing entities in that storage even if the new storage's base + // table is empty. + if ($entity_type->getStorageClass() != $original_storage_class) { + if (!class_exists($original_storage_class)) { + return TRUE; + } + $original_storage = $original_storage_class::createInstance(\Drupal::getContainer(), $entity_type); + return $original_storage->hasData(); + } + return $this->storage->hasData(); } /** diff --git a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php index d86fe33..daead58 100644 --- a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php @@ -1180,6 +1180,68 @@ public function testLoadMultiplePersistentCacheMiss() { $this->assertEquals($entity, $entities[$id]); } + public function testHasData() { + $select_fetch_field = $this->getMockBuilder('\Drupal\Core\Database\StatementInterface') + ->disableOriginalConstructor() + ->getMock(); + + $select_fetch_field->expects($this->once()) + ->method('fetchField') + ->will($this->returnValue(TRUE)); + + $select_execute = $this->getMockBuilder('\Drupal\Core\Database\Query\Select') + ->disableOriginalConstructor() + ->getMock(); + + $select_execute->expects($this->once()) + ->method('execute') + ->will($this->returnValue($select_fetch_field)); + + $select_fields = $this->getMockBuilder('\Drupal\Core\Database\Query\Select') + ->disableOriginalConstructor() + ->getMock(); + + $select_fields->expects($this->once()) + ->method('countQuery') + ->will($this->returnValue($select_execute)); + + $database_select = $this->getMockBuilder('\Drupal\Core\Database\Query\Select') + ->disableOriginalConstructor() + ->getMock(); + + $database_select->expects($this->once()) + ->method('fields') + ->will($this->returnValue($select_fields)); + + $database = $this->getMockBuilder('Drupal\Core\Database\Connection') + ->disableOriginalConstructor() + ->getMock(); + + $database->expects($this->once()) + ->method('select') + ->will($this->returnValue($database_select)); + + $this->container->set('database', $database); + + $this->entityManager->expects($this->any()) + ->method('getDefinition') + ->will($this->returnValue($this->entityType)); + + $this->entityManager->expects($this->any()) + ->method('getFieldStorageDefinitions') + ->will($this->returnValue($this->fieldDefinitions)); + + $this->entityManager->expects($this->any()) + ->method('getBaseFieldDefinitions') + ->will($this->returnValue($this->fieldDefinitions)); + + $this->entityStorage = new SqlContentEntityStorage($this->entityType, $database, $this->entityManager, $this->cache); + + $result = $this->entityStorage->hasData(); + + $this->assertTrue($result, 'hasData returned TRUE'); + } + /** * Tests entity ID sanitization. */