class EntityFieldManagerTest

Same name and namespace in other branches
  1. 9 core/tests/Drupal/Tests/Core/Entity/EntityFieldManagerTest.php \Drupal\Tests\Core\Entity\EntityFieldManagerTest
  2. 8.9.x core/tests/Drupal/Tests/Core/Entity/EntityFieldManagerTest.php \Drupal\Tests\Core\Entity\EntityFieldManagerTest
  3. 11.x core/tests/Drupal/Tests/Core/Entity/EntityFieldManagerTest.php \Drupal\Tests\Core\Entity\EntityFieldManagerTest

@coversDefaultClass \Drupal\Core\Entity\EntityFieldManager
@group Entity

Hierarchy

Expanded class hierarchy of EntityFieldManagerTest

File

core/tests/Drupal/Tests/Core/Entity/EntityFieldManagerTest.php, line 42

Namespace

Drupal\Tests\Core\Entity
View source
class EntityFieldManagerTest extends UnitTestCase {
  
  /**
   * The typed data manager.
   *
   * @var \Drupal\Core\TypedData\TypedDataManagerInterface|\Prophecy\Prophecy\ProphecyInterface
   */
  protected $typedDataManager;
  
  /**
   * The module handler.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface|\Prophecy\Prophecy\ProphecyInterface
   */
  protected $moduleHandler;
  
  /**
   * The cache backend to use.
   *
   * @var \Drupal\Core\Cache\CacheBackendInterface|\Prophecy\Prophecy\ProphecyInterface
   */
  protected $cacheBackend;
  
  /**
   * The cache tags invalidator.
   *
   * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface|\Prophecy\Prophecy\ProphecyInterface
   */
  protected $cacheTagsInvalidator;
  
  /**
   * The language manager.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface|\Prophecy\Prophecy\ProphecyInterface
   */
  protected $languageManager;
  
  /**
   * The keyvalue factory.
   *
   * @var \Drupal\Core\KeyValueStore\KeyValueFactoryInterface|\Prophecy\Prophecy\ProphecyInterface
   */
  protected $keyValueFactory;
  
  /**
   * The event dispatcher.
   *
   * @var \Symfony\Contracts\EventDispatcher\EventDispatcherInterface|\Prophecy\Prophecy\ProphecyInterface
   */
  protected $eventDispatcher;
  
  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface|\Prophecy\Prophecy\ProphecyInterface
   */
  protected $entityTypeManager;
  
  /**
   * The entity type repository.
   *
   * @var \Drupal\Core\Entity\EntityTypeRepositoryInterface|\Prophecy\Prophecy\ProphecyInterface
   */
  protected $entityTypeRepository;
  
  /**
   * The entity type bundle info.
   *
   * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface|\Prophecy\Prophecy\ProphecyInterface
   */
  protected $entityTypeBundleInfo;
  
  /**
   * The entity display repository.
   *
   * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface|\Prophecy\Prophecy\ProphecyInterface
   */
  protected $entityDisplayRepository;
  
  /**
   * The entity field manager under test.
   *
   * @var \Drupal\Core\Entity\EntityFieldManager
   */
  protected $entityFieldManager;
  
  /**
   * The dependency injection container.
   *
   * @var \Symfony\Component\DependencyInjection\ContainerInterface|\Prophecy\Prophecy\ProphecyInterface
   */
  protected $container;
  
  /**
   * The entity type definition.
   *
   * @var \Drupal\Core\Entity\EntityTypeInterface|\Prophecy\Prophecy\ProphecyInterface
   */
  protected $entityType;
  
  /**
   * The entity last installed schema repository.
   *
   * @var \Prophecy\Prophecy\ObjectProphecy|\Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface
   */
  protected $entityLastInstalledSchemaRepository;
  
