Skip to content

Commit

Permalink
Merge pull request #196 from openeuropa/EWPP-3658
Browse files Browse the repository at this point in the history
EWPP-3658: Link list display plugin integration.
  • Loading branch information
upchuk authored Jan 15, 2024
2 parents a3e87e7 + 40351e4 commit 2945c60
Show file tree
Hide file tree
Showing 11 changed files with 903 additions and 5 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@
"psr-4": {
"Drupal\\Tests\\oe_list_pages\\": "./tests/src",
"Drupal\\Tests\\oe_link_lists\\": "./build/modules/contrib/oe_link_lists/tests/src",
"Drupal\\Tests\\oe_list_pages_link_list_source\\": "./modules/oe_list_pages_link_list_source/tests/src"
"Drupal\\Tests\\oe_list_pages_link_list_source\\": "./modules/oe_list_pages_link_list_source/tests/src",
"Drupal\\Tests\\oe_list_pages_link_list_displays\\": "./modules/oe_list_pages_link_list_displays/tests/src"
}
},
"extra": {
Expand Down
26 changes: 26 additions & 0 deletions modules/oe_list_pages_link_list_displays/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# OE List Pages Link List Displays

This module furthers the integration with the `OE Link Lists` component by
taking over the rendering of the list pages and using the
`Display` plugins made available for link lists.

## How to use

Install the module and it will directly start working.

When you create a list page, you will have a mandatory `Display` select where
you will need to pick one of the available link list display plugins.

List pages created before the module was installed will continue to render using
the default view mode.

## How it works

The module acts in two places.

First, it alters the `ListPage` entity meta configuration form to present the user
with the option to pick and configure the Display plugin to use.
This choice is then stored in the `extra` configuration key of the list page.

Second, the module takes over the `ListBuilder` object responsible for rendering
the list and uses the chosen Display plugin to actually build the list.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: List page displays from link lists
description: Exposes the link list displays on list pages
type: module
core_version_requirement: ^9.4 || ^10

dependencies:
- oe_list_pages:oe_list_pages
- oe_link_lists:oe_link_lists
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

/**
* @file
* The OpenEuropa List Pages Link List Displays module.
*/

declare(strict_types = 1);

use Drupal\Core\Form\FormStateInterface;

/**
* Implements hook_list_page_entity_meta_form_alter().
*/
function oe_list_pages_link_list_displays_list_page_entity_meta_form_alter(array &$form, FormStateInterface $form_state) {
$entity_meta_bundle = $form_state->get('entity_meta_bundle');
/** @var \Drupal\emr\Entity\EntityMetaInterface $entity_meta */
$entity_meta = $form_state->get($entity_meta_bundle . '_entity_meta');
\Drupal::service('oe_list_pages_link_list_displays.list_display_selection_builder')->form($form, $form_state, $entity_meta);
}

/**
* Implements hook_list_page_entity_meta_form_submit_alter().
*/
function oe_list_pages_link_list_displays_list_page_entity_meta_form_submit_alter(array &$form, FormStateInterface $form_state, array &$configuration) {
$display_configuration = \Drupal::service('oe_list_pages_link_list_displays.list_display_selection_builder')->extractPluginConfiguration('display', $form, $form_state);
$configuration['extra']['oe_list_pages_link_list_displays']['display'] = $display_configuration;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
services:
oe_list_pages_link_list_displays.list_display_selection_builder:
class: Drupal\oe_list_pages_link_list_displays\ListDisplaySelectionBuilder
arguments: ['@plugin.manager.oe_link_lists.link_display']
175 changes: 175 additions & 0 deletions modules/oe_list_pages_link_list_displays/src/ListBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
<?php

declare(strict_types = 1);

namespace Drupal\oe_list_pages_link_list_displays;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Pager\PagerManagerInterface;
use Drupal\facets\Processor\ProcessorPluginManager;
use Drupal\facets\UrlProcessor\UrlProcessorPluginManager;
use Drupal\facets\Utility\FacetsUrlGenerator;
use Drupal\oe_link_lists\Event\EntityValueResolverEvent;
use Drupal\oe_link_lists\LinkCollection;
use Drupal\oe_link_lists\LinkDisplayPluginManagerInterface;
use Drupal\oe_list_pages\ListBuilder as DefaultListBuilder;
use Drupal\oe_list_pages\ListExecutionManagerInterface;
use Drupal\oe_list_pages\ListPageConfiguration;
use Drupal\oe_list_pages\ListSourceFactory;
use Drupal\oe_list_pages\MultiselectFilterFieldPluginManager;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

/**
* Link List display-based list builder.
*
* We take over the original list builder and use the chosen display plugins
* to render the list.
*/
class ListBuilder extends DefaultListBuilder {

/**
* The event dispatcher.
*
* @var \Symfony\Contracts\EventDispatcher\EventDispatcherInterface
*/
protected $eventDispatcher;

/**
* The link display manager.
*
* @var \Drupal\oe_link_lists\LinkDisplayPluginManagerInterface
*/
protected $linkDisplayPluginManager;

/**
* {@inheritdoc}
*
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(ListExecutionManagerInterface $listExecutionManager, EntityTypeManager $entityTypeManager, PagerManagerInterface $pager, EntityRepositoryInterface $entityRepository, FormBuilderInterface $formBuilder, FacetsUrlGenerator $facetsUrlGenerator, ProcessorPluginManager $processorManager, RequestStack $requestStack, UrlProcessorPluginManager $urlProcessorManager, MultiselectFilterFieldPluginManager $multiselectFilterManager, ListSourceFactory $listSourceFactory, EventDispatcherInterface $eventDispatcher, LinkDisplayPluginManagerInterface $linkDisplayPluginManager) {
parent::__construct($listExecutionManager, $entityTypeManager, $pager, $entityRepository, $formBuilder, $facetsUrlGenerator, $processorManager, $requestStack, $urlProcessorManager, $multiselectFilterManager, $listSourceFactory);
$this->eventDispatcher = $eventDispatcher;
$this->linkDisplayPluginManager = $linkDisplayPluginManager;
}

/**
* {@inheritdoc}
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
public function buildList(ListPageConfiguration $configuration): array {
$extra = $configuration->getExtra();
if (!isset($extra['oe_list_pages_link_list_displays'])) {
// If we don't have the displays configured, we simply defer back to the
// parent like nothing happened.
return parent::buildList($configuration);
}

// Verify that the chosen display plugin exists.
$display_configuration = $extra['oe_list_pages_link_list_displays'];
$display_plugin = $display_configuration['display']['plugin'];
$display_plugin_configuration = $display_configuration['display']['plugin_configuration'] ?? [];
if (!$this->linkDisplayPluginManager->hasDefinition($display_plugin)) {
return parent::buildList($configuration);
}

$build = [
'list' => [],
];

$cache = new CacheableMetadata();
$cache->addCacheContexts(['url.query_args']);

$sort = $this->getSortFromUrl($configuration);
// The sort could potentially be overridden from the URL.
if ($sort) {
$configuration->setSort($sort);
}

$list_execution = $this->listExecutionManager->executeList($configuration);
if (empty($list_execution)) {
$cache->applyTo($build);
return $build;
}

$list_source = $list_execution->getListSource();
if (!$list_source) {
$cache->applyTo($build);
return $build;
}

$query = $list_execution->getQuery();
$cache->addCacheableDependency($query);
$cache->addCacheTags($query->getCacheTags());
$result = $list_execution->getResults();
$configuration = $list_execution->getConfiguration();
$cache->addCacheTags([$configuration->getEntityType() . '_list:' . $configuration->getBundle()]);

$this->pager->createPager($result->getResultCount(), $query->getOption('limit'));
$build['pager'] = [
'#type' => 'pager',
];

if (!$result->getResultCount()) {
$cache->applyTo($build);
return $build;
}

$links = new LinkCollection();
foreach ($result->getResultItems() as $item) {
try {
// Do not crash the application in case the index still has an item in
// it pointing to an entity that got deleted.
$entity = $item->getOriginalObject()->getEntity();
}
catch (\Exception $exception) {
continue;
}

/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $this->entityRepository->getTranslationFromContext($entity);

// Turn the entity into a LinkInterface.
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$event = new EntityValueResolverEvent($entity);
$this->eventDispatcher->dispatch($event, EntityValueResolverEvent::NAME);
$cache->addCacheableDependency($entity);
$links->add($event->getLink());
}

$links->addCacheableDependency($cache);

// Check each link for access before rendering.
foreach ($links as $key => $link) {
/** @var \Drupal\oe_link_lists\LinkInterface $link */
$access = $link->access('view', NULL, TRUE);
$cache->addCacheableDependency($access);

if (!$access->isAllowed()) {
unset($links[$key]);
}
}

if ($links->isEmpty()) {
$build = [];
$cache->addCacheableDependency($links);
$cache->applyTo($build);
return $build;
}

// Prepare the links for rendering with the chosen display plugin.
/** @var \Drupal\oe_link_lists\LinkDisplayInterface $plugin */
$plugin = $this->linkDisplayPluginManager->createInstance($display_plugin, $display_plugin_configuration);
$build['list'] = $plugin->build($links);
$cache->addCacheableDependency($links);
$cache->applyTo($build);

return $build;
}

}
Loading

0 comments on commit 2945c60

Please sign in to comment.