diff --git a/core/modules/book/book.routing.yml b/core/modules/book/book.routing.yml index 0b0f2a6..69ba077 100644 --- a/core/modules/book/book.routing.yml +++ b/core/modules/book/book.routing.yml @@ -23,6 +23,8 @@ book_export: pattern: '/book/export/{type}/{node}' defaults: _content: '\Drupal\book\Controller\BookController::bookExport' + options: + _access_mode: 'ALL' requirements: _permission: 'access printer-friendly version' _entity_access: 'node.view' diff --git a/core/modules/book/lib/Drupal/book/BookExport.php b/core/modules/book/lib/Drupal/book/BookExport.php index 39117bd..8b367f7 100644 --- a/core/modules/book/lib/Drupal/book/BookExport.php +++ b/core/modules/book/lib/Drupal/book/BookExport.php @@ -59,7 +59,9 @@ public function __construct(EntityManager $entityManager) { * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException * Thrown when the node was not attached to a book. * - * @return string A string containing HTML representing the node and its children in + * @return array + * A render array representing the HTML for a node and its children in the + * book hierarchy. */ public function bookExportHtml(NodeInterface $node) { if (!isset($node->book)) { @@ -117,10 +119,10 @@ protected function exportTraverse(array $tree, $callable) { * (optional) All the rendered child nodes within the current node. Defaults * to an empty string. * - * @return string - * The HTML generated for the given node. + * @return array + * A render array for the exported HTML of a given node. * - * @see book_export_traverse() + * @see \Drupal\book\BookExport::exportTraverse() */ protected function bookNodeExport(NodeInterface $node, $children = '') { $build = $this->nodeRender->view($node, 'print', NULL); diff --git a/core/modules/book/lib/Drupal/book/Controller/BookController.php b/core/modules/book/lib/Drupal/book/Controller/BookController.php index 2c5248c..63ab802 100644 --- a/core/modules/book/lib/Drupal/book/Controller/BookController.php +++ b/core/modules/book/lib/Drupal/book/Controller/BookController.php @@ -1,4 +1,5 @@ get('book.manager'), $container->get('book.export')); - } - - /** * Constructs a BookController object. + * + * @param \Drupal\book\BookManager $bookManager + * The book manager. + * @param \Drupal\book\BookExport $bookExport + * The book export service. */ public function __construct(BookManager $bookManager, BookExport $bookExport) { $this->bookManager = $bookManager; @@ -51,6 +48,16 @@ public function __construct(BookManager $bookManager, BookExport $bookExport) { } /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('book.manager'), + $container->get('book.export') + ); + } + + /** * Returns an administrative overview of all books. * * @return string @@ -61,7 +68,6 @@ public function adminOverview() { $rows = array(); $headers = array(t('Book'), t('Operations')); - // Add any recognized books to the table list. foreach ($this->bookManager->getAllBooks() as $book) { $row = array( @@ -80,8 +86,12 @@ public function adminOverview() { ); $rows[] = $row; } - $table = array('#theme' => 'table', '#header' => $headers, '#rows' => $rows, '#empty' => t('No books available.')); - return drupal_render($table); + return array( + '#theme' => 'table', + '#header' => $headers, + '#rows' => $rows, + '#empty' => t('No books available.'), + ); } /** @@ -95,17 +105,19 @@ public function bookRender() { foreach ($this->bookManager->getAllBooks() as $book) { $book_list[] = l($book['title'], $book['href'], $book['options']); } - $item_list = array('#theme' => 'item_list' , '#items' => $book_list); - return drupal_render($item_list); + return array( + '#theme' => 'item_list', + '#items' => $book_list, + ); } /** * Generates representations of a book page and its children. * - * The function delegates the generation of output to helper functions. The - * function name is derived by prepending 'book_export_' to the given output - * type. So, e.g., a type of 'html' results in a call to the function - * book_export_html(). + * The method delegates the generation of output to helper methods. The method + * name is derived by prepending 'bookExport' to the camelized form of given + * output type. For example, a type of 'html' results in a call to the method + * bookExportHtml(). * * @param string $type * A string encoding the type of output requested. The following types are @@ -115,24 +127,22 @@ public function bookRender() { * @param \Drupal\node\NodeInterface $node * The node to export. * - * @return \Symfony\Component\HttpFoundation\Response - * A string representing the node and its children in the book hierarchy in a - * format determined by the $type parameter. + * @return array + * A render array representing the node and its children in the book + * hierarchy in a format determined by the $type parameter. * * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ public function bookExport($type, NodeInterface $node) { - $type = Unicode::strtolower($type); + $method = 'bookExport' . Container::camelize($type); // @todo Convert the custom export functionality to serializer. - $book_export_service = $this->bookExport; - $method = 'bookExport' . $type; - if (!method_exists($book_export_service, $method)) { + if (!method_exists($this->bookExport, $method)) { drupal_set_message(t('Unknown export format.')); throw new NotFoundHttpException(); } - return new Response($book_export_service->{$method}($node)); + return $this->bookExport->{$method}($node); } } diff --git a/core/modules/node/lib/Drupal/node/NodeBCDecorator.php b/core/modules/node/lib/Drupal/node/NodeBCDecorator.php index 77694fc..885a546 100644 --- a/core/modules/node/lib/Drupal/node/NodeBCDecorator.php +++ b/core/modules/node/lib/Drupal/node/NodeBCDecorator.php @@ -15,6 +15,13 @@ class NodeBCDecorator extends EntityBCDecorator implements NodeInterface { /** + * The NodeInterface object being decorated. + * + * @var \Drupal\node\NodeInterface + */ + protected $decorated; + + /** * {@inheritdoc} */ public function setTitle($title) { @@ -132,4 +139,11 @@ public function setRevisionAuthorId($uid) { return $this->decorated->setRevisionAuthorId($uid); } + /** + * {@inheritdoc} + */ + public function prepareLangcode() { + return $this->decorated->prepareLangcode(); + } + } diff --git a/core/modules/node/lib/Drupal/node/NodeInterface.php b/core/modules/node/lib/Drupal/node/NodeInterface.php index 61e60a5..ffb9144 100644 --- a/core/modules/node/lib/Drupal/node/NodeInterface.php +++ b/core/modules/node/lib/Drupal/node/NodeInterface.php @@ -177,4 +177,12 @@ public function getRevisionAuthor(); */ public function setRevisionAuthorId($uid); + /** + * Prepares the langcode for a node. + * + * @return string + * The langcode for this node. + */ + public function prepareLangcode(); + } diff --git a/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php index 6572ba9..a3cda94 100644 --- a/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php +++ b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php @@ -11,6 +11,8 @@ use Drupal\Core\Entity\EntityStorageControllerInterface; use Drupal\Core\Entity\Annotation\EntityType; use Drupal\Core\Annotation\Translation; +use Drupal\Core\Language\Language; +use Drupal\Core\Session\AccountInterface; use Drupal\node\NodeInterface; use Drupal\node\NodeBCDecorator; @@ -145,6 +147,39 @@ public static function preDelete(EntityStorageControllerInterface $storage_contr /** * {@inheritdoc} */ + public function access($operation = 'view', AccountInterface $account = NULL) { + if ($operation == 'create') { + return parent::access($operation, $account); + } + + return \Drupal::entityManager() + ->getAccessController($this->entityType) + ->access($this, $operation, $this->prepareLangcode(), $account); + } + + /** + * {@inheritdoc} + */ + public function prepareLangcode() { + $langcode = $this->language()->id; + // If the Language module is enabled, try to use the language from content + // negotiation. + if (\Drupal::moduleHandler()->moduleExists('language')) { + // Load languages the node exists in. + $node_translations = $this->getTranslationLanguages(); + // Load the language from content negotiation. + $content_negotiation_langcode = \Drupal::languageManager()->getLanguage(Language::TYPE_CONTENT)->id; + // If there is a translation available, use it. + if (isset($node_translations[$content_negotiation_langcode])) { + $langcode = $content_negotiation_langcode; + } + } + return $langcode; + } + + /** + * {@inheritdoc} + */ public function setTitle($title) { $this->set('title', $title); return $this; diff --git a/core/modules/node/node.module b/core/modules/node/node.module index 5a6d53a..5c53b54 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -2045,19 +2045,7 @@ function node_access($op, $node, $account = NULL, $langcode = NULL) { // If no language code was provided, default to the node's langcode. if (empty($langcode)) { - $langcode = $node->language()->id; - // If the Language module is enabled, try to use the language from content - // negotiation. - if (module_exists('language')) { - // Load languages the node exists in. - $node_translations = $node->getTranslationLanguages(); - // Load the language from content negotiation. - $content_negotiation_langcode = language(Language::TYPE_CONTENT)->id; - // If there is a translation available, use it. - if (isset($node_translations[$content_negotiation_langcode])) { - $langcode = $content_negotiation_langcode; - } - } + $langcode = $node->prepareLangcode(); } return $access_controller->access($node, $op, $langcode, $account); }