  /**
   * {@inheritdoc}
   */
  protected function setUp() : void {
    parent::setUp();
    $this->container = $this->prophesize(ContainerInterface::class);
    \Drupal::setContainer($this->container
      ->reveal());
    $this->typedDataManager = $this->prophesize(TypedDataManagerInterface::class);
    $this->typedDataManager
      ->getDefinition('field_item:boolean')
      ->willReturn([
      'class' => BooleanItem::class,
    ]);
    $this->container
      ->get('typed_data_manager')
      ->willReturn($this->typedDataManager
      ->reveal());
    $this->moduleHandler = $this->prophesize(ModuleHandlerInterface::class);
    $this->moduleHandler
      ->alter('entity_base_field_info', Argument::type('array'), Argument::any())
      ->willReturn(NULL);
    $this->moduleHandler
      ->alter('entity_bundle_field_info', Argument::type('array'), Argument::any(), Argument::type('string'))
      ->willReturn(NULL);
    $this->cacheBackend = $this->prophesize(CacheBackendInterface::class);
    $this->cacheTagsInvalidator = $this->prophesize(CacheTagsInvalidatorInterface::class);
    $language = new Language([
      'id' => 'en',
    ]);
    $this->languageManager = $this->prophesize(LanguageManagerInterface::class);
    $this->languageManager
      ->getCurrentLanguage()
      ->willReturn($language);
    $this->languageManager
      ->getLanguages()
      ->willReturn([
      'en' => (object) [
        'id' => 'en',
      ],
    ]);
    $this->keyValueFactory = $this->prophesize(KeyValueFactoryInterface::class);
    $this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class);
    $this->entityTypeRepository = $this->prophesize(EntityTypeRepositoryInterface::class);
    $this->entityTypeBundleInfo = $this->prophesize(EntityTypeBundleInfoInterface::class);
    $this->entityDisplayRepository = $this->prophesize(EntityDisplayRepositoryInterface::class);
    $this->entityLastInstalledSchemaRepository = $this->prophesize(EntityLastInstalledSchemaRepositoryInterface::class);
    $this->entityFieldManager = new TestEntityFieldManager($this->entityTypeManager
      ->reveal(), $this->entityTypeBundleInfo
      ->reveal(), $this->entityDisplayRepository
      ->reveal(), $this->typedDataManager
      ->reveal(), $this->languageManager
      ->reveal(), $this->keyValueFactory
      ->reveal(), $this->moduleHandler
      ->reveal(), $this->cacheBackend
      ->reveal(), $this->entityLastInstalledSchemaRepository
      ->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 = []) {
    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([]);
      $definitions[$key] = $entity_type->reveal();
    }
    $this->entityTypeManager
      ->getDefinition(Argument::type('string'))
      ->will(function ($args) use ($definitions) {
      if (isset($definitions[$args[0]])) {
        return $definitions[$args[0]];
      }
      throw new PluginNotFoundException($args[0]);
    });
    $this->entityTypeManager
      ->getDefinition(Argument::type('string'), FALSE)
      ->will(function ($args) use ($definitions) {
      if (isset($definitions[$args[0]])) {
        return $definitions[$args[0]];
      }
    });
    $this->entityTypeManager
      ->getDefinitions()
      ->willReturn($definitions);
  }
  
  /**
   * Tests the getBaseFieldDefinitions() method.
   *
   * @covers ::getBaseFieldDefinitions
   * @covers ::buildBaseFieldDefinitions
   */
  public function testGetBaseFieldDefinitions() : void {
    $field_definition = $this->setUpEntityWithFieldDefinition();
    $expected = [
      'id' => $field_definition,
    ];
    $this->assertSame($expected, $this->entityFieldManager
      ->getBaseFieldDefinitions('test_entity_type'));
  }
  
  /**
   * Tests the getFieldDefinitions() method.
   *
   * @covers ::getFieldDefinitions
   * @covers ::buildBundleFieldDefinitions
   */
  public function testGetFieldDefinitions() : void {
    $field_definition = $this->setUpEntityWithFieldDefinition();
    $bundle_field_definition = $this->prophesize()
      ->willImplement(FieldDefinitionInterface::class)
      ->willImplement(FieldStorageDefinitionInterface::class);
    // Define bundle fields to be stored on the default Entity class.
    $bundle_fields = [
      'the_entity_id' => [
        'test_entity_bundle' => [
          'id_bundle' => $bundle_field_definition->reveal(),
        ],
        'test_entity_bundle_class' => [
          'some_extra_field' => $bundle_field_definition->reveal(),
        ],
      ],
    ];
    // Define bundle fields to be stored on the bundle class.
    $bundle_class_fields = [
      'the_entity_id' => [
        'test_entity_bundle_class' => [
          'id_bundle_class' => $bundle_field_definition->reveal(),
        ],
      ],
    ];
    EntityTypeManagerTestEntity::$bundleFieldDefinitions = $bundle_fields;
    EntityTypeManagerTestEntityBundle::$bundleClassFieldDefinitions = $bundle_class_fields;
    // Test that only base fields are retrieved.
    $expected = [
      'id' => $field_definition,
    ];
    $this->assertSame($expected, $this->entityFieldManager
      ->getFieldDefinitions('test_entity_type', 'some_other_bundle'));
    // Test that base fields and bundle fields from the default entity class are
    // retrieved.
    $expected = [
      'id' => $field_definition,
      'id_bundle' => $bundle_fields['the_entity_id']['test_entity_bundle']['id_bundle'],
    ];
    $this->assertSame($expected, $this->entityFieldManager
      ->getFieldDefinitions('test_entity_type', 'test_entity_bundle'));
    // Test that base fields and bundle fields from the bundle class and
    // entity class are retrieved
    $expected = [
      'id' => $field_definition,
      'some_extra_field' => $bundle_fields['the_entity_id']['test_entity_bundle_class']['some_extra_field'],
      'id_bundle_class' => $bundle_class_fields['the_entity_id']['test_entity_bundle_class']['id_bundle_class'],
    ];
    $this->assertSame($expected, $this->entityFieldManager
      ->getFieldDefinitions('test_entity_type', 'test_entity_bundle_class'));
  }
  
  /**
   * Tests the getFieldStorageDefinitions() method.
   *
   * @covers ::getFieldStorageDefinitions
   * @covers ::buildFieldStorageDefinitions
   */
  public function testGetFieldStorageDefinitions() : void {
    $field_definition = $this->setUpEntityWithFieldDefinition(TRUE);
    $field_storage_definition = $this->prophesize(FieldStorageDefinitionInterface::class);
    $field_storage_definition->getName()
      ->willReturn('field_storage');
    $base_field_definition = $this->prophesize(BaseFieldDefinition::class);
    $base_field_definition->setProvider('example_module')
      ->shouldBeCalled();
    $base_field_definition->setName('base_field')
      ->shouldBeCalled();
    $base_field_definition->setTargetEntityTypeId('test_entity_type')
      ->shouldBeCalled();
    $definitions = [
      'base_field' => $base_field_definition->reveal(),
      'field_storage' => $field_storage_definition->reveal(),
    ];
    $this->moduleHandler
      ->invokeAllWith('entity_base_field_info', Argument::any());
    $this->moduleHandler
      ->invokeAllWith('entity_field_storage_info', Argument::any())
      ->will(function ($arguments) use ($definitions) {
      [
        $hook,
        $callback,
      ] = $arguments;
      $callback(function () use ($definitions) {
        return $definitions;
      }, 'example_module');
    });
    $this->moduleHandler
      ->alter('entity_field_storage_info', $definitions, $this->entityType)
      ->willReturn(NULL);
    $expected = [
      'id' => $field_definition,
      'base_field' => $base_field_definition->reveal(),
      'field_storage' => $field_storage_definition->reveal(),
    ];
    $this->assertSame($expected, $this->entityFieldManager
      ->getFieldStorageDefinitions('test_entity_type'));
  }
  
  /**
   * Tests the getBaseFieldDefinitions() method with a translatable entity type.
   *
   * @covers ::getBaseFieldDefinitions
   * @covers ::buildBaseFieldDefinitions
   *
   * @dataProvider providerTestGetBaseFieldDefinitionsTranslatableEntityTypeDefaultLangcode
   */
  public function testGetBaseFieldDefinitionsTranslatableEntityTypeDefaultLangcode($default_langcode_key) : void {
    $this->setUpEntityWithFieldDefinition(FALSE, 'id', [
      'langcode' => 'langcode',
      'default_langcode' => $default_langcode_key,
    ]);
    $field_definition = $this->prophesize()
      ->willImplement(FieldDefinitionInterface::class)
      ->willImplement(FieldStorageDefinitionInterface::class);
    $field_definition->isTranslatable()
      ->willReturn(TRUE);
    $entity_class = EntityTypeManagerTestEntity::class;
    $entity_class::$baseFieldDefinitions += [
      'langcode' => $field_definition,
    ];
    $this->entityType
      ->isTranslatable()
      ->willReturn(TRUE);
    $definitions = $this->entityFieldManager
      ->getBaseFieldDefinitions('test_entity_type');
    $this->assertTrue(isset($definitions[$default_langcode_key]));
  }
  
  /**
   * Provides test data for testGetBaseFieldDefinitionsTranslatableEntityTypeDefaultLangcode().
   *
   * @return array
   *   Test data.
   */
  public static function providerTestGetBaseFieldDefinitionsTranslatableEntityTypeDefaultLangcode() {
    return [
      [
        'default_langcode',
      ],
      [
        'custom_default_langcode_key',
      ],
    ];
  }
  
  /**
   * Tests the getBaseFieldDefinitions() method with a translatable entity type.
   *
   * @covers ::getBaseFieldDefinitions
   * @covers ::buildBaseFieldDefinitions
   *
   * @dataProvider providerTestGetBaseFieldDefinitionsTranslatableEntityTypeLangcode
   */
  public function testGetBaseFieldDefinitionsTranslatableEntityTypeLangcode($provide_key, $provide_field, $translatable) : void {
    $keys = $provide_key ? [
      'langcode' => 'langcode',
    ] : [];
    $this->setUpEntityWithFieldDefinition(FALSE, 'id', $keys);
    if ($provide_field) {
      $field_definition = $this->prophesize()
        ->willImplement(FieldDefinitionInterface::class)
        ->willImplement(FieldStorageDefinitionInterface::class);
      $field_definition->isTranslatable()
        ->willReturn($translatable);
      if (!$translatable) {
        $field_definition->setTranslatable(!$translatable)
          ->shouldBeCalled();
      }
      $entity_class = EntityTypeManagerTestEntity::class;
      $entity_class::$baseFieldDefinitions += [
        'langcode' => $field_definition->reveal(),
      ];
    }
    $this->entityType
      ->isTranslatable()
      ->willReturn(TRUE);
    $this->entityType
      ->getLabel()
      ->willReturn('Test');
    $this->expectException(\LogicException::class);
    $this->expectExceptionMessage('The Test entity type cannot be translatable as it does not define a translatable "langcode" field.');
    $this->entityFieldManager
      ->getBaseFieldDefinitions('test_entity_type');
  }
  
  /**
   * Provides test data for testGetBaseFieldDefinitionsTranslatableEntityTypeLangcode().
   *
   * @return array
   *   Test data.
   */
  public static function providerTestGetBaseFieldDefinitionsTranslatableEntityTypeLangcode() {
    return [
      [
        FALSE,
        TRUE,
        TRUE,
      ],
      [
        TRUE,
        FALSE,
        TRUE,
      ],
      [
        TRUE,
        TRUE,
        FALSE,
      ],
    ];
  }
  
  /**
   * Tests the getBaseFieldDefinitions() method with caching.
   *
   * @covers ::getBaseFieldDefinitions
   */
  public function testGetBaseFieldDefinitionsWithCaching() : void {
    $field_definition = $this->setUpEntityWithFieldDefinition();
    $expected = [
      'id' => $field_definition,
    ];
    $cacheBackend = $this->cacheBackend;
    $this->cacheBackend
      ->get('entity_base_field_definitions:test_entity_type:en')
      ->willReturn(FALSE)
      ->shouldBeCalled();
    $this->cacheBackend
      ->set('entity_base_field_definitions:test_entity_type:en', Argument::any(), Cache::PERMANENT, [
      'entity_types',
      'entity_field_info',
    ])
      ->will(function (array $args) use ($cacheBackend) {
      $data = (object) [
        'data' => $args[1],
      ];
      $cacheBackend->get('entity_base_field_definitions:test_entity_type:en')
        ->willReturn($data)
        ->shouldBeCalled();
    })
      ->shouldBeCalled();
    $this->assertSame($expected, $this->entityFieldManager
      ->getBaseFieldDefinitions('test_entity_type'));
    $this->entityFieldManager
      ->testClearEntityFieldInfo();
    $this->assertSame($expected, $this->entityFieldManager
      ->getBaseFieldDefinitions('test_entity_type'));
  }
  
  /**
   * Tests the getFieldDefinitions() method with caching.
   *
   * @covers ::getFieldDefinitions
   */
  public function testGetFieldDefinitionsWithCaching() : void {
    $field_definition = $this->setUpEntityWithFieldDefinition(FALSE, 'id');
    $expected = [
      'id' => $field_definition,
    ];
    $cacheBackend = $this->cacheBackend;
    $this->cacheBackend
      ->get('entity_base_field_definitions:test_entity_type:en')
      ->willReturn((object) [
      'data' => $expected,
    ])
      ->shouldBeCalledTimes(2);
    $this->cacheBackend
      ->get('entity_bundle_field_definitions:test_entity_type:test_bundle:en')
      ->willReturn(FALSE)
      ->shouldBeCalledTimes(1);
    $this->cacheBackend
      ->set('entity_bundle_field_definitions:test_entity_type:test_bundle:en', Argument::any(), Cache::PERMANENT, [
      'entity_types',
      'entity_field_info',
    ])
      ->will(function (array $args) use ($cacheBackend) {
      $data = (object) [
        'data' => $args[1],
      ];
      $cacheBackend->get('entity_bundle_field_definitions:test_entity_type:test_bundle:en')
        ->willReturn($data)
        ->shouldBeCalled();
    })
      ->shouldBeCalled();
    $this->assertSame($expected, $this->entityFieldManager
      ->getFieldDefinitions('test_entity_type', 'test_bundle'));
    $this->entityFieldManager
      ->testClearEntityFieldInfo();
    $this->assertSame($expected, $this->entityFieldManager
      ->getFieldDefinitions('test_entity_type', 'test_bundle'));
  }
  
  /**
   * Tests the getFieldStorageDefinitions() method with caching.
   *
   * @covers ::getFieldStorageDefinitions
   */
  public function testGetFieldStorageDefinitionsWithCaching() : void {
    $field_definition = $this->setUpEntityWithFieldDefinition(TRUE, 'id');
    $field_storage_definition = $this->prophesize(FieldStorageDefinitionInterface::class);
    $field_storage_definition->getName()
      ->willReturn('field_storage');
    $definitions = [
      'field_storage' => $field_storage_definition->reveal(),
    ];
    $this->moduleHandler
      ->invokeAllWith('entity_field_storage_info', Argument::any())
      ->will(function ($arguments) use ($definitions) {
      [
        $hook,
        $callback,
      ] = $arguments;
      $callback(function () use ($definitions) {
        return $definitions;
      }, 'example_module');
    });
    $this->moduleHandler
      ->alter('entity_field_storage_info', $definitions, $this->entityType)
      ->willReturn(NULL);
    $expected = [
      'id' => $field_definition,
      'field_storage' => $field_storage_definition->reveal(),
    ];
    $cacheBackend = $this->cacheBackend;
    $this->cacheBackend
      ->get('entity_base_field_definitions:test_entity_type:en')
      ->willReturn((object) [
      'data' => [
        'id' => $expected['id'],
      ],
    ])
      ->shouldBeCalledTimes(2);
    $this->cacheBackend
      ->get('entity_field_storage_definitions:test_entity_type:en')
      ->willReturn(FALSE);
    $this->cacheBackend
      ->set('entity_field_storage_definitions:test_entity_type:en', Argument::any(), Cache::PERMANENT, [
      'entity_types',
      'entity_field_info',
    ])
      ->will(function () use ($expected, $cacheBackend) {
      $cacheBackend->get('entity_field_storage_definitions:test_entity_type:en')
        ->willReturn((object) [
        'data' => $expected,
      ])
        ->shouldBeCalled();
    })
      ->shouldBeCalled();
    $this->assertSame($expected, $this->entityFieldManager
      ->getFieldStorageDefinitions('test_entity_type'));
    $this->entityFieldManager
      ->testClearEntityFieldInfo();
    $this->assertSame($expected, $this->entityFieldManager
      ->getFieldStorageDefinitions('test_entity_type'));
  }
  
  /**
   * Tests the getBaseFieldDefinitions() method with an invalid definition.
   *
   * @covers ::getBaseFieldDefinitions
   * @covers ::buildBaseFieldDefinitions
   */
  public function testGetBaseFieldDefinitionsInvalidDefinition() : void {
    $this->setUpEntityWithFieldDefinition(FALSE, 'langcode', [
      'langcode' => 'langcode',
    ]);
    $this->entityType
      ->isTranslatable()
      ->willReturn(TRUE);
    $this->entityType
      ->getLabel()
      ->willReturn('the_label');
    $this->expectException(\LogicException::class);
    $this->entityFieldManager
      ->getBaseFieldDefinitions('test_entity_type');
  }
  
  /**
   * Tests that getFieldDefinitions() method sets the 'provider' definition key.
   *
   * @covers ::getFieldDefinitions
   * @covers ::buildBundleFieldDefinitions
   */
  public function testGetFieldDefinitionsProvider() : void {
    $this->setUpEntityWithFieldDefinition(TRUE);
    $module = 'entity_field_manager_test_module';
    // @todo Mock FieldDefinitionInterface once it exposes a proper provider
    //   setter. See https://www.drupal.org/node/2346329.
    $field_definition = $this->prophesize(BaseFieldDefinition::class);
    // We expect two calls as the field definition will be returned from both
    // base and bundle entity field info hook implementations.
    $field_definition->getProvider()
      ->shouldBeCalled();
    $field_definition->setProvider($module)
      ->shouldBeCalledTimes(2);
    $field_definition->setName(0)
      ->shouldBeCalledTimes(2);
    $field_definition->setTargetEntityTypeId('test_entity_type')
      ->shouldBeCalled();
    $field_definition->setTargetBundle(NULL)
      ->shouldBeCalled();
    $field_definition->setTargetBundle('test_bundle')
      ->shouldBeCalled();
    $this->moduleHandler
      ->invokeAllWith(Argument::type('string'), Argument::any())
      ->will(function ($arguments) use ($field_definition, $module) {
      [
        $hook,
        $callback,
      ] = $arguments;
      $callback(function () use ($field_definition) {
        return [
          $field_definition->reveal(),
        ];
      }, $module);
    });
    $this->entityFieldManager
      ->getFieldDefinitions('test_entity_type', 'test_bundle');
  }
  
  /**
   * Prepares an entity that defines a field definition.
   *
   * @param bool $custom_invoke_all
   *   (optional) Whether the test will set up its own
   *   ModuleHandlerInterface::invokeAll() implementation. Defaults to FALSE.
   * @param string $field_definition_id
   *   (optional) The ID to use for the field definition. Defaults to 'id'.
   * @param array $entity_keys
   *   (optional) An array of entity keys for the mocked entity type. Defaults
   *   to an empty array.
   *
   * @return \Drupal\Core\Field\BaseFieldDefinition|\Prophecy\Prophecy\ProphecyInterface
   *   A field definition object.
   */
  protected function setUpEntityWithFieldDefinition($custom_invoke_all = FALSE, $field_definition_id = 'id', $entity_keys = []) {
    $field_type_manager = $this->prophesize(FieldTypePluginManagerInterface::class);
    $field_type_manager->getDefaultStorageSettings('boolean')
      ->willReturn([]);
    $field_type_manager->getDefaultFieldSettings('boolean')
      ->willReturn([]);
    $this->container
      ->get('plugin.manager.field.field_type')
      ->willReturn($field_type_manager->reveal());
    $string_translation = $this->prophesize(TranslationInterface::class);
    $this->container
      ->get('string_translation')
      ->willReturn($string_translation->reveal());
    $entity_class = EntityTypeManagerTestEntity::class;
    $field_definition = $this->prophesize()
      ->willImplement(FieldDefinitionInterface::class)
      ->willImplement(FieldStorageDefinitionInterface::class);
    $entity_class::$baseFieldDefinitions = [
      $field_definition_id => $field_definition->reveal(),
    ];
    $entity_class::$bundleFieldDefinitions = [];
    if (!$custom_invoke_all) {
      $this->moduleHandler
        ->invokeAllWith(Argument::cetera(), Argument::cetera());
    }
    // Mock the base field definition override.
    $override_entity_type = $this->prophesize(EntityTypeInterface::class);
    $this->entityType = $this->prophesize(EntityTypeInterface::class);
    $this->setUpEntityTypeDefinitions([
      'test_entity_type' => $this->entityType,
      'base_field_override' => $override_entity_type,
    ]);
    $storage = $this->prophesize(EntityStorageInterface::class);
    $storage->loadMultiple(Argument::type('array'))
      ->willReturn([]);
    // By default, make the storage entity class lookup return the
    // EntityTypeManagerTestEntity class
    $storage->getEntityClass(NULL)
      ->willReturn(EntityTypeManagerTestEntity::class);
    $storage->getEntityClass(Argument::type('string'))
      ->willReturn(EntityTypeManagerTestEntity::class);
    // When using the "test_entity_bundle_class" bundle, return the
    // EntityTypeManagerTestEntityBundle class
    $storage->getEntityClass('test_entity_bundle_class')
      ->willReturn(EntityTypeManagerTestEntityBundle::class);
    $this->entityTypeManager
      ->getStorage('test_entity_type')
      ->willReturn($storage->reveal());
    $this->entityTypeManager
      ->getStorage('base_field_override')
      ->willReturn($storage->reveal());
    $this->entityType
      ->getClass()
      ->willReturn($entity_class);
    $this->entityType
      ->getKeys()
      ->willReturn($entity_keys + [
      'default_langcode' => 'default_langcode',
    ]);
    $this->entityType
      ->entityClassImplements(FieldableEntityInterface::class)
      ->willReturn(TRUE);
    $this->entityType
      ->isTranslatable()
      ->willReturn(FALSE);
    $this->entityType
      ->isRevisionable()
      ->willReturn(FALSE);
    $this->entityType
      ->getProvider()
      ->willReturn('the_provider');
    $this->entityType
      ->id()
      ->willReturn('the_entity_id');
    return $field_definition->reveal();
  }
  
  /**
   * Tests the clearCachedFieldDefinitions() method.
   *
   * @covers ::clearCachedFieldDefinitions
   */
  public function testClearCachedFieldDefinitions() : void {
    $this->setUpEntityTypeDefinitions();
    $this->cacheTagsInvalidator
      ->invalidateTags([
      'entity_field_info',
    ])
      ->shouldBeCalled();
    $this->container
      ->get('cache_tags.invalidator')
      ->willReturn($this->cacheTagsInvalidator
      ->reveal())
      ->shouldBeCalled();
    $this->typedDataManager
      ->clearCachedDefinitions()
      ->shouldBeCalled();
    $this->entityFieldManager
      ->clearCachedFieldDefinitions();
  }
  
  /**
   * @covers ::getExtraFields
   */
  public function testGetExtraFields() : void {
    $this->setUpEntityTypeDefinitions();
    $entity_type_id = $this->randomMachineName();
    $bundle = $this->randomMachineName();
    $language_code = 'en';
    $hook_bundle_extra_fields = [
      $entity_type_id => [
        $bundle => [
          'form' => [
            'foo_extra_field' => [
              'label' => 'Foo',
            ],
          ],
        ],
      ],
    ];
    $processed_hook_bundle_extra_fields = $hook_bundle_extra_fields;
    $processed_hook_bundle_extra_fields[$entity_type_id][$bundle] += [
      'display' => [],
    ];
    $cache_id = 'entity_extra_field_info:' . $language_code;
    $language = new Language([
      'id' => $language_code,
    ]);
    $this->languageManager
      ->getCurrentLanguage()
      ->willReturn($language)
      ->shouldBeCalledTimes(1);
    $this->cacheBackend
      ->get($cache_id)
      ->shouldBeCalled();
    $this->moduleHandler
      ->invokeAll('entity_extra_field_info')
      ->willReturn($hook_bundle_extra_fields);
    $this->moduleHandler
      ->alter('entity_extra_field_info', $hook_bundle_extra_fields)
      ->shouldBeCalled();
    $this->cacheBackend
      ->set($cache_id, $processed_hook_bundle_extra_fields, Cache::PERMANENT, [
      'entity_field_info',
    ])
      ->shouldBeCalled();
    $this->assertSame($processed_hook_bundle_extra_fields[$entity_type_id][$bundle], $this->entityFieldManager
      ->getExtraFields($entity_type_id, $bundle));
  }
  
  /**
   * @covers ::getFieldMap
   */
  public function testGetFieldMap() : void {
    $this->entityTypeBundleInfo
      ->getBundleInfo('test_entity_type')
      ->willReturn([])
      ->shouldBeCalled();
    // Set up a content entity type.
    $entity_type = $this->prophesize(ContentEntityTypeInterface::class);
    $entity_class = EntityTypeManagerTestEntity::class;
    // Define an ID field definition as a base field.
    $id_definition = $this->prophesize(FieldDefinitionInterface::class);
    $id_definition->getType()
      ->willReturn('integer');
    $base_field_definitions = [
      'id' => $id_definition->reveal(),
    ];
    $entity_class::$baseFieldDefinitions = $base_field_definitions;
    // Set up the stored bundle field map.
    $key_value_store = $this->prophesize(KeyValueStoreInterface::class);
    $this->keyValueFactory
      ->get('entity.definitions.bundle_field_map')
      ->willReturn($key_value_store->reveal());
    $key_value_store->getAll()
      ->willReturn([
      'test_entity_type' => [
        'by_bundle' => [
          'type' => 'string',
          'bundles' => [
            'second_bundle' => 'second_bundle',
          ],
        ],
      ],
    ]);
    // Set up a non-content entity type.
    $non_content_entity_type = $this->prophesize(EntityTypeInterface::class);
    // Mock the base field definition override.
    $override_entity_type = $this->prophesize(EntityTypeInterface::class);
    $this->setUpEntityTypeDefinitions([
      'test_entity_type' => $entity_type,
      'non_fieldable' => $non_content_entity_type,
      'base_field_override' => $override_entity_type,
    ]);
    $entity_type->getClass()
      ->willReturn($entity_class);
    $entity_type->getKeys()
      ->willReturn([
      'default_langcode' => 'default_langcode',
    ]);
    $entity_type->entityClassImplements(FieldableEntityInterface::class)
      ->willReturn(TRUE);
    $entity_type->isTranslatable()
      ->shouldBeCalled();
    $entity_type->isRevisionable()
      ->shouldBeCalled();
    $entity_type->getProvider()
      ->shouldBeCalled();
    $non_content_entity_type->entityClassImplements(FieldableEntityInterface::class)
      ->willReturn(FALSE);
    $override_entity_type->entityClassImplements(FieldableEntityInterface::class)
      ->willReturn(FALSE);
    // Set up the entity type bundle info to return two bundles for the
    // fieldable entity type.
    $this->entityTypeBundleInfo
      ->getBundleInfo('test_entity_type')
      ->willReturn([
      'first_bundle' => 'first_bundle',
      'second_bundle' => 'second_bundle',
    ])
      ->shouldBeCalled();
    $this->moduleHandler
      ->invokeAllWith('entity_base_field_info', Argument::any());
    $expected = [
      'test_entity_type' => [
        'id' => [
          'type' => 'integer',
          'bundles' => [
            'first_bundle' => 'first_bundle',
            'second_bundle' => 'second_bundle',
          ],
        ],
        'by_bundle' => [
          'type' => 'string',
          'bundles' => [
            'second_bundle' => 'second_bundle',
          ],
        ],
      ],
    ];
    $this->assertEquals($expected, $this->entityFieldManager
      ->getFieldMap());
  }
  
  /**
   * @covers ::getFieldMap
   */
  public function testGetFieldMapFromCache() : void {
    $expected = [
      'test_entity_type' => [
        'id' => [
          'type' => 'integer',
          'bundles' => [
            'first_bundle' => 'first_bundle',
            'second_bundle' => 'second_bundle',
          ],
        ],
        'by_bundle' => [
          'type' => 'string',
          'bundles' => [
            'second_bundle' => 'second_bundle',
          ],
        ],
      ],
    ];
    $this->setUpEntityTypeDefinitions();
    $this->cacheBackend
      ->get('entity_field_map')
      ->willReturn((object) [
      'data' => $expected,
    ]);
    // Call the field map twice to make sure the static cache works.
    $this->assertEquals($expected, $this->entityFieldManager
      ->getFieldMap());
    $this->assertEquals($expected, $this->entityFieldManager
      ->getFieldMap());
  }
  
  /**
   * @covers ::getFieldMapByFieldType
   */
  public function testGetFieldMapByFieldType() : void {
    // Set up a content entity type.
    $entity_type = $this->prophesize(ContentEntityTypeInterface::class);
    $entity_class = EntityTypeManagerTestEntity::class;
    // Set up the entity type bundle info to return two bundles for the
    // fieldable entity type.
    $this->entityTypeBundleInfo
      ->getBundleInfo('test_entity_type')
      ->willReturn([
      'first_bundle' => 'first_bundle',
      'second_bundle' => 'second_bundle',
    ])
      ->shouldBeCalled();
    $this->moduleHandler
      ->invokeAllWith('entity_base_field_info', Argument::any())
      ->shouldBeCalled();
    // Define an ID field definition as a base field.
    $id_definition = $this->prophesize(FieldDefinitionInterface::class);
    $id_definition->getType()
      ->willReturn('integer')
      ->shouldBeCalled();
    $base_field_definitions = [
      'id' => $id_definition->reveal(),
    ];
    $entity_class::$baseFieldDefinitions = $base_field_definitions;
    // Set up the stored bundle field map.
    $key_value_store = $this->prophesize(KeyValueStoreInterface::class);
    $this->keyValueFactory
      ->get('entity.definitions.bundle_field_map')
      ->willReturn($key_value_store->reveal())
      ->shouldBeCalled();
    $key_value_store->getAll()
      ->willReturn([
      'test_entity_type' => [
        'by_bundle' => [
          'type' => 'string',
          'bundles' => [
            'second_bundle' => 'second_bundle',
          ],
        ],
      ],
    ])
      ->shouldBeCalled();
    // Mock the base field definition override.
    $override_entity_type = $this->prophesize(EntityTypeInterface::class);
    $this->setUpEntityTypeDefinitions([
      'test_entity_type' => $entity_type,
      'base_field_override' => $override_entity_type,
    ]);
    $entity_type->getClass()
      ->willReturn($entity_class)
      ->shouldBeCalled();
    $entity_type->getKeys()
      ->willReturn([
      'default_langcode' => 'default_langcode',
    ])
      ->shouldBeCalled();
    $entity_type->entityClassImplements(FieldableEntityInterface::class)
      ->willReturn(TRUE)
      ->shouldBeCalled();
    $entity_type->isTranslatable()
      ->shouldBeCalled();
    $entity_type->isRevisionable()
      ->shouldBeCalled();
    $entity_type->getProvider()
      ->shouldBeCalled();
    $override_entity_type->entityClassImplements(FieldableEntityInterface::class)
      ->willReturn(FALSE)
      ->shouldBeCalled();
    $integerFields = $this->entityFieldManager
      ->getFieldMapByFieldType('integer');
    $this->assertCount(1, $integerFields['test_entity_type']);
    $this->assertArrayNotHasKey('non_fieldable', $integerFields);
    $this->assertArrayHasKey('id', $integerFields['test_entity_type']);
    $this->assertArrayNotHasKey('by_bundle', $integerFields['test_entity_type']);
    $stringFields = $this->entityFieldManager
      ->getFieldMapByFieldType('string');
    $this->assertCount(1, $stringFields['test_entity_type']);
    $this->assertArrayNotHasKey('non_fieldable', $stringFields);
    $this->assertArrayHasKey('by_bundle', $stringFields['test_entity_type']);
    $this->assertArrayNotHasKey('id', $stringFields['test_entity_type']);
  }

}

