Version 1
[yaffs-website] / web / core / tests / Drupal / Tests / Core / Entity / EntityTypeManagerTest.php
diff --git a/web/core/tests/Drupal/Tests/Core/Entity/EntityTypeManagerTest.php b/web/core/tests/Drupal/Tests/Core/Entity/EntityTypeManagerTest.php
new file mode 100644 (file)
index 0000000..4e2a79f
--- /dev/null
@@ -0,0 +1,507 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Entity\EntityTypeManagerTest.
+ */
+
+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\EntityManagerInterface;
+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\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;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->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 {
+
+}