EntityTypeManagerTest.php
Same filename in other branches
Namespace
Drupal\Tests\Core\EntityFile
-
core/
tests/ Drupal/ Tests/ Core/ Entity/ EntityTypeManagerTest.php
View source
<?php
declare (strict_types=1);
namespace Drupal\Tests\Core\Entity;
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityHandlerBase;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\Exception\InvalidLinkTemplateException;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Tests\UnitTestCase;
use Prophecy\Argument;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* @coversDefaultClass \Drupal\Core\Entity\EntityTypeManager
* @group Entity
*/
class EntityTypeManagerTest extends UnitTestCase {
/**
* The entity type manager under test.
*
* @var \Drupal\Core\Entity\EntityTypeManager
*/
protected $entityTypeManager;
/**
* The translation manager.
*
* @var \Drupal\Core\StringTranslation\TranslationInterface|\Prophecy\Prophecy\ProphecyInterface
*/
protected $translationManager;
/**
* The plugin discovery.
*
* @var \Drupal\Component\Plugin\Discovery\DiscoveryInterface|\Prophecy\Prophecy\ProphecyInterface
*/
protected $discovery;
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface|\Prophecy\Prophecy\ProphecyInterface
*/
protected $moduleHandler;
/**
* The cache backend.
*
* @var \Drupal\Core\Cache\CacheBackendInterface|\Prophecy\Prophecy\ProphecyInterface
*/
protected $cacheBackend;
/**
* The entity last installed schema repository.
*
* @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface|\Prophecy\Prophecy\ProphecyInterface
*/
protected $entityLastInstalledSchemaRepository;
/**
* {@inheritdoc}
*/
protected function setUp() : void {
parent::setUp();
$this->moduleHandler = $this->prophesize(ModuleHandlerInterface::class);
$this->cacheBackend = $this->prophesize(CacheBackendInterface::class);
$this->translationManager = $this->prophesize(TranslationInterface::class);
$this->entityLastInstalledSchemaRepository = $this->prophesize(EntityLastInstalledSchemaRepositoryInterface::class);
$container = $this->prophesize(Container::class);
$this->entityTypeManager = new TestEntityTypeManager(new \ArrayObject(), $this->moduleHandler
->reveal(), $this->cacheBackend
->reveal(), $this->translationManager
->reveal(), $this->getClassResolverStub(), $this->entityLastInstalledSchemaRepository
->reveal(), $container->reveal());
$this->discovery = $this->prophesize(DiscoveryInterface::class);
$this->entityTypeManager
->setDiscovery($this->discovery
->reveal());
}
/**
* Sets up the entity type manager to be tested.
*
* @param \Drupal\Core\Entity\EntityTypeInterface[]|\Prophecy\Prophecy\ProphecyInterface[] $definitions
* (optional) An array of entity type definitions.
*/
protected function setUpEntityTypeDefinitions($definitions = []) : void {
$class = get_class($this->createMock(EntityInterface::class));
foreach ($definitions as $key => $entity_type) {
// \Drupal\Core\Entity\EntityTypeInterface::getLinkTemplates() is called
// by \Drupal\Core\Entity\EntityTypeManager::processDefinition() so it must
// always be mocked.
$entity_type->getLinkTemplates()
->willReturn([]);
// Give the entity type a legitimate class to return.
$entity_type->getClass()
->willReturn($class);
$entity_type->setClass($class)
->willReturn($entity_type->reveal());
$definitions[$key] = $entity_type->reveal();
}
$this->discovery
->getDefinition(Argument::cetera())
->will(function ($args) use ($definitions) {
$entity_type_id = $args[0];
$exception_on_invalid = $args[1];
if (isset($definitions[$entity_type_id])) {
return $definitions[$entity_type_id];
}
elseif (!$exception_on_invalid) {
return NULL;
}
else {
throw new PluginNotFoundException($entity_type_id);
}
});
$this->discovery
->getDefinitions()
->willReturn($definitions);
}
/**
* Tests the hasHandler() method.
*
* @covers ::hasHandler
*
* @dataProvider providerTestHasHandler
*/
public function testHasHandler($entity_type_id, $expected) : void {
$apple = $this->prophesize(EntityTypeInterface::class);
$apple->hasHandlerClass('storage')
->willReturn(TRUE);
$banana = $this->prophesize(EntityTypeInterface::class);
$banana->hasHandlerClass('storage')
->willReturn(FALSE);
$this->setUpEntityTypeDefinitions([
'apple' => $apple,
'banana' => $banana,
]);
$entity_type = $this->entityTypeManager
->hasHandler($entity_type_id, 'storage');
$this->assertSame($expected, $entity_type);
}
/**
* Provides test data for testHasHandler().
*
* @return array
* Test data.
*/
public static function providerTestHasHandler() {
return [
[
'apple',
TRUE,
],
[
'banana',
FALSE,
],
[
'pear',
FALSE,
],
];
}
/**
* Tests the getStorage() method.
*
* @covers ::getStorage
*/
public function testGetStorage() : void {
$class = $this->getTestHandlerClass();
$entity = $this->prophesize(EntityTypeInterface::class);
$entity->getHandlerClass('storage')
->willReturn($class);
$this->setUpEntityTypeDefinitions([
'test_entity_type' => $entity,
]);
$this->assertInstanceOf($class, $this->entityTypeManager
->getStorage('test_entity_type'));
}
/**
* Tests the getListBuilder() method.
*
* @covers ::getListBuilder
*/
public function testGetListBuilder() : void {
$class = $this->getTestHandlerClass();
$entity = $this->prophesize(EntityTypeInterface::class);
$entity->getHandlerClass('list_builder')
->willReturn($class);
$this->setUpEntityTypeDefinitions([
'test_entity_type' => $entity,
]);
$this->assertInstanceOf($class, $this->entityTypeManager
->getListBuilder('test_entity_type'));
}
/**
* Tests the getViewBuilder() method.
*
* @covers ::getViewBuilder
*/
public function testGetViewBuilder() : void {
$class = $this->getTestHandlerClass();
$entity = $this->prophesize(EntityTypeInterface::class);
$entity->getHandlerClass('view_builder')
->willReturn($class);
$this->setUpEntityTypeDefinitions([
'test_entity_type' => $entity,
]);
$this->assertInstanceOf($class, $this->entityTypeManager
->getViewBuilder('test_entity_type'));
}
/**
* Tests the getAccessControlHandler() method.
*
* @covers ::getAccessControlHandler
*/
public function testGetAccessControlHandler() : void {
$class = $this->getTestHandlerClass();
$entity = $this->prophesize(EntityTypeInterface::class);
$entity->getHandlerClass('access')
->willReturn($class);
$this->setUpEntityTypeDefinitions([
'test_entity_type' => $entity,
]);
$this->assertInstanceOf($class, $this->entityTypeManager
->getAccessControlHandler('test_entity_type'));
}
/**
* Tests the getFormObject() method.
*
* @covers ::getFormObject
*/
public function testGetFormObject() : void {
$apple = $this->prophesize(EntityTypeInterface::class);
$apple->getFormClass('default')
->willReturn(TestEntityForm::class);
$banana = $this->prophesize(EntityTypeInterface::class);
$banana->getFormClass('default')
->willReturn(TestEntityFormInjected::class);
$this->setUpEntityTypeDefinitions([
'apple' => $apple,
'banana' => $banana,
]);
$apple_form = $this->entityTypeManager
->getFormObject('apple', 'default');
$this->assertInstanceOf(TestEntityForm::class, $apple_form);
$this->assertInstanceOf(ModuleHandlerInterface::class, $apple_form->moduleHandler);
$this->assertInstanceOf(TranslationInterface::class, $apple_form->stringTranslation);
$banana_form = $this->entityTypeManager
->getFormObject('banana', 'default');
$this->assertInstanceOf(TestEntityFormInjected::class, $banana_form);
$this->assertEquals('yellow', $banana_form->color);
}
/**
* Provides test data for testGetFormObjectInvalidOperation().
*
* @return array
* Test data.
*/
public static function provideFormObjectInvalidOperationData() : array {
return [
'missing_form_handler' => [
'test_entity_type',
'edit',
'',
'The "test_entity_type" entity type did not specify a "edit" form class.',
],
'missing_form_handler_class' => [
'test_entity_type',
'edit',
'Drupal\\test_entity_type\\Form\\NonExistingClass',
'The "edit" form handler of the "test_entity_type" entity type specifies a non-existent class "Drupal\\test_entity_type\\Form\\NonExistingClass".',
],
];
}
/**
* Tests the getFormObject() method with an invalid operation.
*
* @covers ::getFormObject
*
* @dataProvider provideFormObjectInvalidOperationData
*/
public function testGetFormObjectInvalidOperation(string $entity_type_id, string $operation, string $form_class, string $exception_message) : void {
$entity = $this->prophesize(EntityTypeInterface::class);
$entity->getFormClass($operation)
->willReturn(NULL);
if (!$form_class) {
$entity->getHandlerClasses()
->willReturn([]);
}
else {
$entity->getHandlerClasses()
->willReturn([
'form' => [
$operation => $form_class,
],
]);
}
$this->setUpEntityTypeDefinitions([
$entity_type_id => $entity,
]);
$this->expectException(InvalidPluginDefinitionException::class);
$this->expectExceptionMessage($exception_message);
$this->entityTypeManager
->getFormObject($entity_type_id, $operation);
}
/**
* Tests the getHandler() method.
*
* @covers ::getHandler
*/
public function testGetHandler() : void {
$class = get_class($this->getMockForAbstractClass(TestEntityHandlerBase::class));
$apple = $this->prophesize(EntityTypeInterface::class);
$apple->getHandlerClass('storage')
->willReturn($class);
$this->setUpEntityTypeDefinitions([
'apple' => $apple,
]);
$apple_controller = $this->entityTypeManager
->getHandler('apple', 'storage');
$this->assertInstanceOf($class, $apple_controller);
$this->assertInstanceOf(ModuleHandlerInterface::class, $apple_controller->moduleHandler);
$this->assertInstanceOf(TranslationInterface::class, $apple_controller->stringTranslation);
}
/**
* Provides test data for testGetHandlerMissingHandler().
*
* @return array
* Test data.
*/
public static function provideMissingHandlerData() : array {
return [
'missing_handler' => [
'test_entity_type',
'storage',
'',
'The "test_entity_type" entity type did not specify a storage handler.',
],
'missing_handler_class' => [
'test_entity_type',
'storage',
'Non_Existing_Class',
'The storage handler of the "test_entity_type" entity type specifies a non-existent class "Non_Existing_Class".',
],
];
}
/**
* Tests the getHandler() method when no controller is defined.
*
* @covers ::getHandler
*
* @dataProvider provideMissingHandlerData
*/
public function testGetHandlerMissingHandler(string $entity_type, string $handler_name, string $handler_class, $exception_message) : void {
$entity = $this->prophesize(EntityTypeInterface::class);
$entity->getHandlerClass($handler_name)
->willReturn(NULL);
if (!$handler_class) {
$entity->getHandlerClasses()
->willReturn([]);
}
else {
$entity->getHandlerClasses()
->willReturn([
$handler_name => $handler_class,
]);
}
$this->setUpEntityTypeDefinitions([
$entity_type => $entity,
]);
$this->expectException(InvalidPluginDefinitionException::class);
$this->expectExceptionMessage($exception_message);
$this->entityTypeManager
->getHandler($entity_type, $handler_name);
}
/**
* @covers ::getRouteProviders
*/
public function testGetRouteProviders() : void {
$apple = $this->prophesize(EntityTypeInterface::class);
$apple->getRouteProviderClasses()
->willReturn([
'default' => TestRouteProvider::class,
]);
$this->setUpEntityTypeDefinitions([
'apple' => $apple,
]);
$apple_route_provider = $this->entityTypeManager
->getRouteProviders('apple');
$this->assertInstanceOf(TestRouteProvider::class, $apple_route_provider['default']);
$this->assertInstanceOf(ModuleHandlerInterface::class, $apple_route_provider['default']->moduleHandler);
$this->assertInstanceOf(TranslationInterface::class, $apple_route_provider['default']->stringTranslation);
}
/**
* Tests the processDefinition() method.
*
* @covers ::processDefinition
*/
public function testProcessDefinition() : void {
$apple = $this->prophesize(EntityTypeInterface::class);
$this->setUpEntityTypeDefinitions([
'apple' => $apple,
]);
$apple->getLinkTemplates()
->willReturn([
'canonical' => 'path/to/apple',
]);
$definition = $apple->reveal();
$this->expectException(InvalidLinkTemplateException::class);
$this->expectExceptionMessage("Link template 'canonical' for entity type 'apple' must start with a leading slash, the current link template is 'path/to/apple'");
$this->entityTypeManager
->processDefinition($definition, 'apple');
}
/**
* Tests the getDefinition() method.
*
* @covers ::getDefinition
*
* @dataProvider providerTestGetDefinition
*/
public function testGetDefinition($entity_type_id, $expected) : void {
$entity = $this->prophesize(EntityTypeInterface::class);
$this->setUpEntityTypeDefinitions([
'apple' => $entity,
'banana' => $entity,
]);
$entity_type = $this->entityTypeManager
->getDefinition($entity_type_id, FALSE);
if ($expected) {
$this->assertInstanceOf(EntityTypeInterface::class, $entity_type);
}
else {
$this->assertNull($entity_type);
}
}
/**
* Provides test data for testGetDefinition().
*
* @return array
* Test data.
*/
public static function providerTestGetDefinition() {
return [
[
'apple',
TRUE,
],
[
'banana',
TRUE,
],
[
'pear',
FALSE,
],
];
}
/**
* Tests the getDefinition() method with an invalid definition.
*
* @covers ::getDefinition
*/
public function testGetDefinitionInvalidException() : void {
$this->setUpEntityTypeDefinitions();
$this->expectException(PluginNotFoundException::class);
$this->expectExceptionMessage('The "pear" entity type does not exist.');
$this->entityTypeManager
->getDefinition('pear', TRUE);
}
/**
* Gets a mock controller class name.
*
* @return string
* A mock controller class name.
*/
protected function getTestHandlerClass() : string {
return get_class($this->getMockForAbstractClass(EntityHandlerBase::class));
}
}
/**
* Provides a test entity handler.
*/
abstract class TestEntityHandlerBase extends EntityHandlerBase {
/**
* {@inheritdoc}
*/
public $moduleHandler;
/**
* {@inheritdoc}
*/
public $stringTranslation;
}
/**
* Provides a test entity type manager.
*/
class TestEntityTypeManager extends EntityTypeManager {
/**
* Sets the discovery for the manager.
*
* @param \Drupal\Component\Plugin\Discovery\DiscoveryInterface $discovery
* The discovery object.
*/
public function setDiscovery(DiscoveryInterface $discovery) : void {
$this->discovery = $discovery;
}
}
/**
* Provides a test entity form.
*/
class TestEntityForm extends EntityHandlerBase {
/**
* {@inheritdoc}
*/
public $moduleHandler;
/**
* {@inheritdoc}
*/
public $stringTranslation;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* {@inheritdoc}
*/
public function getBaseFormId() {
return 'the_base_form_id';
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'the_form_id';
}
/**
* {@inheritdoc}
*/
public function setEntity(EntityInterface $entity) {
return $this;
}
/**
* {@inheritdoc}
*/
public function setOperation($operation) {
return $this;
}
/**
* {@inheritdoc}
*/
public function setEntityTypeManager(EntityTypeManagerInterface $entity_type_manager) {
$this->entityTypeManager = $entity_type_manager;
return $this;
}
}
/**
* Provides a test entity form that uses injection.
*/
class TestEntityFormInjected extends TestEntityForm implements ContainerInjectionInterface {
/**
* The color of the entity type.
*
* @var string
*/
public $color;
/**
* Constructs a new TestEntityFormInjected.
*
* @param string $color
* The color of the entity type.
*/
public function __construct($color) {
$this->color = $color;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static('yellow');
}
}
/**
* Provides a test entity route provider.
*/
class TestRouteProvider extends EntityHandlerBase {
/**
* {@inheritdoc}
*/
public $moduleHandler;
/**
* {@inheritdoc}
*/
public $stringTranslation;
}
Classes
Title | Deprecated | Summary |
---|---|---|
EntityTypeManagerTest | @coversDefaultClass \Drupal\Core\Entity\EntityTypeManager @group Entity | |
TestEntityForm | Provides a test entity form. | |
TestEntityFormInjected | Provides a test entity form that uses injection. | |
TestEntityHandlerBase | Provides a test entity handler. | |
TestEntityTypeManager | Provides a test entity type manager. | |
TestRouteProvider | Provides a test entity route provider. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.