moduleHandler = $this->prophesize(ModuleHandlerInterface::class); $this->moduleHandler->getImplementations('entity_type_build')->willReturn([]); $this->moduleHandler->alter('entity_type', Argument::type('array'))->willReturn(NULL); $this->cacheBackend = $this->prophesize(CacheBackendInterface::class); $this->translationManager = $this->prophesize(TranslationInterface::class); $this->entityTypeManager = new TestEntityTypeManager(new \ArrayObject(), $this->moduleHandler->reveal(), $this->cacheBackend->reveal(), $this->translationManager->reveal(), $this->getClassResolverStub()); $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 = []) { $class = $this->getMockClass(EntityInterface::class); foreach ($definitions as $key => $entity_type) { // \Drupal\Core\Entity\EntityTypeInterface::getLinkTemplates() is called // by \Drupal\Core\Entity\EntityManager::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) { $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 function providerTestHasHandler() { return [ ['apple', TRUE], ['banana', FALSE], ['pear', FALSE], ]; } /** * Tests the getStorage() method. * * @covers ::getStorage */ public function testGetStorage() { $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() { $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() { $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() { $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() { $entity_manager = $this->prophesize(EntityManagerInterface::class); $container = $this->prophesize(ContainerInterface::class); $container->get('entity.manager')->willReturn($entity_manager->reveal()); \Drupal::setContainer($container->reveal()); $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->assertAttributeInstanceOf(ModuleHandlerInterface::class, 'moduleHandler', $apple_form); $this->assertAttributeInstanceOf(TranslationInterface::class, 'stringTranslation', $apple_form); $banana_form = $this->entityTypeManager->getFormObject('banana', 'default'); $this->assertInstanceOf(TestEntityFormInjected::class, $banana_form); $this->assertAttributeEquals('yellow', 'color', $banana_form); } /** * Tests the getFormObject() method with an invalid operation. * * @covers ::getFormObject */ public function testGetFormObjectInvalidOperation() { $entity = $this->prophesize(EntityTypeInterface::class); $entity->getFormClass('edit')->willReturn(''); $this->setUpEntityTypeDefinitions(['test_entity_type' => $entity]); $this->setExpectedException(InvalidPluginDefinitionException::class); $this->entityTypeManager->getFormObject('test_entity_type', 'edit'); } /** * Tests the getHandler() method. * * @covers ::getHandler */ public function testGetHandler() { $class = $this->getTestHandlerClass(); $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->assertAttributeInstanceOf(ModuleHandlerInterface::class, 'moduleHandler', $apple_controller); $this->assertAttributeInstanceOf(TranslationInterface::class, 'stringTranslation', $apple_controller); } /** * Tests the getHandler() method when no controller is defined. * * @covers ::getHandler */ public function testGetHandlerMissingHandler() { $entity = $this->prophesize(EntityTypeInterface::class); $entity->getHandlerClass('storage')->willReturn(''); $this->setUpEntityTypeDefinitions(['test_entity_type' => $entity]); $this->setExpectedException(InvalidPluginDefinitionException::class); $this->entityTypeManager->getHandler('test_entity_type', 'storage'); } /** * @covers ::getRouteProviders */ public function testGetRouteProviders() { $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->assertAttributeInstanceOf(ModuleHandlerInterface::class, 'moduleHandler', $apple_route_provider['default']); $this->assertAttributeInstanceOf(TranslationInterface::class, 'stringTranslation', $apple_route_provider['default']); } /** * Tests the processDefinition() method. * * @covers ::processDefinition */ public function testProcessDefinition() { $apple = $this->prophesize(EntityTypeInterface::class); $this->setUpEntityTypeDefinitions(['apple' => $apple]); $apple->getLinkTemplates()->willReturn(['canonical' => 'path/to/apple']); $definition = $apple->reveal(); $this->setExpectedException(InvalidLinkTemplateException::class, "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) { $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 function providerTestGetDefinition() { return [ ['apple', TRUE], ['banana', TRUE], ['pear', FALSE], ]; } /** * Tests the getDefinition() method with an invalid definition. * * @covers ::getDefinition */ public function testGetDefinitionInvalidException() { $this->setUpEntityTypeDefinitions(); $this->setExpectedException(PluginNotFoundException::class, '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() { return get_class($this->getMockForAbstractClass(EntityHandlerBase::class)); } } 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) { $this->discovery = $discovery; } } /** * Provides a test entity form. */ class TestEntityForm extends EntityHandlerBase { /** * The entity manager. * * @var \Drupal\Core\Entity\EntityManagerInterface */ protected $entityManager; /** * 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 setEntityManager(EntityManagerInterface $entity_manager) { $this->entityManager = $entity_manager; 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 */ protected $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 { }