domain_views_display-1.x-dev/src/Plugin/views/display_extender/DomainViewsDisplayExtender.php
src/Plugin/views/display_extender/DomainViewsDisplayExtender.php
<?php
declare(strict_types=1);
namespace Drupal\domain_views_display\Plugin\views\display_extender;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\domain\DomainInterface;
use Drupal\domain\DomainStorageInterface;
use Drupal\views\Attribute\ViewsDisplayExtender;
use Drupal\views\Plugin\views\display_extender\DisplayExtenderPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Adds the option for a display to be overridden per-domain.
*
* @ingroup views_display_extender_plugins
*
* @see \Drupal\domain_views_display\DomainViewsDisplay
*/
#[ViewsDisplayExtender(
id: self::ID,
title: new TranslatableMarkup('Domain Views Display extender'),
help: new TranslatableMarkup('Domain Views Display settings for this view.'),
)]
class DomainViewsDisplayExtender extends DisplayExtenderPluginBase {
/**
* The plugin ID.
*
* @var string
*/
public const ID = 'domain_views_display_display_extender';
/**
* The entity type manager.
*/
protected EntityTypeManagerInterface $entityTypeManager;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, mixed $plugin_definition): static {
$extender = parent::create($container, $configuration, $plugin_id, $plugin_definition);
$extender->entityTypeManager = $container->get('entity_type.manager');
return $extender;
}
/**
* {@inheritdoc}
*/
protected function defineOptions(): array {
$options = parent::defineOptions();
$options['override_displays'] = ['default' => []];
return $options;
}
/**
* {@inheritdoc}
*/
public function optionsSummary(&$categories, &$options): void {
$categories['domain_views_display'] = [
'title' => $this->t('Domain overrides'),
'column' => 'second',
];
if ($this->options['override_displays']) {
$domains = $this->getDomainStorage()->loadMultipleSorted(array_keys($this->options['override_displays']));
// @phpstan-ignore return.type
$domain_names = array_map(fn (DomainInterface $domain): string|TranslatableMarkup => $domain->label(), $domains);
$value = implode(', ', $domain_names);
}
else {
$value = $this->t("None");
}
$options['override_displays'] = [
'category' => 'domain_views_display',
'title' => $this->t('Override display'),
'value' => $value,
];
}
/**
* {@inheritdoc}
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state): void {
if ($form_state->get('section') == 'override_displays') {
$form['#title'] .= $this->t("Per-domain display overrides");
$form['override_displays'] = [
'#type' => 'fieldset',
'#title' => $this->t("Override the display by domain"),
'#tree' => TRUE,
'#description' => $this->t("Choose to use a different display based on the current domain."),
];
$domains = $this->getDomainStorage()->loadMultipleSorted();
foreach ($domains as $domain) {
assert($domain instanceof DomainInterface);
// @todo If this display is already used as an override for another
// display, don't allow this one to be overridden on the same domains.
// ie it shouldn't be possible to have display X forward to display Y
// on domain A, and have display Y forward to display Z on domain A.
// This would prevent inefficiencies and loops.
$summarize = fn(array $display): TranslatableMarkup => $this->t("@title (@id)", [
'@title' => $display['display_title'],
'@id' => $display['id'],
]);
// @phpstan-ignore argument.type, argument.type
$displays = array_map($summarize, $this->view->storage->get('display'));
unset($displays[$this->view->current_display]);
unset($displays['default']);
$form['override_displays'][$domain->id()] = [
'#title' => $domain->label(),
'#type' => 'select',
'#options' => $displays,
'#empty_option' => $this->t("This display"),
'#default_value' => $this->options['override_displays'][$domain->id()] ?? NULL,
];
}
}
}
/**
* {@inheritdoc}
*/
public function submitOptionsForm(&$form, FormStateInterface $form_state): void {
parent::submitOptionsForm($form, $form_state);
if ($form_state->get('section') == 'override_displays') {
// @phpstan-ignore argument.type
$this->options['override_displays'] = array_filter($form_state->getValue('override_displays'));
}
}
/**
* {@inheritdoc}
*/
public function calculateDependencies(): array {
// This doesn't seem to actually impact the View dependencies.
// @see https://www.drupal.org/project/drupal/issues/2426607
$dependencies = parent::calculateDependencies();
$domain_ids = array_keys($this->options['override_displays']);
$domains = $this->getDomainStorage()->loadMultiple($domain_ids);
foreach ($domains as $domain) {
$dependencies['config'][] = $domain->getConfigDependencyName();
}
return $dependencies;
}
/**
* Gets the domain storage.
*/
protected function getDomainStorage(): DomainStorageInterface {
$storage = $this->entityTypeManager->getStorage('domain');
assert($storage instanceof DomainStorageInterface);
return $storage;
}
}
