diff -u b/core/lib/Drupal/Core/Entity/EntityDisplayBase.php b/core/lib/Drupal/Core/Entity/EntityDisplayBase.php --- b/core/lib/Drupal/Core/Entity/EntityDisplayBase.php +++ b/core/lib/Drupal/Core/Entity/EntityDisplayBase.php @@ -602,19 +602,18 @@ * @param string $name * The name of the element. * - * @return \Drupal\Core\Entity\DisplayComponentHandlerInterface|false + * @return \Drupal\Core\Entity\DisplayComponentHandlerInterface * The display component handler. */ public function getComponentHandlerByElementName($name) { if (!isset($this->handlers[$name])) { $handlers = $this->handlerManager->getDefinitions(); - $handler = FALSE; foreach (array_keys($handlers) as $type) { $handler = $this->getComponentHandler($type); if ($handler && $handler->hasElement($name)) { break; } - $handler = FALSE; + $handler = NULL; } $this->handlers[$name] = $handler; } diff -u b/core/lib/Drupal/Core/Field/FormatterPluginManager.php b/core/lib/Drupal/Core/Field/FormatterPluginManager.php --- b/core/lib/Drupal/Core/Field/FormatterPluginManager.php +++ b/core/lib/Drupal/Core/Field/FormatterPluginManager.php @@ -128,6 +128,7 @@ $configuration += [ 'field_definition' => $field_definition, 'view_mode' => $options['view_mode'], + 'label' => $field_definition->getLabel(), ]; return $this->createInstance($plugin_id, $configuration); } only in patch2: unchanged: --- /dev/null +++ b/core/modules/field/tests/src/Unit/Plugin/DisplayComponent/FieldDisplayComponentHandlerTest.php @@ -0,0 +1,464 @@ +createMock('Drupal\Core\Extension\ModuleHandlerInterface'); + $typed_data_manager = $this->createMock(TypedDataManagerInterface::class); + $plugin_manager = new FieldTypePluginManager( + $namespaces, + $this->createMock('Drupal\Core\Cache\CacheBackendInterface'), + $module_handler, + $typed_data_manager + ); + + $container = new ContainerBuilder(); + $container->set('plugin.manager.field.field_type', $plugin_manager); + \Drupal::setContainer($container); + + $this->formatterPluginManager = $this->getMockBuilder(FormatterPluginManager::class) + ->disableOriginalConstructor() + ->getMock(); + $this->widgetPluginManager = $this->getMockBuilder(WidgetPluginManager::class) + ->disableOriginalConstructor() + ->getMock(); + $this->entityFieldManager = $this->getMockBuilder(EntityFieldManagerInterface::class) + ->onlyMethods(['getFieldDefinitions']) + ->getMockForAbstractClass(); + + // Create test definitions. + $this->definition = BaseFieldDefinition::create('text'); + $this->definitions = $this->getTestFieldDefinitions(); + $this->entityFieldManager->expects($this->any()) + ->method('getFieldDefinitions') + ->willReturn($this->definitions); + + // Create a field display component handler to test. + $this->handler = new FieldDisplayComponentHandler([], 'test', [], $this->formatterPluginManager, $this->widgetPluginManager, $this->entityFieldManager); + } + + /** + * Tests MassageIn. + * + * @covers ::massageIn() + * + * @dataProvider providerTestMassageIn + */ + public function testMassageIn($field_name, $display_context, $expected) { + $this->formatterPluginManager->expects($this->any()) + ->method('prepareConfiguration') + ->willReturn('formatter configuration'); + $this->widgetPluginManager->expects($this->any()) + ->method('prepareConfiguration') + ->willReturn('widget configuration'); + + $this->handler->setContext([ + 'entity_type' => 'anything', + 'bundle' => 'bar', + 'display_context' => $display_context, + ]); + + $testMethod = new \ReflectionMethod(FieldDisplayComponentHandler::class, 'massageIn'); + $testMethod->setAccessible(TRUE); + $actual = $testMethod->invokeArgs($this->handler, [$field_name, []]); + $this->assertEquals($expected, $actual); + } + + /** + * Provides data for testGetDisplayableField(). + */ + public function providerTestMassageIn() { + return [ + 'no field definition' => [ + 'not_exist', + '', + [], + ], + 'widget' => [ + 'title', + 'form', + 'widget configuration', + ], + 'formatter' => [ + 'headline', + 'view', + 'formatter configuration', + ], + ]; + + } + + /** + * Tests MassageOut. + * + * @covers ::massageOut() + * + * @dataProvider providerTestMassageOut + */ + public function testMassageOut($properties, $display_context, $expected) { + $properties = [ + 'content' => [ + 'title' => 'foo', + 'headline' => 'foo', + ], + 'hidden' => [ + 'title' => 'bar', + 'headline' => 'bar', + ], + 'baz' => [ + 'title' => 'cat', + 'headline' => 'dog', + ], + ]; + + $this->handler->setContext([ + 'entity_type' => 'anything', + 'bundle' => 'bar', + 'display_context' => $display_context, + ]); + + $testMethod = new \ReflectionMethod(FieldDisplayComponentHandler::class, 'massageOut'); + $testMethod->setAccessible(TRUE); + $actual = $testMethod->invokeArgs($this->handler, [$properties]); + $this->assertEquals($expected, $actual); + } + + /** + * Provides data for testGetDisplayableField(). + */ + public function providerTestMassageOut() { + $properties = [ + 'content' => [ + 'title' => 'foo', + 'headline' => 'foo', + ], + 'hidden' => [ + 'title' => 'bar', + 'headline' => 'bar', + ], + 'baz' => [ + 'title' => 'cat', + 'headline' => 'dog', + ], + ]; + return [ + 'no context' => [ + 'not_exist', + 'no_context', + $properties, + ], + 'text context' => [ + 'title', + 'form', + [ + 'content' => [ + 'headline' => 'foo', + ], + 'hidden' => [ + 'headline' => 'bar', + ], + 'baz' => [ + 'title' => 'cat', + 'headline' => 'dog', + ], + ], + ], + 'headline context' => [ + 'headline', + 'view', + [ + 'content' => [ + 'title' => 'foo', + ], + 'hidden' => [ + 'title' => 'bar', + ], + 'baz' => [ + 'title' => 'cat', + 'headline' => 'dog', + ], + ], + ], + ]; + } + + /** + * Tests getRenderer. + * + * @covers ::getRenderer() + * + * @dataProvider providerTestGetRenderer + */ + public function testGetRenderer($options, $display_context, $name, $expected) { + if ($display_context == 'view') { + $this->formatterPluginManager->expects($this->any()) + ->method('getInstance') + ->willReturn($expected); + } + else { + $this->widgetPluginManager->expects($this->any()) + ->method('getInstance') + ->willReturn($expected); + } + + $this->handler->setContext([ + 'entity_type' => 'foo', + 'bundle' => 'bar', + 'display_context' => $display_context, + 'mode' => 'cat', + ]); + + $testMethod = new \ReflectionMethod(FieldDisplayComponentHandler::class, 'getRenderer'); + $testMethod->setAccessible(TRUE); + $actual = $testMethod->invokeArgs($this->handler, [$name, $options]); + $this->assertEquals($expected, $actual); + } + + /** + * Provides data for testGetRenderer(). + */ + public function providerTestGetRenderer() { + return [ + 'no type' => [ + [], + 'no_name', + 'no_name', + NULL, + ], + 'form' => [ + ['type' => 'text'], + 'form', + 'title', + $this->getMockBuilder(StringTextfieldWidget::class) + ->disableOriginalConstructor() + ->getMock(), + ], + 'view' => [ + ['type' => 'text'], + 'view', + 'headline', + $this->getMockBuilder(TextDefaultFormatter::class) + ->disableOriginalConstructor() + ->getMock(), + ], + ]; + } + + /** + * Tests hasElement. + * + * @covers ::hasElement() + * + * @dataProvider providerTestHasElement + */ + public function testHasElement($display_context, $name, $expected) { + $this->handler->setContext([ + 'entity_type' => 'foo', + 'bundle' => 'bar', + 'display_context' => $display_context, + ]); + + $testMethod = new \ReflectionMethod(FieldDisplayComponentHandler::class, 'hasElement'); + $testMethod->setAccessible(TRUE); + $actual = $testMethod->invokeArgs($this->handler, [$name]); + $this->assertEquals($expected, $actual); + } + + /** + * Provides data for testHasElement(). + */ + public function providerTestHasElement() { + return [ + 'no context' => [ + 'no_context', + '', + FALSE, + ], + 'form' => [ + 'form', + 'title', + TRUE, + ], + 'view' => [ + 'view', + 'headline', + TRUE, + ], + ]; + } + + /** + * Tests getFieldDefinition. + * + * @covers ::getFieldDefinition() + * + * @dataProvider providerTestGetFieldDefinition + */ + public function testGetFieldDefinition($display_context, $expected_name) { + $this->handler->setContext([ + 'entity_type' => 'foo', + 'bundle' => 'bar', + 'display_context' => $display_context, + ]); + + $testMethod = new \ReflectionMethod(FieldDisplayComponentHandler::class, 'getFieldDefinition'); + $testMethod->setAccessible(TRUE); + $actual = $testMethod->invokeArgs($this->handler, [$expected_name]); + $expected = $expected_name; + if (!empty($expected_name)) { + $expected = $this->definitions[$expected_name]; + } + $this->assertEquals($expected, $actual); + } + + /** + * Provides data for testGetFieldDefinition(). + */ + public function providerTestGetFieldDefinition() { + return [ + 'no context' => [ + 'no_context', + NULL, + ], + 'form' => [ + 'form', + 'title', + ], + 'view' => [ + 'view', + 'headline', + ], + ]; + } + + /** + * Tests getDisplayableFields. + * + * @covers ::getDisplayableFields() + * + * @dataProvider providerTestGetDisplayableField + */ + public function testGetDisplayableField($display_context, $expected_name) { + $this->handler->setContext([ + 'entity_type' => 'foo', + 'bundle' => 'bar', + 'display_context' => $display_context, + ]); + + $testMethod = new \ReflectionMethod(FieldDisplayComponentHandler::class, 'getDisplayableFields'); + $testMethod->setAccessible(TRUE); + $actual = $testMethod->invokeArgs($this->handler, []); + if (empty($expected_name)) { + $expected = $expected_name; + } + else { + $expected[$expected_name] = $this->definitions[$expected_name]; + } + $this->assertEquals($expected, $actual); + } + + /** + * Provides data for testGetDisplayableField(). + */ + public function providerTestGetDisplayableField() { + return [ + 'no context' => [ + 'no_context', + [], + ], + 'form' => [ + 'form', + 'title', + ], + 'view' => [ + 'view', + 'headline', + ], + ]; + } + + /** + * Helper to set field definitions for all tests. + */ + public function getTestFieldDefinitions() { + $title = clone($this->definition); + $headline = clone($this->definition); + + return [ + 'no_display' => $this->definition, + 'headline' => $headline->setDisplayOptions('view', ['label' => 'above']), + 'title' => $title->setDisplayOptions('form', ['label' => 'above']), + ]; + } + +} only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Core/Entity/Access/EntityFormDisplayAccessControlHandlerTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/Access/EntityFormDisplayAccessControlHandlerTest.php @@ -7,6 +7,7 @@ use Drupal\Core\Cache\Context\CacheContextsManager; use Drupal\Core\Config\Entity\ConfigEntityTypeInterface; use Drupal\Core\DependencyInjection\Container; +use Drupal\Core\Entity\DisplayComponentHandlerPluginManager; use Drupal\Core\Entity\Entity\Access\EntityFormDisplayAccessControlHandler; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\Entity\EntityFieldManagerInterface; @@ -182,6 +183,7 @@ protected function setUp(): void { $container->set('uuid', $this->createMock(UuidInterface::class)); $container->set('renderer', $this->createMock(RendererInterface::class)); $container->set('cache_contexts_manager', $this->prophesize(CacheContextsManager::class)); + $container->set('plugin.manager.entity.display_component_handler', $this->prophesize(DisplayComponentHandlerPluginManager::class)); \Drupal::setContainer($container); $this->entity = new EntityFormDisplay([