function BundleClassTest::testBundleClassAttributeDiscovery

Tests bundle class discovery via attributes.

File

core/tests/Drupal/KernelTests/Core/Entity/BundleClassTest.php, line 317

Class

BundleClassTest
Tests entity bundle classes.

Namespace

Drupal\KernelTests\Core\Entity

Code

public function testBundleClassAttributeDiscovery() : void {
  $this->installEntitySchema('entity_test_with_bundle');
  // Confirm bundle entity type classes are not entity type definitions.
  \Drupal::service(ModuleInstallerInterface::class)->install([
    'entity_test_attribute_bundle_class',
  ]);
  $definitions = \Drupal::entityTypeManager()->getDefinitions();
  $this->assertArrayHasKey('entity_test', $definitions);
  $this->assertArrayNotHasKey('entity_test:bundle_class_a', $definitions);
  $this->assertArrayNotHasKey('entity_test:bundle_class_b', $definitions);
  $this->assertArrayNotHasKey('entity_test:subdir_bundle_class', $definitions);
  $this->assertArrayNotHasKey('entity_test_with_bundle:new_bundle', $definitions);
  $storage = \Drupal::entityTypeManager()->getStorage('entity_test');
  $bundle_info_service = \Drupal::service(EntityTypeBundleInfoInterface::class);
  $bundle_info = $bundle_info_service->getAllBundleInfo();
  // Test bundle class info where all properties are overridden by the
  // attribute properties.
  $this->assertSame('Bundle class A label set by attribute', $bundle_info['entity_test']['bundle_class_a']['label']->getUntranslatedString());
  $this->assertFalse($bundle_info['entity_test']['bundle_class_a']['translatable']);
  $entity = $storage->create([
    'type' => 'bundle_class_a',
  ]);
  $this->assertInstanceOf(EntityTestBundleClassOverrideA::class, $entity);
  // Test bundle class info where all only the class is overridden by
  // attribute properties.
  $this->assertSame('Bundle class B', $bundle_info['entity_test']['bundle_class_b']['label']);
  $this->assertTrue($bundle_info['entity_test']['bundle_class_b']['translatable']);
  $entity = $storage->create([
    'type' => 'bundle_class_b',
  ]);
  $this->assertInstanceOf(EntityTestBundleClassOverrideB::class, $entity);
  // Confirm that attribute discovery of bundle classes works in
  // subdirectories of {module}/src/Entity. Attribute discovery of bundle
  // classes directly in the {module}/src/Entity directories are already
  // tested by other methods in this test class.
  $this->assertSame('subdir_bundle_class', $bundle_info['entity_test']['subdir_bundle_class']['label']);
  $this->assertArrayNotHasKey('translatable', $bundle_info['entity_test']['subdir_bundle_class']);
  $entity = $storage->create([
    'type' => 'subdir_bundle_class',
  ]);
  $this->assertInstanceOf(EntityTestSubdirBundleClass::class, $entity);
  // There have been no bundle entities created for entity_test_with_bundle,
  // so there should be no bundle class info for the entity type.
  $this->assertArrayNotHasKey('entity_test_with_bundle', $bundle_info);
  // Confirm bundle classes are not accessible as entity type definitions.
  $bundle_plugin_ids = [
    'entity_test:bundle_class_a',
    'entity_test:bundle_class_b',
    'entity_test:subdir_bundle_class',
    'entity_test_with_bundle:new_bundle',
  ];
  foreach ($bundle_plugin_ids as $id) {
    try {
      $throwable = NULL;
      $bundle_entity_type = \Drupal::entityTypeManager()->getDefinition($id);
      $this->assertNull($bundle_entity_type);
    } catch (\Throwable $throwable) {
    }
    $this->assertInstanceOf(\LogicException::class, $throwable);
    $this->assertSame('Bundle entity types are not supported directly.', $throwable->getMessage());
  }
  // Activate the entity_bundle_info_alter hook implementation in this class
  // to confirm the alter hook can change bundle info provided by attributes.
  $this->alterAttributeBundleInfo = TRUE;
  $bundle_info_service->clearCachedBundles();
  $bundle_info = $bundle_info_service->getAllBundleInfo();
  $this->assertSame('Overridden bundle class to SharedEntityTestBundleClassA', $bundle_info['entity_test']['subdir_bundle_class']['label']);
  $this->assertTrue($bundle_info['entity_test']['subdir_bundle_class']['translatable']);
  $entity = $storage->create([
    'type' => 'subdir_bundle_class',
  ]);
  $this->assertInstanceOf(SharedEntityTestBundleClassA::class, $entity);
  $this->assertSame('Overridden bundle class to SharedEntityTestBundleClassB', $bundle_info['entity_test']['bundle_class_b']['label']);
  $this->assertTrue($bundle_info['entity_test']['bundle_class_b']['translatable']);
  $entity = $storage->create([
    'type' => 'bundle_class_b',
  ]);
  $this->assertInstanceOf(SharedEntityTestBundleClassB::class, $entity);
  // Create the bundle entity for entity_test_with_bundle, and confirm the
  // bundle class defined by attributes is set.
  $entity_test_with_bundle_bundle_type = \Drupal::entityTypeManager()->getDefinition('entity_test_with_bundle')
    ->getBundleEntityType();
  $bundle_entity = \Drupal::entityTypeManager()->getStorage($entity_test_with_bundle_bundle_type)
    ->create([
    'id' => 'new_bundle',
  ]);
  $bundle_entity->save();
  $bundle_info = $bundle_info_service->getAllBundleInfo();
  $this->assertSame('A new bundle for an entity type with a bundle entity type', $bundle_info['entity_test_with_bundle']['new_bundle']['label']->getUntranslatedString());
  $this->assertFalse($bundle_info['entity_test_with_bundle']['new_bundle']['translatable']);
  $entity = \Drupal::entityTypeManager()->getStorage('entity_test_with_bundle')
    ->create([
    'type' => 'new_bundle',
  ]);
  $this->assertInstanceOf(EntityTestWithBundleTypeNewBundle::class, $entity);
}

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