Skip to content
Snippets Groups Projects

Issue #3463231: Plugin for tracking entities used in contextual filters from insert view

Files
5
<?php
namespace Drupal\insert_view_adv\Plugin\EntityUsage\Track;
use Drupal\Component\Utility\Html;
use Drupal\entity_usage\Plugin\EntityUsage\Track\TextFieldEmbedBase;
use Drupal\taxonomy\Plugin\views\argument\IndexTid;
use Drupal\taxonomy\Plugin\views\argument\IndexTidDepth;
use Drupal\taxonomy\Plugin\views\argument\IndexTidDepthModifier;
use Drupal\views\Plugin\views\argument\EntityReferenceArgument;
use Drupal\views\Plugin\views\ViewsHandlerInterface;
use Drupal\views\Views;
/**
* Tracks usage of entities used as contextual filters by advanced insert view.
*
* @EntityUsageTrack(
* id = "insert_view_arguments",
* label = @Translation("Insert view arguments"),
* description = @Translation("Tracks relationships created with 'Advanced Insert View arguments' in formatted text fields."),
* field_types = {"text", "text_long", "text_with_summary"},
* )
*/
class InsertViewArguments extends TextFieldEmbedBase {
/**
* View argument handlers keyed by view id, display id.
*
* @var array
*/
protected array $argumentHandlers = [];
/**
* {@inheritdoc}
*/
public function parseEntitiesFromText($text): array {
$dom = Html::load($text);
$xpath = new \DOMXPath($dom);
$entities = [];
/** @var \DOMElement $node */
foreach ($xpath->query('//drupal-view[@data-arguments]') as $node) {
// Skip elements with empty data-arguments attributes.
$argumentValues = explode('/', $node->getAttribute('data-arguments'));
if (empty($argumentValues)) {
continue;
}
$viewId = $node->getAttribute('data-view-id');
$displayId = $node->getAttribute('data-display-id');
$handlers = $this->getArgumentHandlers($viewId, $displayId);
foreach ($handlers as $index => $handler) {
if (
!empty($argumentValues[$index]) &&
($entityType = $this->getEntityTargetFromHandler($handler))
) {
try {
$entityStorage = $this->entityTypeManager->getStorage($entityType);
$entity = $entityStorage->load($argumentValues[$index]);
$entities[$entity->uuid()] = $entityType;
}
catch (\Exception $e) {
// Possibility that referenced argument does not exist so continue.
continue;
}
}
}
}
return $entities;
}
/**
* Gets the argument handlers for a view display.
*
* Loading the handlers so we have the full access to the definition which for
* entity references will contain the target_entity_type_id.
*
* @param string $viewId
* View ID.
* @param string $displayId
* View display ID.
*
* @return \Drupal\views\Plugin\views\ViewsHandlerInterface[]
* View argument handlers for the given view display.
*/
protected function getArgumentHandlers(string $viewId, string $displayId): array {
if (!isset($this->argumentHandlers[$viewId][$displayId])) {
$this->argumentHandlers[$viewId][$displayId] = [];
// Ensure view exists.
if (($view = Views::getView($viewId))) {
// Ensure display exists.
$view->initDisplay();
if ($view->displayHandlers->has($displayId)) {
$view->setDisplay($displayId);
$arguments = $view->display_handler->getOption('arguments') ?: [];
$argumentHandlerManager = Views::handlerManager('argument');
$this->argumentHandlers[$viewId][$displayId] = array_map([$argumentHandlerManager, 'getHandler'], array_values($arguments));
}
}
}
return $this->argumentHandlers[$viewId][$displayId];
}
/**
* Get the entity type id of the target from a handler.
*
* @param \Drupal\views\Plugin\views\ViewsHandlerInterface $handler
* The argument handler.
*
* @return string|null
* The entity type id if determined, or NULL.
*/
protected function getEntityTargetFromHandler(ViewsHandlerInterface $handler): ?string {
if ($handler instanceof EntityReferenceArgument) {
return $handler->definition['target_entity_type_id'];
}
// Taxonomy arguments do not subclass EntityReferenceArgument and must be
// handled separately.
if (
$handler instanceof IndexTid ||
$handler instanceof IndexTidDepth ||
$handler instanceof IndexTidDepthModifier
) {
return 'taxonomy_term';
}
return NULL;
}
}
Loading