3 namespace Drupal\Tests\Core\Field;
5 use Drupal\Component\Plugin\Exception\PluginNotFoundException;
6 use Drupal\Core\Cache\CacheBackendInterface;
7 use Drupal\Core\Entity\DynamicallyFieldableEntityStorageInterface;
8 use Drupal\Core\Entity\EntityFieldManagerInterface;
9 use Drupal\Core\Entity\EntityInterface;
10 use Drupal\Core\Entity\EntityTypeInterface;
11 use Drupal\Core\Entity\EntityTypeManagerInterface;
12 use Drupal\Core\Field\FieldDefinitionInterface;
13 use Drupal\Core\Field\FieldDefinitionListener;
14 use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
15 use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
16 use Drupal\Tests\UnitTestCase;
17 use Prophecy\Argument;
20 * @coversDefaultClass \Drupal\Core\Field\FieldDefinitionListener
23 class FieldDefinitionListenerTest extends UnitTestCase {
26 * The key-value factory.
28 * @var \Drupal\Core\KeyValueStore\KeyValueFactoryInterface|\Prophecy\Prophecy\ProphecyInterface
30 protected $keyValueFactory;
33 * The entity type manager.
35 * @var \Drupal\Core\Entity\EntityTypeManagerInterface|\Prophecy\Prophecy\ProphecyInterface
37 protected $entityTypeManager;
40 * The entity field manager.
42 * @var \Drupal\Core\Entity\EntityFieldManagerInterface|\Prophecy\Prophecy\ProphecyInterface
44 protected $entityFieldManager;
49 * @var \Drupal\Core\Cache\CacheBackendInterface|\Prophecy\Prophecy\ProphecyInterface
51 protected $cacheBackend;
54 * The field definition listener under test.
56 * @var \Drupal\Core\Field\FieldDefinitionListener
58 protected $fieldDefinitionListener;
63 protected function setUp() {
66 $this->keyValueFactory = $this->prophesize(KeyValueFactoryInterface::class);
67 $this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class);
68 $this->entityFieldManager = $this->prophesize(EntityFieldManagerInterface::class);
69 $this->cacheBackend = $this->prophesize(CacheBackendInterface::class);
71 $this->fieldDefinitionListener = new FieldDefinitionListener($this->entityTypeManager->reveal(), $this->entityFieldManager->reveal(), $this->keyValueFactory->reveal(), $this->cacheBackend->reveal());
75 * Sets up the entity manager to be tested.
77 * @param \Drupal\Core\Entity\EntityTypeInterface[]|\Prophecy\Prophecy\ProphecyInterface[] $definitions
78 * (optional) An array of entity type definitions.
80 protected function setUpEntityManager($definitions = []) {
81 $class = $this->getMockClass(EntityInterface::class);
82 foreach ($definitions as $key => $entity_type) {
83 // \Drupal\Core\Entity\EntityTypeInterface::getLinkTemplates() is called
84 // by \Drupal\Core\Entity\EntityManager::processDefinition() so it must
86 $entity_type->getLinkTemplates()->willReturn([]);
88 // Give the entity type a legitimate class to return.
89 $entity_type->getClass()->willReturn($class);
91 $definitions[$key] = $entity_type->reveal();
94 $this->entityTypeManager->getDefinition(Argument::cetera())
95 ->will(function ($args) use ($definitions) {
96 $entity_type_id = $args[0];
97 $exception_on_invalid = $args[1];
98 if (isset($definitions[$entity_type_id])) {
99 return $definitions[$entity_type_id];
101 elseif (!$exception_on_invalid) {
104 else throw new PluginNotFoundException($entity_type_id);
106 $this->entityTypeManager->getDefinitions()->willReturn($definitions);
110 * @covers ::onFieldDefinitionCreate
112 public function testOnFieldDefinitionCreateNewField() {
113 $field_definition = $this->prophesize(FieldDefinitionInterface::class);
114 $field_definition->getTargetEntityTypeId()->willReturn('test_entity_type');
115 $field_definition->getTargetBundle()->willReturn('test_bundle');
116 $field_definition->getName()->willReturn('test_field');
117 $field_definition->getType()->willReturn('test_type');
119 $storage = $this->prophesize(DynamicallyFieldableEntityStorageInterface::class);
120 $storage->onFieldDefinitionCreate($field_definition->reveal())->shouldBeCalledTimes(1);
121 $this->entityTypeManager->getStorage('test_entity_type')->willReturn($storage->reveal());
123 $entity = $this->prophesize(EntityTypeInterface::class);
124 $this->setUpEntityManager(['test_entity_type' => $entity]);
126 // Set up the stored bundle field map.
127 $key_value_store = $this->prophesize(KeyValueStoreInterface::class);
128 $this->keyValueFactory->get('entity.definitions.bundle_field_map')->willReturn($key_value_store->reveal());
129 $key_value_store->get('test_entity_type')->willReturn([]);
130 $key_value_store->set('test_entity_type', [
132 'type' => 'test_type',
133 'bundles' => ['test_bundle' => 'test_bundle'],
135 ])->shouldBeCalled();
137 $this->fieldDefinitionListener->onFieldDefinitionCreate($field_definition->reveal());
141 * @covers ::onFieldDefinitionCreate
143 public function testOnFieldDefinitionCreateExistingField() {
144 $field_definition = $this->prophesize(FieldDefinitionInterface::class);
145 $field_definition->getTargetEntityTypeId()->willReturn('test_entity_type');
146 $field_definition->getTargetBundle()->willReturn('test_bundle');
147 $field_definition->getName()->willReturn('test_field');
149 $storage = $this->prophesize(DynamicallyFieldableEntityStorageInterface::class);
150 $storage->onFieldDefinitionCreate($field_definition->reveal())->shouldBeCalledTimes(1);
151 $this->entityTypeManager->getStorage('test_entity_type')->willReturn($storage->reveal());
153 $entity = $this->prophesize(EntityTypeInterface::class);
154 $this->setUpEntityManager(['test_entity_type' => $entity]);
156 // Set up the stored bundle field map.
157 $key_value_store = $this->prophesize(KeyValueStoreInterface::class);
158 $this->keyValueFactory->get('entity.definitions.bundle_field_map')->willReturn($key_value_store->reveal());
159 $key_value_store->get('test_entity_type')->willReturn([
161 'type' => 'test_type',
162 'bundles' => ['existing_bundle' => 'existing_bundle'],
165 $key_value_store->set('test_entity_type', [
167 'type' => 'test_type',
168 'bundles' => ['existing_bundle' => 'existing_bundle', 'test_bundle' => 'test_bundle'],
173 $this->fieldDefinitionListener->onFieldDefinitionCreate($field_definition->reveal());
177 * @covers ::onFieldDefinitionUpdate
179 public function testOnFieldDefinitionUpdate() {
180 $field_definition = $this->prophesize(FieldDefinitionInterface::class);
181 $field_definition->getTargetEntityTypeId()->willReturn('test_entity_type');
183 $storage = $this->prophesize(DynamicallyFieldableEntityStorageInterface::class);
184 $storage->onFieldDefinitionUpdate($field_definition->reveal(), $field_definition->reveal())->shouldBeCalledTimes(1);
185 $this->entityTypeManager->getStorage('test_entity_type')->willReturn($storage->reveal());
187 $entity = $this->prophesize(EntityTypeInterface::class);
188 $this->setUpEntityManager(['test_entity_type' => $entity]);
190 $this->fieldDefinitionListener->onFieldDefinitionUpdate($field_definition->reveal(), $field_definition->reveal());
194 * @covers ::onFieldDefinitionDelete
196 public function testOnFieldDefinitionDeleteMultipleBundles() {
197 $field_definition = $this->prophesize(FieldDefinitionInterface::class);
198 $field_definition->getTargetEntityTypeId()->willReturn('test_entity_type');
199 $field_definition->getTargetBundle()->willReturn('test_bundle');
200 $field_definition->getName()->willReturn('test_field');
202 $storage = $this->prophesize(DynamicallyFieldableEntityStorageInterface::class);
203 $storage->onFieldDefinitionDelete($field_definition->reveal())->shouldBeCalledTimes(1);
204 $this->entityTypeManager->getStorage('test_entity_type')->willReturn($storage->reveal());
206 $entity = $this->prophesize(EntityTypeInterface::class);
207 $this->setUpEntityManager(['test_entity_type' => $entity]);
209 // Set up the stored bundle field map.
210 $key_value_store = $this->prophesize(KeyValueStoreInterface::class);
211 $this->keyValueFactory->get('entity.definitions.bundle_field_map')->willReturn($key_value_store->reveal());
212 $key_value_store->get('test_entity_type')->willReturn([
214 'type' => 'test_type',
215 'bundles' => ['test_bundle' => 'test_bundle'],
218 'type' => 'test_type',
219 'bundles' => ['test_bundle' => 'test_bundle'],
222 $key_value_store->set('test_entity_type', [
224 'type' => 'test_type',
225 'bundles' => ['test_bundle' => 'test_bundle'],
230 $this->fieldDefinitionListener->onFieldDefinitionDelete($field_definition->reveal());
235 * @covers ::onFieldDefinitionDelete
237 public function testOnFieldDefinitionDeleteSingleBundles() {
238 $field_definition = $this->prophesize(FieldDefinitionInterface::class);
239 $field_definition->getTargetEntityTypeId()->willReturn('test_entity_type');
240 $field_definition->getTargetBundle()->willReturn('test_bundle');
241 $field_definition->getName()->willReturn('test_field');
243 $storage = $this->prophesize(DynamicallyFieldableEntityStorageInterface::class);
244 $storage->onFieldDefinitionDelete($field_definition->reveal())->shouldBeCalledTimes(1);
245 $this->entityTypeManager->getStorage('test_entity_type')->willReturn($storage->reveal());
247 $entity = $this->prophesize(EntityTypeInterface::class);
248 $this->setUpEntityManager(['test_entity_type' => $entity]);
250 // Set up the stored bundle field map.
251 $key_value_store = $this->prophesize(KeyValueStoreInterface::class);
252 $this->keyValueFactory->get('entity.definitions.bundle_field_map')->willReturn($key_value_store->reveal());
253 $key_value_store->get('test_entity_type')->willReturn([
255 'type' => 'test_type',
256 'bundles' => ['test_bundle' => 'test_bundle', 'second_bundle' => 'second_bundle'],
259 $key_value_store->set('test_entity_type', [
261 'type' => 'test_type',
262 'bundles' => ['second_bundle' => 'second_bundle'],
267 $this->fieldDefinitionListener->onFieldDefinitionDelete($field_definition->reveal());