Issue #3001313 by bnjmnm, tim.plunkett, bobbygryzynger, Cyberschorsch, yogeshmpawar, mikey en, hershy.k, borisson_: Field blocks in the layout builder do not have view mode suggestions
parent
81179a0baa
commit
90534acefb
|
@ -405,3 +405,15 @@ function layout_builder_preprocess_language_content_settings_table(&$variables)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_theme_suggestions_HOOK_alter().
|
||||
*/
|
||||
function layout_builder_theme_suggestions_field_alter(&$suggestions, array $variables) {
|
||||
$element = $variables['element'];
|
||||
if (isset($element['#third_party_settings']['layout_builder']['view_mode'])) {
|
||||
// See system_theme_suggestions_field().
|
||||
$suggestions[] = 'field__' . $element['#entity_type'] . '__' . $element['#field_name'] . '__' . $element['#bundle'] . '__' . $element['#third_party_settings']['layout_builder']['view_mode'];
|
||||
}
|
||||
return $suggestions;
|
||||
}
|
||||
|
|
|
@ -109,6 +109,7 @@ trait LayoutEntityHelperTrait {
|
|||
$view_mode = 'full';
|
||||
if ($entity instanceof LayoutEntityDisplayInterface) {
|
||||
$contexts['display'] = EntityContext::fromEntity($entity);
|
||||
$contexts['view_mode'] = new Context(new ContextDefinition('string'), $entity->getMode());
|
||||
}
|
||||
else {
|
||||
$contexts['entity'] = EntityContext::fromEntity($entity);
|
||||
|
|
|
@ -156,6 +156,7 @@ class FieldBlock extends BlockBase implements ContextAwarePluginInterface, Conta
|
|||
*/
|
||||
public function build() {
|
||||
$display_settings = $this->getConfiguration()['formatter'];
|
||||
$display_settings['third_party_settings']['layout_builder']['view_mode'] = $this->getContextValue('view_mode');
|
||||
$entity = $this->getEntity();
|
||||
try {
|
||||
$build = $entity->get($this->fieldName)->view($display_settings);
|
||||
|
|
|
@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityTypeRepositoryInterface;
|
|||
use Drupal\Core\Field\FieldConfigInterface;
|
||||
use Drupal\Core\Field\FieldTypePluginManagerInterface;
|
||||
use Drupal\Core\Field\FormatterPluginManager;
|
||||
use Drupal\Core\Plugin\Context\ContextDefinition;
|
||||
use Drupal\Core\Plugin\Context\EntityContextDefinition;
|
||||
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
|
@ -123,6 +124,7 @@ class FieldBlockDeriver extends DeriverBase implements ContainerDeriverInterface
|
|||
$context_definition->addConstraint('Bundle', [$bundle]);
|
||||
$derivative['context_definitions'] = [
|
||||
'entity' => $context_definition,
|
||||
'view_mode' => new ContextDefinition('string'),
|
||||
];
|
||||
|
||||
$derivative_id = $entity_type_id . PluginBase::DERIVATIVE_SEPARATOR . $bundle . PluginBase::DERIVATIVE_SEPARATOR . $field_name;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\layout_builder\Plugin\SectionStorage;
|
||||
|
||||
use Drupal\Component\Plugin\Context\ContextInterface as ComponentContextInterface;
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Cache\RefinableCacheableDependencyInterface;
|
||||
|
@ -33,6 +34,7 @@ use Symfony\Component\Routing\RouteCollection;
|
|||
* weight = 20,
|
||||
* context_definitions = {
|
||||
* "display" = @ContextDefinition("entity:entity_view_display"),
|
||||
* "view_mode" = @ContextDefinition("string", default_value = "default"),
|
||||
* },
|
||||
* )
|
||||
*
|
||||
|
@ -432,4 +434,15 @@ class DefaultsSectionStorage extends SectionStorageBase implements ContainerFact
|
|||
return $this->isLayoutBuilderEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setContext($name, ComponentContextInterface $context) {
|
||||
// Set the view mode context based on the display context.
|
||||
if ($name === 'display') {
|
||||
$this->setContextValue('view_mode', $context->getContextValue()->getMode());
|
||||
}
|
||||
parent::setContext($name, $context);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ use Symfony\Component\Routing\RouteCollection;
|
|||
* "entity" = @ContextDefinition("entity", constraints = {
|
||||
* "EntityHasField" = \Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage::FIELD_NAME,
|
||||
* }),
|
||||
* "view_mode" = @ContextDefinition("string"),
|
||||
* "view_mode" = @ContextDefinition("string", default_value = "default"),
|
||||
* }
|
||||
* )
|
||||
*
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace Drupal\layout_builder\Plugin\SectionStorage;
|
||||
|
||||
use Drupal\Core\Plugin\Context\Context;
|
||||
use Drupal\Core\Plugin\Context\ContextDefinition;
|
||||
use Drupal\Core\Plugin\ContextAwarePluginBase;
|
||||
use Drupal\layout_builder\Routing\LayoutBuilderRoutesTrait;
|
||||
use Drupal\layout_builder\Section;
|
||||
|
@ -109,7 +111,16 @@ abstract class SectionStorageBase extends ContextAwarePluginBase implements Sect
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContextsDuringPreview() {
|
||||
return $this->getContexts();
|
||||
$contexts = $this->getContexts();
|
||||
|
||||
// view_mode is a required context, but SectionStorage plugins are not
|
||||
// required to return it (for example, the layout_library plugin provided
|
||||
// in the Layout Library module. In these instances, explicitly create a
|
||||
// view_mode context with the value "default".
|
||||
if (!isset($contexts['view_mode']) || $contexts['view_mode']->validate()->count() || !$contexts['view_mode']->getContextValue()) {
|
||||
$contexts['view_mode'] = new Context(new ContextDefinition('string'), 'default');
|
||||
}
|
||||
return $contexts;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
name: 'Layout Builder Field Block Theme Suggestions Test'
|
||||
type: module
|
||||
description: 'Support module for testing.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* For testing Field Block theme suggestions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_theme().
|
||||
*/
|
||||
function layout_builder_field_block_theme_suggestions_test_theme() {
|
||||
// It is necessary to explicitly register the template via hook_theme()
|
||||
// because it is added via a module, not a theme.
|
||||
return [
|
||||
'field__node__body__bundle_with_section_field__default' => [
|
||||
'base hook' => 'field',
|
||||
],
|
||||
];
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
<h1>I am a field template for a specific view mode!</h1>
|
|
@ -0,0 +1,5 @@
|
|||
services:
|
||||
layout_builder_fieldblock_test.fake_view_mode_context:
|
||||
class: Drupal\layout_builder_fieldblock_test\ContextProvider\FakeViewModeContext
|
||||
tags:
|
||||
- { name: 'context_provider' }
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\layout_builder_fieldblock_test\ContextProvider;
|
||||
|
||||
use Drupal\Core\Plugin\Context\Context;
|
||||
use Drupal\Core\Plugin\Context\ContextDefinition;
|
||||
use Drupal\Core\Plugin\Context\ContextProviderInterface;
|
||||
|
||||
/**
|
||||
* Provides a global context for view_mode for testing purposes.
|
||||
*
|
||||
* @group layout_builder
|
||||
*/
|
||||
class FakeViewModeContext implements ContextProviderInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRuntimeContexts(array $unqualified_context_ids) {
|
||||
return ['view_mode' => new Context(new ContextDefinition('string'), 'default')];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAvailableContexts() {
|
||||
return $this->getRuntimeContexts([]);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\layout_builder\Functional;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests field block template suggestions.
|
||||
*
|
||||
* @group layout_builder
|
||||
*/
|
||||
class LayoutBuilderFieldBlockThemeSuggestionsTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'layout_builder',
|
||||
'node',
|
||||
'layout_builder_field_block_theme_suggestions_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->createContentType([
|
||||
'type' => 'bundle_with_section_field',
|
||||
'name' => 'Bundle with section field',
|
||||
]);
|
||||
$this->createNode([
|
||||
'type' => 'bundle_with_section_field',
|
||||
'title' => 'A node title',
|
||||
'body' => [
|
||||
[
|
||||
'value' => 'This is content that the template should not render',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->drupalLogin($this->drupalCreateUser([
|
||||
'configure any layout',
|
||||
'administer node display',
|
||||
]));
|
||||
|
||||
$this->drupalGet('admin/structure/types/manage/bundle_with_section_field/display/default');
|
||||
$this->drupalPostForm(NULL, ['layout[enabled]' => TRUE], 'Save');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that of view mode specific field templates are suggested.
|
||||
*/
|
||||
public function testFieldBlockViewModeTemplates() {
|
||||
$assert_session = $this->assertSession();
|
||||
|
||||
$this->drupalGet('node/1');
|
||||
// Confirm that content is displayed by layout builder.
|
||||
$assert_session->elementExists('css', '.block-layout-builder');
|
||||
// Text that only appears in the view mode specific template.
|
||||
$assert_session->pageTextContains('I am a field template for a specific view mode!');
|
||||
// The content of the body field should not be visible because it is
|
||||
// displayed via a template that does not render it.
|
||||
$assert_session->pageTextNotContains('This is content that the template should not render');
|
||||
}
|
||||
|
||||
}
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
namespace Drupal\Tests\layout_builder\Kernel;
|
||||
|
||||
use Drupal\Core\Plugin\Context\Context;
|
||||
use Drupal\Core\Plugin\Context\ContextDefinition;
|
||||
use Drupal\Core\Plugin\Context\EntityContext;
|
||||
use Drupal\Core\Plugin\Context\EntityContextDefinition;
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay;
|
||||
|
@ -51,7 +54,10 @@ class DefaultsSectionStorageTest extends KernelTestBase {
|
|||
$this->installEntitySchema('user');
|
||||
$this->installConfig(['layout_builder_defaults_test']);
|
||||
|
||||
$this->plugin = DefaultsSectionStorage::create($this->container, [], 'defaults', new SectionStorageDefinition());
|
||||
$definition = (new SectionStorageDefinition())
|
||||
->addContextDefinition('display', EntityContextDefinition::fromEntityTypeId('entity_view_display'))
|
||||
->addContextDefinition('view_mode', new ContextDefinition('string'));
|
||||
$this->plugin = DefaultsSectionStorage::create($this->container, [], 'defaults', $definition);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -141,8 +147,9 @@ class DefaultsSectionStorageTest extends KernelTestBase {
|
|||
$context = EntityContext::fromEntity($display);
|
||||
$this->plugin->setContext('display', $context);
|
||||
|
||||
$expected = ['display' => $context];
|
||||
$this->assertSame($expected, $this->plugin->getContexts());
|
||||
$result = $this->plugin->getContexts();
|
||||
$this->assertSame(['view_mode', 'display'], array_keys($result));
|
||||
$this->assertSame($context, $result['display']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -161,7 +168,7 @@ class DefaultsSectionStorageTest extends KernelTestBase {
|
|||
$this->plugin->setContext('display', $context);
|
||||
|
||||
$result = $this->plugin->getContextsDuringPreview();
|
||||
$this->assertEquals(['display', 'layout_builder.entity'], array_keys($result));
|
||||
$this->assertSame(['view_mode', 'display', 'layout_builder.entity'], array_keys($result));
|
||||
|
||||
$this->assertSame($context, $result['display']);
|
||||
|
||||
|
@ -169,6 +176,10 @@ class DefaultsSectionStorageTest extends KernelTestBase {
|
|||
$result_value = $result['layout_builder.entity']->getContextValue();
|
||||
$this->assertInstanceOf(EntityTest::class, $result_value);
|
||||
$this->assertSame('entity_test', $result_value->bundle());
|
||||
|
||||
$this->assertInstanceOf(Context::class, $result['view_mode']);
|
||||
$result_value = $result['view_mode']->getContextValue();
|
||||
$this->assertSame('default', $result_value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -203,4 +214,24 @@ class DefaultsSectionStorageTest extends KernelTestBase {
|
|||
$this->assertSame('entity_test.entity_test.default', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests loading given a display.
|
||||
*/
|
||||
public function testLoadFromDisplay() {
|
||||
$display = LayoutBuilderEntityViewDisplay::create([
|
||||
'targetEntityType' => 'entity_test',
|
||||
'bundle' => 'entity_test',
|
||||
'mode' => 'default',
|
||||
'status' => TRUE,
|
||||
]);
|
||||
$display->save();
|
||||
$contexts = [
|
||||
'display' => EntityContext::fromEntity($display),
|
||||
];
|
||||
|
||||
$section_storage_manager = $this->container->get('plugin.manager.layout_builder.section_storage');
|
||||
$section_storage = $section_storage_manager->load('defaults', $contexts);
|
||||
$this->assertInstanceOf(DefaultsSectionStorage::class, $section_storage);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ use Drupal\Core\Extension\ModuleHandlerInterface;
|
|||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Field\FormatterPluginManager;
|
||||
use Drupal\Core\Plugin\Context\ContextDefinition;
|
||||
use Drupal\Core\Form\EnforcedResponseException;
|
||||
use Drupal\Core\Plugin\Context\EntityContextDefinition;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
@ -210,6 +211,7 @@ class FieldBlockTest extends EntityKernelTestBase {
|
|||
'bundles' => ['entity_test'],
|
||||
'context_definitions' => [
|
||||
'entity' => EntityContextDefinition::fromEntityTypeId('entity_test')->setLabel('Test'),
|
||||
'view_mode' => new ContextDefinition('string'),
|
||||
],
|
||||
];
|
||||
$formatter_manager = $this->prophesize(FormatterPluginManager::class);
|
||||
|
@ -225,6 +227,7 @@ class FieldBlockTest extends EntityKernelTestBase {
|
|||
$this->logger->reveal()
|
||||
);
|
||||
$block->setContextValue('entity', $entity_prophecy->reveal());
|
||||
$block->setContextValue('view_mode', 'default');
|
||||
return $block;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ class LayoutEntityHelperTraitTest extends KernelTestBase {
|
|||
],
|
||||
],
|
||||
],
|
||||
['display'],
|
||||
['display', 'view_mode'],
|
||||
];
|
||||
$data['fieldable entity'] = [
|
||||
'entity_test',
|
||||
|
|
|
@ -2,13 +2,17 @@
|
|||
|
||||
namespace Drupal\Tests\layout_builder\Unit;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Entity\EntityType;
|
||||
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Entity\FieldableEntityInterface;
|
||||
use Drupal\Core\Plugin\Context\ContextDefinition;
|
||||
use Drupal\Core\Plugin\Context\ContextInterface;
|
||||
use Drupal\Core\Plugin\Context\EntityContextDefinition;
|
||||
use Drupal\Core\TypedData\TypedDataManagerInterface;
|
||||
use Drupal\layout_builder\Entity\LayoutEntityDisplayInterface;
|
||||
use Drupal\layout_builder\Entity\SampleEntityGeneratorInterface;
|
||||
use Drupal\layout_builder\Plugin\SectionStorage\DefaultsSectionStorage;
|
||||
|
@ -67,6 +71,17 @@ class DefaultsSectionStorageTest extends UnitTestCase {
|
|||
* @covers ::setThirdPartySetting
|
||||
*/
|
||||
public function testThirdPartySettings() {
|
||||
$this->entityTypeManager->getDefinition('entity_view_display')->willReturn(new EntityType(['id' => 'entity_view_display']));
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('typed_data_manager', $this->prophesize(TypedDataManagerInterface::class)->reveal());
|
||||
$container->set('entity_type.manager', $this->entityTypeManager->reveal());
|
||||
\Drupal::setContainer($container);
|
||||
|
||||
$this->plugin->getPluginDefinition()
|
||||
->addContextDefinition('display', EntityContextDefinition::fromEntityTypeId('entity_view_display'))
|
||||
->addContextDefinition('view_mode', new ContextDefinition('string'));
|
||||
|
||||
// Set an initial value on the section list.
|
||||
$section_list = $this->prophesize(LayoutEntityDisplayInterface::class);
|
||||
|
||||
|
|
Loading…
Reference in New Issue