class VersionHistoryController
Same name in other branches
- 11.x core/lib/Drupal/Core/Entity/Controller/VersionHistoryController.php \Drupal\Core\Entity\Controller\VersionHistoryController
Provides a controller showing revision history for an entity.
This controller is agnostic to any entity type by using \Drupal\Core\Entity\RevisionLogInterface.
Hierarchy
- class \Drupal\Core\Controller\ControllerBase implements \Drupal\Core\DependencyInjection\ContainerInjectionInterface uses \Drupal\Core\DependencyInjection\AutowireTrait, \Drupal\Core\Logger\LoggerChannelTrait, \Drupal\Core\Messenger\MessengerTrait, \Drupal\Core\Routing\RedirectDestinationTrait, \Drupal\Core\StringTranslation\StringTranslationTrait
- class \Drupal\Core\Entity\Controller\VersionHistoryController extends \Drupal\Core\Controller\ControllerBase
Expanded class hierarchy of VersionHistoryController
2 files declare their use of VersionHistoryController
- RevisionHtmlRouteProvider.php in core/
lib/ Drupal/ Core/ Entity/ Routing/ RevisionHtmlRouteProvider.php - RevisionVersionHistoryTest.php in core/
tests/ Drupal/ FunctionalTests/ Entity/ RevisionVersionHistoryTest.php
File
-
core/
lib/ Drupal/ Core/ Entity/ Controller/ VersionHistoryController.php, line 26
Namespace
Drupal\Core\Entity\ControllerView source
class VersionHistoryController extends ControllerBase {
const REVISIONS_PER_PAGE = 50;
/**
* Constructs a new VersionHistoryController.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
* @param \Drupal\Core\Language\LanguageManagerInterface $languageManager
* The language manager.
* @param \Drupal\Core\Datetime\DateFormatterInterface $dateFormatter
* The date formatter service.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer.
*/
public function __construct(EntityTypeManagerInterface $entityTypeManager, LanguageManagerInterface $languageManager, DateFormatterInterface $dateFormatter, RendererInterface $renderer) {
$this->entityTypeManager = $entityTypeManager;
$this->languageManager = $languageManager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container->get('entity_type.manager'), $container->get('language_manager'), $container->get('date.formatter'), $container->get('renderer'));
}
/**
* Generates an overview table of revisions for an entity.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $routeMatch
* The route match.
*
* @return array
* A render array.
*/
public function __invoke(RouteMatchInterface $routeMatch) : array {
$entityTypeId = $routeMatch->getRouteObject()
->getOption('entity_type_id');
$entity = $routeMatch->getParameter($entityTypeId);
return $this->revisionOverview($entity);
}
/**
* Builds a link to revert an entity revision.
*
* @param \Drupal\Core\Entity\RevisionableInterface $revision
* The entity to build a revert revision link for.
*
* @return array|null
* A link to revert an entity revision, or NULL if the entity type does not
* have an a route to revert an entity revision.
*/
protected function buildRevertRevisionLink(RevisionableInterface $revision) : ?array {
if (!$revision->hasLinkTemplate('revision-revert-form')) {
return NULL;
}
$url = $revision->toUrl('revision-revert-form');
// @todo Merge in cacheability after
// https://www.drupal.org/project/drupal/issues/2473873.
if (!$url->access()) {
return NULL;
}
return [
'title' => $this->t('Revert'),
'url' => $url,
];
}
/**
* Builds a link to delete an entity revision.
*
* @param \Drupal\Core\Entity\RevisionableInterface $revision
* The entity to build a delete revision link for.
*
* @return array|null
* A link render array.
*/
protected function buildDeleteRevisionLink(RevisionableInterface $revision) : ?array {
if (!$revision->hasLinkTemplate('revision-delete-form')) {
return NULL;
}
$url = $revision->toUrl('revision-delete-form');
// @todo Merge in cacheability after
// https://www.drupal.org/project/drupal/issues/2473873.
if (!$url->access()) {
return NULL;
}
return [
'title' => $this->t('Delete'),
'url' => $url,
];
}
/**
* Get a description of the revision.
*
* @param \Drupal\Core\Entity\RevisionableInterface $revision
* The entity revision.
*
* @return array
* A render array describing the revision.
*/
protected function getRevisionDescription(RevisionableInterface $revision) : array {
$context = [];
if ($revision instanceof RevisionLogInterface) {
// Use revision link to link to revisions that are not active.
[
'type' => $dateFormatType,
'format' => $dateFormatFormat,
] = $this->getRevisionDescriptionDateFormat($revision);
$linkText = $this->dateFormatter
->format($revision->getRevisionCreationTime(), $dateFormatType, $dateFormatFormat);
// @todo Simplify this when https://www.drupal.org/node/2334319 lands.
$username = [
'#theme' => 'username',
'#account' => $revision->getRevisionUser(),
];
$context['username'] = $this->renderer
->render($username);
}
else {
$linkText = $revision->access('view label') ? $revision->label() : $this->t('- Restricted access -');
}
$url = $revision->hasLinkTemplate('revision') ? $revision->toUrl('revision') : NULL;
$context['revision'] = $url && $url->access() ? Link::fromTextAndUrl($linkText, $url)->toString() : (string) $linkText;
$context['message'] = $revision instanceof RevisionLogInterface ? [
'#markup' => $revision->getRevisionLogMessage(),
'#allowed_tags' => Xss::getHtmlTagList(),
] : '';
return [
'data' => [
'#type' => 'inline_template',
'#template' => isset($context['username']) ? '{% trans %} {{ revision }} by {{ username }}{% endtrans %}{% if message %}<p class="revision-log">{{ message }}</p>{% endif %}' : '{% trans %} {{ revision }} {% endtrans %}{% if message %}<p class="revision-log">{{ message }}</p>{% endif %}',
'#context' => $context,
],
];
}
/**
* Date format to use for revision description dates.
*
* @param \Drupal\Core\Entity\RevisionableInterface $revision
* The revision in context.
*
* @return array
* An array with keys 'type' and optionally 'format' suitable for passing
* to date formatter service.
*/
protected function getRevisionDescriptionDateFormat(RevisionableInterface $revision) : array {
return [
'type' => 'short',
'format' => '',
];
}
/**
* Generates revisions of an entity relevant to the current language.
*
* @param \Drupal\Core\Entity\RevisionableInterface $entity
* The entity.
*
* @return \Generator|\Drupal\Core\Entity\RevisionableInterface
* Generates revisions.
*/
protected function loadRevisions(RevisionableInterface $entity) {
$entityType = $entity->getEntityType();
$translatable = $entityType->isTranslatable();
$entityStorage = $this->entityTypeManager
->getStorage($entity->getEntityTypeId());
assert($entityStorage instanceof RevisionableStorageInterface);
$result = $entityStorage->getQuery()
->accessCheck(FALSE)
->allRevisions()
->condition($entityType->getKey('id'), $entity->id())
->sort($entityType->getKey('revision'), 'DESC')
->pager(self::REVISIONS_PER_PAGE)
->execute();
$currentLangcode = $this->languageManager
->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)
->getId();
foreach ($entityStorage->loadMultipleRevisions(array_keys($result)) as $revision) {
// Only show revisions that are affected by the language that is being
// displayed.
if (!$translatable || $revision->hasTranslation($currentLangcode) && $revision->getTranslation($currentLangcode)
->isRevisionTranslationAffected()) {
(yield $translatable ? $revision->getTranslation($currentLangcode) : $revision);
}
}
}
/**
* Generates an overview table of revisions of an entity.
*
* @param \Drupal\Core\Entity\RevisionableInterface $entity
* A revisionable entity.
*
* @return array
* A render array.
*/
protected function revisionOverview(RevisionableInterface $entity) : array {
$build['entity_revisions_table'] = [
'#theme' => 'table',
'#header' => [
'revision' => [
'data' => $this->t('Revision'),
],
'operations' => [
'data' => $this->t('Operations'),
],
],
];
foreach ($this->loadRevisions($entity) as $revision) {
$build['entity_revisions_table']['#rows'][$revision->getRevisionId()] = $this->buildRow($revision);
}
$build['pager'] = [
'#type' => 'pager',
];
(new CacheableMetadata())->addCacheableDependency($entity)
->addCacheContexts([
'languages:language_content',
])
->applyTo($build);
return $build;
}
/**
* Builds a table row for a revision.
*
* @param \Drupal\Core\Entity\RevisionableInterface $revision
* An entity revision.
*
* @return array
* A table row.
*/
protected function buildRow(RevisionableInterface $revision) : array {
$row = [];
$rowAttributes = [];
$row['revision']['data'] = $this->getRevisionDescription($revision);
$row['operations']['data'] = [];
// Revision status.
if ($revision->isDefaultRevision()) {
$rowAttributes['class'][] = 'revision-current';
$row['operations']['data']['status']['#markup'] = $this->t('<em>Current revision</em>');
}
// Operation links.
$links = $this->getOperationLinks($revision);
if (count($links) > 0) {
$row['operations']['data']['operations'] = [
'#type' => 'operations',
'#links' => $links,
];
}
return [
'data' => $row,
] + $rowAttributes;
}
/**
* Get operations for an entity revision.
*
* @param \Drupal\Core\Entity\RevisionableInterface $revision
* The entity to build revision links for.
*
* @return array
* An array of operation links.
*/
protected function getOperationLinks(RevisionableInterface $revision) : array {
// Removes links which are inaccessible or not rendered.
return array_filter([
$this->buildRevertRevisionLink($revision),
$this->buildDeleteRevisionLink($revision),
]);
}
}
Members
Title Sort descending | Modifiers | Object type | Summary | Overriden Title | Overrides |
---|---|---|---|---|---|
ControllerBase::$configFactory | protected | property | The configuration factory. | ||
ControllerBase::$currentUser | protected | property | The current user service. | 2 | |
ControllerBase::$entityFormBuilder | protected | property | The entity form builder. | ||
ControllerBase::$entityTypeManager | protected | property | The entity type manager. | ||
ControllerBase::$formBuilder | protected | property | The form builder. | 1 | |
ControllerBase::$keyValue | protected | property | The key-value storage. | 1 | |
ControllerBase::$languageManager | protected | property | The language manager. | 1 | |
ControllerBase::$moduleHandler | protected | property | The module handler. | 1 | |
ControllerBase::$stateService | protected | property | The state service. | ||
ControllerBase::cache | protected | function | Returns the requested cache bin. | ||
ControllerBase::config | protected | function | Retrieves a configuration object. | ||
ControllerBase::container | private | function | Returns the service container. | ||
ControllerBase::currentUser | protected | function | Returns the current user. | 2 | |
ControllerBase::entityFormBuilder | protected | function | Retrieves the entity form builder. | ||
ControllerBase::entityTypeManager | protected | function | Retrieves the entity type manager. | ||
ControllerBase::formBuilder | protected | function | Returns the form builder service. | 1 | |
ControllerBase::keyValue | protected | function | Returns a key/value storage collection. | 1 | |
ControllerBase::languageManager | protected | function | Returns the language manager service. | 1 | |
ControllerBase::moduleHandler | protected | function | Returns the module handler. | 1 | |
ControllerBase::redirect | protected | function | Returns a redirect response object for the specified route. | ||
ControllerBase::state | protected | function | Returns the state storage service. | ||
LoggerChannelTrait::$loggerFactory | protected | property | The logger channel factory service. | ||
LoggerChannelTrait::getLogger | protected | function | Gets the logger for a specific channel. | ||
LoggerChannelTrait::setLoggerFactory | public | function | Injects the logger channel factory. | ||
MessengerTrait::$messenger | protected | property | The messenger. | 16 | |
MessengerTrait::messenger | public | function | Gets the messenger. | 16 | |
MessengerTrait::setMessenger | public | function | Sets the messenger. | ||
RedirectDestinationTrait::$redirectDestination | protected | property | The redirect destination service. | 2 | |
RedirectDestinationTrait::getDestinationArray | protected | function | Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url. | ||
RedirectDestinationTrait::getRedirectDestination | protected | function | Returns the redirect destination service. | ||
RedirectDestinationTrait::setRedirectDestination | public | function | Sets the redirect destination service. | ||
StringTranslationTrait::$stringTranslation | protected | property | The string translation service. | 3 | |
StringTranslationTrait::formatPlural | protected | function | Formats a string containing a count of items. | ||
StringTranslationTrait::getNumberOfPlurals | protected | function | Returns the number of plurals supported by a given language. | ||
StringTranslationTrait::getStringTranslation | protected | function | Gets the string translation service. | ||
StringTranslationTrait::setStringTranslation | public | function | Sets the string translation service to use. | 2 | |
StringTranslationTrait::t | protected | function | Translates a string to the current language or to a given language. | ||
VersionHistoryController::buildDeleteRevisionLink | protected | function | Builds a link to delete an entity revision. | ||
VersionHistoryController::buildRevertRevisionLink | protected | function | Builds a link to revert an entity revision. | ||
VersionHistoryController::buildRow | protected | function | Builds a table row for a revision. | ||
VersionHistoryController::create | public static | function | Instantiates a new instance of the implementing class using autowiring. | Overrides AutowireTrait::create | |
VersionHistoryController::getOperationLinks | protected | function | Get operations for an entity revision. | ||
VersionHistoryController::getRevisionDescription | protected | function | Get a description of the revision. | ||
VersionHistoryController::getRevisionDescriptionDateFormat | protected | function | Date format to use for revision description dates. | ||
VersionHistoryController::loadRevisions | protected | function | Generates revisions of an entity relevant to the current language. | ||
VersionHistoryController::revisionOverview | protected | function | Generates an overview table of revisions of an entity. | ||
VersionHistoryController::REVISIONS_PER_PAGE | constant | ||||
VersionHistoryController::__construct | public | function | Constructs a new VersionHistoryController. | ||
VersionHistoryController::__invoke | public | function | Generates an overview table of revisions for an entity. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.