Mercurial > hg > isophonics-drupal-site
diff core/modules/node/src/Controller/NodeController.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 1fec387a4317 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/node/src/Controller/NodeController.php Wed Nov 29 16:09:58 2017 +0000 @@ -0,0 +1,306 @@ +<?php + +namespace Drupal\node\Controller; + +use Drupal\Component\Utility\Xss; +use Drupal\Core\Controller\ControllerBase; +use Drupal\Core\Datetime\DateFormatterInterface; +use Drupal\Core\DependencyInjection\ContainerInjectionInterface; +use Drupal\Core\Render\RendererInterface; +use Drupal\Core\Url; +use Drupal\node\NodeStorageInterface; +use Drupal\node\NodeTypeInterface; +use Drupal\node\NodeInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Returns responses for Node routes. + */ +class NodeController extends ControllerBase implements ContainerInjectionInterface { + + /** + * The date formatter service. + * + * @var \Drupal\Core\Datetime\DateFormatterInterface + */ + protected $dateFormatter; + + /** + * The renderer service. + * + * @var \Drupal\Core\Render\RendererInterface + */ + protected $renderer; + + /** + * Constructs a NodeController object. + * + * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter + * The date formatter service. + * @param \Drupal\Core\Render\RendererInterface $renderer + * The renderer service. + */ + public function __construct(DateFormatterInterface $date_formatter, RendererInterface $renderer) { + $this->dateFormatter = $date_formatter; + $this->renderer = $renderer; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('date.formatter'), + $container->get('renderer') + ); + } + + /** + * Displays add content links for available content types. + * + * Redirects to node/add/[type] if only one content type is available. + * + * @return array|\Symfony\Component\HttpFoundation\RedirectResponse + * A render array for a list of the node types that can be added; however, + * if there is only one node type defined for the site, the function + * will return a RedirectResponse to the node add page for that one node + * type. + */ + public function addPage() { + $build = [ + '#theme' => 'node_add_list', + '#cache' => [ + 'tags' => $this->entityManager()->getDefinition('node_type')->getListCacheTags(), + ], + ]; + + $content = []; + + // Only use node types the user has access to. + foreach ($this->entityManager()->getStorage('node_type')->loadMultiple() as $type) { + $access = $this->entityManager()->getAccessControlHandler('node')->createAccess($type->id(), NULL, [], TRUE); + if ($access->isAllowed()) { + $content[$type->id()] = $type; + } + $this->renderer->addCacheableDependency($build, $access); + } + + // Bypass the node/add listing if only one content type is available. + if (count($content) == 1) { + $type = array_shift($content); + return $this->redirect('node.add', ['node_type' => $type->id()]); + } + + $build['#content'] = $content; + + return $build; + } + + /** + * Provides the node submission form. + * + * @param \Drupal\node\NodeTypeInterface $node_type + * The node type entity for the node. + * + * @return array + * A node submission form. + */ + public function add(NodeTypeInterface $node_type) { + $node = $this->entityManager()->getStorage('node')->create([ + 'type' => $node_type->id(), + ]); + + $form = $this->entityFormBuilder()->getForm($node); + + return $form; + } + + /** + * Displays a node revision. + * + * @param int $node_revision + * The node revision ID. + * + * @return array + * An array suitable for drupal_render(). + */ + public function revisionShow($node_revision) { + $node = $this->entityManager()->getStorage('node')->loadRevision($node_revision); + $node = $this->entityManager()->getTranslationFromContext($node); + $node_view_controller = new NodeViewController($this->entityManager, $this->renderer, $this->currentUser()); + $page = $node_view_controller->view($node); + unset($page['nodes'][$node->id()]['#cache']); + return $page; + } + + /** + * Page title callback for a node revision. + * + * @param int $node_revision + * The node revision ID. + * + * @return string + * The page title. + */ + public function revisionPageTitle($node_revision) { + $node = $this->entityManager()->getStorage('node')->loadRevision($node_revision); + return $this->t('Revision of %title from %date', ['%title' => $node->label(), '%date' => format_date($node->getRevisionCreationTime())]); + } + + /** + * Generates an overview table of older revisions of a node. + * + * @param \Drupal\node\NodeInterface $node + * A node object. + * + * @return array + * An array as expected by drupal_render(). + */ + public function revisionOverview(NodeInterface $node) { + $account = $this->currentUser(); + $langcode = $node->language()->getId(); + $langname = $node->language()->getName(); + $languages = $node->getTranslationLanguages(); + $has_translations = (count($languages) > 1); + $node_storage = $this->entityManager()->getStorage('node'); + $type = $node->getType(); + + $build['#title'] = $has_translations ? $this->t('@langname revisions for %title', ['@langname' => $langname, '%title' => $node->label()]) : $this->t('Revisions for %title', ['%title' => $node->label()]); + $header = [$this->t('Revision'), $this->t('Operations')]; + + $revert_permission = (($account->hasPermission("revert $type revisions") || $account->hasPermission('revert all revisions') || $account->hasPermission('administer nodes')) && $node->access('update')); + $delete_permission = (($account->hasPermission("delete $type revisions") || $account->hasPermission('delete all revisions') || $account->hasPermission('administer nodes')) && $node->access('delete')); + + $rows = []; + $default_revision = $node->getRevisionId(); + + foreach ($this->getRevisionIds($node, $node_storage) as $vid) { + /** @var \Drupal\node\NodeInterface $revision */ + $revision = $node_storage->loadRevision($vid); + // Only show revisions that are affected by the language that is being + // displayed. + if ($revision->hasTranslation($langcode) && $revision->getTranslation($langcode)->isRevisionTranslationAffected()) { + $username = [ + '#theme' => 'username', + '#account' => $revision->getRevisionUser(), + ]; + + // Use revision link to link to revisions that are not active. + $date = $this->dateFormatter->format($revision->revision_timestamp->value, 'short'); + if ($vid != $node->getRevisionId()) { + $link = $this->l($date, new Url('entity.node.revision', ['node' => $node->id(), 'node_revision' => $vid])); + } + else { + $link = $node->link($date); + } + + $row = []; + $column = [ + 'data' => [ + '#type' => 'inline_template', + '#template' => '{% trans %}{{ date }} by {{ username }}{% endtrans %}{% if message %}<p class="revision-log">{{ message }}</p>{% endif %}', + '#context' => [ + 'date' => $link, + 'username' => $this->renderer->renderPlain($username), + 'message' => ['#markup' => $revision->revision_log->value, '#allowed_tags' => Xss::getHtmlTagList()], + ], + ], + ]; + // @todo Simplify once https://www.drupal.org/node/2334319 lands. + $this->renderer->addCacheableDependency($column['data'], $username); + $row[] = $column; + + if ($vid == $default_revision) { + $row[] = [ + 'data' => [ + '#prefix' => '<em>', + '#markup' => $this->t('Current revision'), + '#suffix' => '</em>', + ], + ]; + + $rows[] = [ + 'data' => $row, + 'class' => ['revision-current'], + ]; + } + else { + $links = []; + if ($revert_permission) { + $links['revert'] = [ + 'title' => $vid < $node->getRevisionId() ? $this->t('Revert') : $this->t('Set as current revision'), + 'url' => $has_translations ? + Url::fromRoute('node.revision_revert_translation_confirm', ['node' => $node->id(), 'node_revision' => $vid, 'langcode' => $langcode]) : + Url::fromRoute('node.revision_revert_confirm', ['node' => $node->id(), 'node_revision' => $vid]), + ]; + } + + if ($delete_permission) { + $links['delete'] = [ + 'title' => $this->t('Delete'), + 'url' => Url::fromRoute('node.revision_delete_confirm', ['node' => $node->id(), 'node_revision' => $vid]), + ]; + } + + $row[] = [ + 'data' => [ + '#type' => 'operations', + '#links' => $links, + ], + ]; + + $rows[] = $row; + } + } + } + + $build['node_revisions_table'] = [ + '#theme' => 'table', + '#rows' => $rows, + '#header' => $header, + '#attached' => [ + 'library' => ['node/drupal.node.admin'], + ], + '#attributes' => ['class' => 'node-revision-table'], + ]; + + $build['pager'] = ['#type' => 'pager']; + + return $build; + } + + /** + * The _title_callback for the node.add route. + * + * @param \Drupal\node\NodeTypeInterface $node_type + * The current node. + * + * @return string + * The page title. + */ + public function addPageTitle(NodeTypeInterface $node_type) { + return $this->t('Create @name', ['@name' => $node_type->label()]); + } + + /** + * Gets a list of node revision IDs for a specific node. + * + * @param \Drupal\node\NodeInterface $node + * The node entity. + * @param \Drupal\node\NodeStorageInterface $node_storage + * The node storage handler. + * + * @return int[] + * Node revision IDs (in descending order). + */ + protected function getRevisionIds(NodeInterface $node, NodeStorageInterface $node_storage) { + $result = $node_storage->getQuery() + ->allRevisions() + ->condition($node->getEntityType()->getKey('id'), $node->id()) + ->sort($node->getEntityType()->getKey('revision'), 'DESC') + ->pager(50) + ->execute(); + return array_keys($result); + } + +}