class NodeController

Same name in other branches
  1. 7.x modules/node/node.module \NodeController
  2. 9 core/modules/node/src/Controller/NodeController.php \Drupal\node\Controller\NodeController
  3. 10 core/modules/node/src/Controller/NodeController.php \Drupal\node\Controller\NodeController
  4. 11.x core/modules/node/src/Controller/NodeController.php \Drupal\node\Controller\NodeController

Returns responses for Node routes.

Hierarchy

Expanded class hierarchy of NodeController

File

core/modules/node/src/Controller/NodeController.php, line 21

Namespace

Drupal\node\Controller
View source
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;
    
    /**
     * The entity repository service.
     *
     * @var \Drupal\Core\Entity\EntityRepositoryInterface
     */
    protected $entityRepository;
    
    /**
     * Constructs a NodeController object.
     *
     * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
     *   The date formatter service.
     * @param \Drupal\Core\Render\RendererInterface $renderer
     *   The renderer service.
     * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
     *   The entity repository.
     */
    public function __construct(DateFormatterInterface $date_formatter, RendererInterface $renderer, EntityRepositoryInterface $entity_repository = NULL) {
        $this->dateFormatter = $date_formatter;
        $this->renderer = $renderer;
        if (!$entity_repository) {
            @trigger_error('The entity.repository service must be passed to NodeController::__construct(), it is required before Drupal 9.0.0. See https://www.drupal.org/node/2549139.', E_USER_DEPRECATED);
            $entity_repository = \Drupal::service('entity.repository');
        }
        $this->entityRepository = $entity_repository;
    }
    
    /**
     * {@inheritdoc}
     */
    public static function create(ContainerInterface $container) {
        return new static($container->get('date.formatter'), $container->get('renderer'), $container->get('entity.repository'));
    }
    
    /**
     * 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->entityTypeManager()
                    ->getDefinition('node_type')
                    ->getListCacheTags(),
            ],
        ];
        $content = [];
        // Only use node types the user has access to.
        foreach ($this->entityTypeManager()
            ->getStorage('node_type')
            ->loadMultiple() as $type) {
            $access = $this->entityTypeManager()
                ->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.
     *
     * @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Define
     *   entity form routes through the _entity_form instead through the
     *   _controller directive.
     */
    public function add(NodeTypeInterface $node_type) {
        @trigger_error(__METHOD__ . ' is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Define entity form routes through the _entity_form instead through the _controller directive. See https://www.drupal.org/node/3084856', E_USER_DEPRECATED);
        $node = $this->entityTypeManager()
            ->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\Core\Render\RendererInterface::render().
     */
    public function revisionShow($node_revision) {
        $node = $this->entityTypeManager()
            ->getStorage('node')
            ->loadRevision($node_revision);
        $node = $this->entityRepository
            ->getTranslationFromContext($node);
        $node_view_controller = new NodeViewController($this->entityTypeManager(), $this->renderer, $this->currentUser(), $this->entityRepository);
        $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->entityTypeManager()
            ->getStorage('node')
            ->loadRevision($node_revision);
        return $this->t('Revision of %title from %date', [
            '%title' => $node->label(),
            '%date' => $this->dateFormatter
                ->format($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\Core\Render\RendererInterface::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->entityTypeManager()
            ->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();
        $current_revision_displayed = FALSE;
        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');
                // We treat also the latest translation-affecting revision as current
                // revision, if it was the default revision, as its values for the
                // current language will be the same of the current default revision in
                // this case.
                $is_current_revision = $vid == $default_revision || !$current_revision_displayed && $revision->wasDefaultRevision();
                if (!$is_current_revision) {
                    $link = Link::fromTextAndUrl($date, new Url('entity.node.revision', [
                        'node' => $node->id(),
                        'node_revision' => $vid,
                    ]))
                        ->toString();
                }
                else {
                    $link = $node->toLink($date)
                        ->toString();
                    $current_revision_displayed = TRUE;
                }
                $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 ($is_current_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);
    }

}

Members

Title Sort descending Deprecated Modifiers Object type Summary Overriden Title Overrides
ControllerBase::$configFactory protected property The configuration factory.
ControllerBase::$currentUser protected property The current user service. 1
ControllerBase::$entityFormBuilder protected property The entity form builder.
ControllerBase::$entityManager protected property The entity manager.
ControllerBase::$entityTypeManager protected property The entity type manager.
ControllerBase::$formBuilder protected property The form builder. 2
ControllerBase::$keyValue protected property The key-value storage. 1
ControllerBase::$languageManager protected property The language manager. 1
ControllerBase::$moduleHandler protected property The module handler. 2
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. 1
ControllerBase::entityFormBuilder protected function Retrieves the entity form builder.
ControllerBase::entityManager Deprecated protected function Retrieves the entity manager service.
ControllerBase::entityTypeManager protected function Retrieves the entity type manager.
ControllerBase::formBuilder protected function Returns the form builder service. 2
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. 2
ControllerBase::redirect protected function Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait::redirect
ControllerBase::state protected function Returns the state storage service.
LinkGeneratorTrait::$linkGenerator protected property The link generator. 1
LinkGeneratorTrait::getLinkGenerator Deprecated protected function Returns the link generator.
LinkGeneratorTrait::l Deprecated protected function Renders a link to a route given a route name and its parameters.
LinkGeneratorTrait::setLinkGenerator Deprecated public function Sets the link generator 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. 17
MessengerTrait::messenger public function Gets the messenger. 17
MessengerTrait::setMessenger public function Sets the messenger.
NodeController::$dateFormatter protected property The date formatter service.
NodeController::$entityRepository protected property The entity repository service.
NodeController::$renderer protected property The renderer service.
NodeController::add Deprecated public function Provides the node submission form.
NodeController::addPage public function Displays add content links for available content types.
NodeController::addPageTitle public function The _title_callback for the node.add route.
NodeController::create public static function Instantiates a new instance of this class. Overrides ControllerBase::create
NodeController::getRevisionIds protected function Gets a list of node revision IDs for a specific node.
NodeController::revisionOverview public function Generates an overview table of older revisions of a node.
NodeController::revisionPageTitle public function Page title callback for a node revision.
NodeController::revisionShow public function Displays a node revision.
NodeController::__construct public function Constructs a NodeController object.
RedirectDestinationTrait::$redirectDestination protected property The redirect destination service. 1
RedirectDestinationTrait::getDestinationArray protected function Prepares a &#039;destination&#039; 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.
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.
UrlGeneratorTrait::$urlGenerator protected property The url generator.
UrlGeneratorTrait::getUrlGenerator Deprecated protected function Returns the URL generator service.
UrlGeneratorTrait::setUrlGenerator Deprecated public function Sets the URL generator service.
UrlGeneratorTrait::url Deprecated protected function Generates a URL or path for a specific route based on the given parameters.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.