display_builder-1.0.x-dev/modules/display_builder_page_layout/src/Plugin/DisplayVariant/DisplayBuilderDisplayVariant.php
modules/display_builder_page_layout/src/Plugin/DisplayVariant/DisplayBuilderDisplayVariant.php
<?php
declare(strict_types=1);
namespace Drupal\display_builder_page_layout\Plugin\DisplayVariant;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Display\Attribute\DisplayVariant;
use Drupal\Core\Display\ContextAwareVariantInterface;
use Drupal\Core\Display\VariantBase;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Url;
use Drupal\display_builder\DisplayBuilderHelpers;
use Drupal\display_builder\Entity\DisplayBuilder;
use Drupal\display_builder\StateManager\StateManagerInterface;
use Drupal\display_builder_page_layout\DisplayBuilderPageLayout;
use Drupal\ui_patterns\Element\ComponentElementBuilder;
use Drupal\ui_patterns\Plugin\Context\RequirementsContext;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a Layout Builder variant.
*
* @todo do we need this display or only the page?
*/
#[DisplayVariant(
id: 'display_builder',
admin_label: new TranslatableMarkup('Display Builder (Content only)'),
)]
class DisplayBuilderDisplayVariant extends VariantBase implements ContainerFactoryPluginInterface, ContextAwareVariantInterface {
private const PAGE_MANAGER_PREFIX = 'page_manager_';
/**
* An array of collected contexts.
*
* This is only used on runtime, and is not stored.
*
* @var \Drupal\Component\Plugin\Context\ContextInterface[]
*/
protected $contexts = [];
/**
* The display builder state manager.
*/
protected StateManagerInterface $stateManager;
/**
* The entity type manager service.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The display builder page layout config.
*
* @var \Drupal\Core\Config\ImmutableConfig
*/
protected $config;
/**
* Component element builder.
*
* @var \Drupal\ui_patterns\Element\ComponentElementBuilder
*/
protected $componentElementBuilder;
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
StateManagerInterface $state_manager,
ConfigFactoryInterface $config_factory,
EntityTypeManagerInterface $entity_type_manager,
ComponentElementBuilder $component_element_builder,
) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->stateManager = $state_manager;
$this->config = $config_factory->get(DisplayBuilderPageLayout::PAGE_LAYOUT_CONFIG);
$this->entityTypeManager = $entity_type_manager;
$this->componentElementBuilder = $component_element_builder;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('display_builder.state_manager'),
$container->get('config.factory'),
$container->get('entity_type.manager'),
$container->get('ui_patterns.component_element_builder'),
);
}
/**
* {@inheritdoc}
*/
public function build(): array {
$build = [];
$builder_id = $this->configuration['display_builder_id'] ?? '';
if (empty($this->configuration['display_builder_id'])) {
throw new \LogicException('Missing display builder id in this page manager variant.');
}
$builder_data = $this->stateManager->getCurrentState($builder_id);
$contexts = $this->stateManager->getContexts($builder_id) ?? [];
// @todo merge contexts from page manager.
// phpcs:ignore-next-line
// $contexts = \array_merge($contexts, $this->getContexts());
$display_builder_data = [];
foreach ($builder_data as $source_data) {
$build = $this->componentElementBuilder->buildSource([], 'content', [], $source_data, $contexts);
$display_builder_data[] = $build['#slots']['content'][0] ?? [];
}
return $display_builder_data;
}
/**
* {@inheritdoc}
*/
public function getContexts(): array {
return $this->contexts;
}
/**
* {@inheritdoc}
*/
public function setContexts(array $contexts): self {
$this->contexts = $contexts;
return $this;
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
if (isset($this->configuration['display_builder_id']) && !empty($this->configuration['display_builder_id'])) {
$url = Url::fromRoute('display_builder_page_layout.page_manager.manage', ['builder_id' => $this->configuration['display_builder_id']]);
$form['info'] = [
'#markup' => '<p>' . $this->t('Got to the <a href="@url">display builder edit page</a> to edit this variant.', ['@url' => $url->toString()]) . '</p>',
];
return $form;
}
$displayBuilderConfig = $this->entityTypeManager->getStorage('display_builder')->loadMultiple();
$options = [];
foreach ($displayBuilderConfig as $entityId => $configEntity) {
$options[$entityId] = $configEntity->label();
}
$form['builder_config_id'] = [
'#type' => 'select',
'#title' => $this->t('Display Builder config'),
'#description' => $this->t('Pick a display builder configuration to use.'),
'#options' => $options,
'#default_value' => $this->configuration['builder_config_id'] ?? DisplayBuilder::DISPLAY_BUILDER_CONFIG,
'#required' => TRUE,
];
$form['fixture_id'] = [
'#type' => 'select',
'#title' => $this->t('Initial content'),
'#description' => $this->t('Enter the initial content to use for this display builder.'),
'#options' => DisplayBuilderHelpers::getAllFixturesOptions(['display_builder_page_layout']),
'#default_value' => 'blank',
'#required' => TRUE,
];
return $form;
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void {
// Save label.
parent::submitConfigurationForm($form, $form_state);
// Nothing to do if we are editing a variant on page manager form.
if (empty($form_state->getValues())) {
return;
}
// Generate a display builder instance id, prefix is only to ease
// identification and is never used for any process or logic.
$display_builder_id = \sprintf('%s%s', self::PAGE_MANAGER_PREFIX, uniqid());
$builder_config_id = $form_state->getValue('builder_config_id');
// Get the initial data from fixture.
// @todo display_builder_devel module will be deleted or split.
$fixture_id = $form_state->getValue('fixture_id');
$builder_data = DisplayBuilderHelpers::getFixtureDataFromModule('display_builder_page_layout', '', $fixture_id);
// Set context mark to know it's a page manager builder, and add the page
// manager config uuid to save later builder data in the page manager
// configuration object.
// We add both requirements to allow sources from
// Drupal\ui_patterns_overrides\Plugin\UiPatterns\Source.
$contexts = [];
$requirements = [
DisplayBuilderPageLayout::PAGE_MANAGER_CONTEXT_REQUIREMENT,
DisplayBuilderPageLayout::PAGE_LAYOUT_CONTEXT_REQUIREMENT,
];
$contexts = RequirementsContext::addToContext($requirements, $contexts);
$contexts['page_manager_variant_uuid'] = new Context(ContextDefinition::create('string'), $this->configuration['uuid'] ?? '');
$this->stateManager->create($display_builder_id, $builder_config_id, $builder_data, $contexts);
$this->configuration['display_builder_id'] = $display_builder_id;
$this->configuration['display_builder_sources'] = $builder_data;
}
}
