View source
<?php
namespace Drupal\entity_usage\Controller;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Database\Connection;
use Drupal\Core\Database\DatabaseExceptionWrapper;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityPublishedInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\entity_usage\EntityUsageInterface;
use Drupal\entity_usage\EntityUsageSourceLevel;
use Symfony\Component\DependencyInjection\ContainerInterface;
class ListUsageController extends ControllerBase {
const ITEMS_PER_GROUP_DEFAULT = 25;
protected $entityFieldManager;
protected $entityUsage;
protected $entityUsageConfig;
protected $database;
public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, EntityUsageInterface $entity_usage, ConfigFactoryInterface $config_factory, Connection $database) {
$this->entityTypeManager = $entity_type_manager;
$this->entityFieldManager = $entity_field_manager;
$this->entityUsage = $entity_usage;
$this->entityUsageConfig = $config_factory
->get('entity_usage.settings');
$this->database = $database;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('entity_type.manager'), $container
->get('entity_field.manager'), $container
->get('entity_usage.usage'), $container
->get('config.factory'), $container
->get('database'));
}
public function listUsagePage($entity_type, $entity_id) {
$target_has_hidden_usages = $this
->checkHiddenUsages($entity_type, $entity_id);
$items_per_group = $this->entityUsageConfig
->get('usage_controller_items_per_group') ?: self::ITEMS_PER_GROUP_DEFAULT;
$total = $this
->getPageRows($entity_type, $entity_id, NULL, NULL, TRUE);
$page = pager_default_initialize($total, $items_per_group);
$value_rows = $this
->getPageRows($entity_type, $entity_id, $page * $items_per_group, $items_per_group);
if (empty($value_rows)) {
if ($target_has_hidden_usages) {
$empty_message = $this
->t('There are no recorded usages for entity of type: @type with id: @id, but some usages were found in past versions (revisions) of some nodes.', [
'@type' => $entity_type,
'@id' => $entity_id,
]);
}
else {
$empty_message = $this
->t('There are no recorded usages for entity of type: @type with id: @id', [
'@type' => $entity_type,
'@id' => $entity_id,
]);
}
return [
'#markup' => $empty_message,
];
}
$header = [
$this
->t('Entity'),
$this
->t('Type'),
$this
->t('Language'),
$this
->t('Status'),
];
$entity_types = $this->entityTypeManager
->getDefinitions();
$languages = $this
->languageManager()
->getLanguages(LanguageInterface::STATE_ALL);
foreach ($value_rows as $row) {
$type_storage = $this->entityTypeManager
->getStorage($row['source_type']);
$source_entity = $type_storage
->load($row['source_id']);
if (!$source_entity) {
continue;
}
$source_link = $this
->getSourceEntityCanonicalLink($source_entity);
$lang_label = !empty($languages[$row['source_langcode']]) ? $languages[$row['source_langcode']]
->getName() : '-';
$published = '-';
if ($source_entity instanceof EntityPublishedInterface) {
$published = $source_entity
->isPublished() ? $this
->t('Published') : $this
->t('Unpublished');
}
$rows[] = [
$source_link,
$entity_types[$row['source_type']]
->getLabel(),
$lang_label,
$published,
];
}
$build[] = [
'#theme' => 'table',
'#rows' => $rows,
'#header' => $header,
];
$build[] = [
'#type' => 'pager',
];
if ($target_has_hidden_usages) {
$build[] = [
'#markup' => $this
->t('Note: This page only includes usages in the current revisions of referencing entities. This entity is also being used in nodes that no longer reference it on their current revision.'),
];
}
return $build;
}
protected function getPageRows($target_type, $target_id, $start, $items_per_page, $count_only = FALSE) {
$rows = [];
$top_level_types = EntityUsageSourceLevel::getTopLevelEntityTypes();
foreach ($top_level_types as $source_type) {
$source_definition = \Drupal::entityTypeManager()
->getDefinition($source_type);
$source_base_table = $source_definition
->getBaseTable();
$source_revision_key = $source_definition
->hasKey('revision') ? $source_definition
->getKey('revision') : NULL;
$query = $this->database
->select('entity_usage', 'eu')
->fields('eu', [
'source_id',
'source_id_string',
'source_langcode',
])
->orderBy('source_id', 'DESC')
->condition('target_type', $target_type)
->condition('target_id', $target_id);
if (!empty($source_base_table) && !empty($source_revision_key)) {
$query
->innerJoin($source_base_table, 'sbt', "sbt.{$source_revision_key} = eu.source_vid");
}
if ($count_only) {
return (int) $query
->countQuery()
->execute()
->fetchField();
}
$db_rows = $query
->range($start, $items_per_page)
->execute()
->fetchAll();
foreach ($db_rows as $db_row) {
$rows[] = [
'source_type' => $source_type,
'source_id' => $db_row->source_id ?? $db_row->source_id_string,
'source_langcode' => $db_row->source_langcode,
];
}
}
array_multisort(array_column($rows, 'source_type'), SORT_ASC, $rows);
array_multisort(array_column($rows, 'source_id'), SORT_DESC, $rows);
return $rows;
}
protected function checkHiddenUsages($target_type, $target_id) {
if (!$this
->moduleHandler()
->moduleExists('node') || !in_array('node', EntityUsageSourceLevel::getTopLevelEntityTypes())) {
return FALSE;
}
$query_string = "SELECT DISTINCT node.vid FROM {entity_usage}\n LEFT JOIN {node}\n ON entity_usage.source_id = node.nid\n WHERE entity_usage.source_vid NOT IN (SELECT node.vid FROM {node})\n AND entity_usage.target_type = :target_type\n AND entity_usage.target_id = :target_id";
try {
$result = $this->database
->query($query_string, [
':target_type' => $target_type,
':target_id' => $target_id,
])
->fetchField();
} catch (DatabaseExceptionWrapper $e) {
return FALSE;
}
return !empty($result);
}
protected function getSourceEntityCanonicalLink(EntityInterface $source_entity, $text = NULL) {
$entity_label = $source_entity
->access('view label') ? $source_entity
->label() : $this
->t('- Restricted access -');
if ($source_entity
->hasLinkTemplate('canonical') && $source_entity
->access('view')) {
return $source_entity
->toLink();
}
else {
return $entity_label;
}
}
public function checkAccess($entity_type, $entity_id) {
$entity = $this->entityTypeManager
->getStorage($entity_type)
->load($entity_id);
if (!$entity || !$entity
->access('view')) {
return AccessResult::forbidden();
}
return AccessResult::allowed();
}
public function getTitle($entity_type, $entity_id) {
$entity = $this->entityTypeManager
->getStorage($entity_type)
->load($entity_id);
if ($entity) {
return $this
->t('Entity usage information for %entity_label', [
'%entity_label' => $entity
->label(),
]);
}
return $this
->t('Entity Usage List');
}
}