diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php index 53be393..a031ac8 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php @@ -334,9 +334,9 @@ protected function invokeHook($hook, EntityInterface $entity) { } /** - * Implements Drupal\Core\Entity\EntityStorageInterface::getQueryServiceName(). + * {@inheritdoc} */ - public function getQueryServiceName() { + protected function getQueryServiceName() { return 'entity.query.config'; } diff --git a/core/lib/Drupal/Core/Entity/ContentEntityNullStorage.php b/core/lib/Drupal/Core/Entity/ContentEntityNullStorage.php index f31b80e..b9843c8 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityNullStorage.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityNullStorage.php @@ -78,7 +78,7 @@ public function save(EntityInterface $entity) { /** * {@inheritdoc} */ - public function getQueryServiceName() { + protected function getQueryServiceName() { throw new QueryException('Null implementation can not be queried.'); } diff --git a/core/lib/Drupal/Core/Entity/DynamicallyFieldableEntityStorageInterface.php b/core/lib/Drupal/Core/Entity/DynamicallyFieldableEntityStorageInterface.php index 1d20217..a5a9a94 100644 --- a/core/lib/Drupal/Core/Entity/DynamicallyFieldableEntityStorageInterface.php +++ b/core/lib/Drupal/Core/Entity/DynamicallyFieldableEntityStorageInterface.php @@ -88,6 +88,7 @@ public function countFieldData($storage_definition, $as_bool = FALSE); * Determines if the storage contains any data. * * @return bool + * TRUE if the storage contains data, FALSE if not. */ public function hasData(); diff --git a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php index a1dea1d..13f9862 100644 --- a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php @@ -244,7 +244,7 @@ public function hasHandler($entity_type, $handler_type); * @param string $handler_type * The controller type to create an instance for. * - * @return mixed + * @return object * A handler instance. * * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException @@ -263,7 +263,7 @@ public function getHandler($entity_type, $handler_type); * @param \Drupal\Core\Entity\EntityTypeInterface $definition * The entity type definition. * - * @return mixed + * @return object * A handler instance. */ public function createHandlerInstance($class, EntityTypeInterface $definition = null); diff --git a/core/lib/Drupal/Core/Entity/EntityStorageBase.php b/core/lib/Drupal/Core/Entity/EntityStorageBase.php index 5d2c2aa..6f3751d 100644 --- a/core/lib/Drupal/Core/Entity/EntityStorageBase.php +++ b/core/lib/Drupal/Core/Entity/EntityStorageBase.php @@ -465,4 +465,21 @@ public function getQuery($conjunction = 'AND') { return \Drupal::service($this->getQueryServicename())->get($this->entityType, $conjunction); } + /** + * {@inheritdoc} + */ + public function getAggregateQuery($conjunction = 'AND') { + // Access the service directly rather than entity.query factory so the + // storage's current entity type is used. + return \Drupal::service($this->getQueryServicename())->getAggregate($this->entityType, $conjunction); + } + + /** + * Gets the name of the service for the query for this entity storage. + * + * @return string + * The name of the service for the query for this entity storage. + */ + abstract protected function getQueryServiceName(); + } diff --git a/core/lib/Drupal/Core/Entity/EntityStorageInterface.php b/core/lib/Drupal/Core/Entity/EntityStorageInterface.php index 6da72fe..b4c897e 100644 --- a/core/lib/Drupal/Core/Entity/EntityStorageInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityStorageInterface.php @@ -148,14 +148,6 @@ public function delete(array $entities); public function save(EntityInterface $entity); /** - * Gets the name of the service for the query for this entity storage. - * - * @return string - * The name of the service for the query for this entity storage. - */ - public function getQueryServiceName(); - - /** * Returns an entity query instance. * * @param string $conjunction @@ -166,11 +158,26 @@ public function getQueryServiceName(); * @return \Drupal\Core\Entity\Query\QueryInterface * The query instance. * - * @see \Drupal\Core\Entity\EntityStorageInterface::getQueryServiceName() + * @see \Drupal\Core\Entity\EntityStorageBase::getQueryServiceName() */ public function getQuery($conjunction = 'AND'); /** + * Returns an aggregated query instance. + * + * @param string $conjunction + * (optional) The logical operator for the query, either: + * - AND: all of the conditions on the query need to match. + * - OR: at least one of the conditions on the query need to match. + * + * @return \Drupal\Core\Entity\Query\QueryAggregateInterface + * The aggregated query object that can query the given entity type. + * + * @see \Drupal\Core\Entity\EntityStorageBase::getQueryServiceName() + */ + public function getAggregateQuery($conjunction = 'AND'); + + /** * Returns the entity type ID. * * @return string diff --git a/core/lib/Drupal/Core/Entity/KeyValueStore/KeyValueEntityStorage.php b/core/lib/Drupal/Core/Entity/KeyValueStore/KeyValueEntityStorage.php index 59ca4d8..3507502 100644 --- a/core/lib/Drupal/Core/Entity/KeyValueStore/KeyValueEntityStorage.php +++ b/core/lib/Drupal/Core/Entity/KeyValueStore/KeyValueEntityStorage.php @@ -202,7 +202,7 @@ protected function has($id, EntityInterface $entity) { /** * {@inheritdoc} */ - public function getQueryServiceName() { + protected function getQueryServiceName() { return 'entity.query.keyvalue'; } diff --git a/core/lib/Drupal/Core/Entity/Query/QueryFactory.php b/core/lib/Drupal/Core/Entity/Query/QueryFactory.php index 5cfda2b..d7777c9 100644 --- a/core/lib/Drupal/Core/Entity/Query/QueryFactory.php +++ b/core/lib/Drupal/Core/Entity/Query/QueryFactory.php @@ -14,9 +14,8 @@ /** * Factory class Creating entity query objects. * - * This class should not be overridden in the container. - * EntityStorageBase::getQuery() accesses the storages query service directly - * without using this factory. + * Any implementation of this service must call getQuery()/getAggregateQuery() + * of the corresponding entity storage. * * @see \Drupal\Core\Entity\EntityStorageBase::getQuery() * @@ -73,8 +72,7 @@ public function get($entity_type_id, $conjunction = 'AND') { * The aggregated query object that can query the given entity type. */ public function getAggregate($entity_type_id, $conjunction = 'AND') { - $service_name = $this->entityManager->getStorage($entity_type_id)->getQueryServiceName(); - return $this->container->get($service_name)->getAggregate($this->entityManager->getDefinition($entity_type_id), $conjunction); + return $this->entityManager->getStorage($entity_type_id)->getAggregateQuery($conjunction); } } diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php index b8db248..d46c37e 100644 --- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php +++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php @@ -1198,7 +1198,7 @@ protected function saveRevision(EntityInterface $entity) { /** * {@inheritdoc} */ - public function getQueryServiceName() { + protected function getQueryServiceName() { return 'entity.query.sql'; } diff --git a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php index 4aaa11a..a3a7013 100644 --- a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php @@ -1062,13 +1062,15 @@ public function providerTestRequiresEntityDataMigration() { ->getMock(); $updated_entity_type_definition->expects($this->any()) ->method('getStorageClass') - ->willReturn('\Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema'); // A class that exists, *any* class. + // A class that exists, *any* class. + ->willReturn('\Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema'); $original_entity_type_definition = $this->getMockBuilder('\Drupal\Core\Entity\EntityTypeInterface') ->disableOriginalConstructor() ->getMock(); $original_entity_type_definition->expects($this->any()) ->method('getStorageClass') - ->willReturn('\Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema'); // A class that exists, *any* class. + // A class that exists, *any* class. + ->willReturn('\Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema'); $original_entity_type_definition_other_nonexisting = $this->getMockBuilder('\Drupal\Core\Entity\EntityTypeInterface') ->disableOriginalConstructor() ->getMock(); @@ -1080,7 +1082,8 @@ public function providerTestRequiresEntityDataMigration() { ->getMock(); $original_entity_type_definition_other_existing->expects($this->any()) ->method('getStorageClass') - ->willReturn('\Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema'); // A class that exists, *any* class. + // A class that exists, *any* class. + ->willReturn('\Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema'); return [ // Case 1: same storage class, ::hasData() === TRUE.