Members

Title Sort descending Deprecated Modifiers Object type Summary Overriden Title Overrides
EntityFieldManagerTest::$cacheBackend protected property The cache backend to use.
EntityFieldManagerTest::$cacheTagsInvalidator protected property The cache tags invalidator.
EntityFieldManagerTest::$container protected property The dependency injection container.
EntityFieldManagerTest::$entityDisplayRepository protected property The entity display repository.
EntityFieldManagerTest::$entityFieldManager protected property The entity field manager under test.
EntityFieldManagerTest::$entityLastInstalledSchemaRepository protected property The entity last installed schema repository.
EntityFieldManagerTest::$entityType protected property The entity type definition.
EntityFieldManagerTest::$entityTypeBundleInfo protected property The entity type bundle info.
EntityFieldManagerTest::$entityTypeManager protected property The entity type manager.
EntityFieldManagerTest::$entityTypeRepository protected property The entity type repository.
EntityFieldManagerTest::$eventDispatcher protected property The event dispatcher.
EntityFieldManagerTest::$keyValueFactory protected property The keyvalue factory.
EntityFieldManagerTest::$languageManager protected property The language manager.
EntityFieldManagerTest::$moduleHandler protected property The module handler.
EntityFieldManagerTest::$typedDataManager protected property The typed data manager.
EntityFieldManagerTest::providerTestGetBaseFieldDefinitionsTranslatableEntityTypeDefaultLangcode public static function Provides test data for testGetBaseFieldDefinitionsTranslatableEntityTypeDefaultLangcode().
EntityFieldManagerTest::providerTestGetBaseFieldDefinitionsTranslatableEntityTypeLangcode public static function Provides test data for testGetBaseFieldDefinitionsTranslatableEntityTypeLangcode().
EntityFieldManagerTest::setUp protected function Overrides UnitTestCase::setUp
EntityFieldManagerTest::setUpEntityTypeDefinitions protected function Sets up the entity type manager to be tested.
EntityFieldManagerTest::setUpEntityWithFieldDefinition protected function Prepares an entity that defines a field definition.
EntityFieldManagerTest::testClearCachedFieldDefinitions public function Tests the clearCachedFieldDefinitions() method.
EntityFieldManagerTest::testGetBaseFieldDefinitions public function Tests the getBaseFieldDefinitions() method.
EntityFieldManagerTest::testGetBaseFieldDefinitionsInvalidDefinition public function Tests the getBaseFieldDefinitions() method with an invalid definition.
EntityFieldManagerTest::testGetBaseFieldDefinitionsTranslatableEntityTypeDefaultLangcode public function Tests the getBaseFieldDefinitions() method with a translatable entity type.
EntityFieldManagerTest::testGetBaseFieldDefinitionsTranslatableEntityTypeLangcode public function Tests the getBaseFieldDefinitions() method with a translatable entity type.
EntityFieldManagerTest::testGetBaseFieldDefinitionsWithCaching public function Tests the getBaseFieldDefinitions() method with caching.
EntityFieldManagerTest::testGetExtraFields public function @covers ::getExtraFields[[api-linebreak]]
EntityFieldManagerTest::testGetFieldDefinitions public function Tests the getFieldDefinitions() method.
EntityFieldManagerTest::testGetFieldDefinitionsProvider public function Tests that getFieldDefinitions() method sets the 'provider' definition key.
EntityFieldManagerTest::testGetFieldDefinitionsWithCaching public function Tests the getFieldDefinitions() method with caching.
EntityFieldManagerTest::testGetFieldMap public function @covers ::getFieldMap[[api-linebreak]]
EntityFieldManagerTest::testGetFieldMapByFieldType public function @covers ::getFieldMapByFieldType[[api-linebreak]]
EntityFieldManagerTest::testGetFieldMapFromCache public function @covers ::getFieldMap[[api-linebreak]]
EntityFieldManagerTest::testGetFieldStorageDefinitions public function Tests the getFieldStorageDefinitions() method.
EntityFieldManagerTest::testGetFieldStorageDefinitionsWithCaching public function Tests the getFieldStorageDefinitions() method with caching.
PhpUnitWarnings::$deprecationWarnings private static property Deprecation warnings from PHPUnit to raise with @trigger_error().
PhpUnitWarnings::addWarning public function Converts PHPUnit deprecation warnings to E_USER_DEPRECATED.
RandomGeneratorTrait::getRandomGenerator protected function Gets the random generator for the utility methods.
RandomGeneratorTrait::randomMachineName protected function Generates a unique random string containing letters and numbers.
RandomGeneratorTrait::randomObject public function Generates a random PHP object.
RandomGeneratorTrait::randomString public function Generates a pseudo-random string of ASCII characters of codes 32 to 126.
RandomGeneratorTrait::randomStringValidate Deprecated public function Callback for random string validation.
UnitTestCase::$root protected property The app root. 1
UnitTestCase::getClassResolverStub protected function Returns a stub class resolver.
UnitTestCase::getConfigFactoryStub public function Returns a stub config factory that behaves according to the passed array.
UnitTestCase::getConfigStorageStub public function Returns a stub config storage that returns the supplied configuration.
UnitTestCase::getContainerWithCacheTagsInvalidator protected function Sets up a container with a cache tags invalidator.
UnitTestCase::getStringTranslationStub public function Returns a stub translation manager that just returns the passed string.
UnitTestCase::setUpBeforeClass public static function
UnitTestCase::__get public function

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.