diff --git a/core/modules/book/book.module b/core/modules/book/book.module
index e113661..8bdfcfc 100644
--- a/core/modules/book/book.module
+++ b/core/modules/book/book.module
@@ -187,14 +187,6 @@ function book_menu() {
'route_name' => 'book_render',
'type' => MENU_SUGGESTED_ITEM,
);
- $items['book/export/%/%node'] = array(
- 'page callback' => 'book_export',
- 'page arguments' => array(2, 3),
- 'access callback' => 'book_export_access',
- 'access arguments' => array(3),
- 'type' => MENU_CALLBACK,
- 'file' => 'book.pages.inc',
- );
$items['node/%node/outline'] = array(
'title' => 'Outline',
'page callback' => 'book_outline',
@@ -218,16 +210,6 @@ function book_menu() {
}
/**
- * Access callback: Determines if the book export page is accessible.
- *
- * @param \Drupal\node\Plugin\Core\Entity\EntityInterface $node
- * The node whose export page is to be viewed.
- */
-function book_export_access(EntityInterface $node) {
- return user_access('access printer-friendly version') && node_access('view', $node);
-}
-
-/**
* Access callback: Determines if the outline tab is accessible.
*
* Path:
@@ -1135,45 +1117,6 @@ function template_preprocess_book_export_html(&$variables) {
}
/**
- * Traverses the book tree to build printable or exportable output.
- *
- * During the traversal, the $visit_func() callback is applied to each node and
- * is called recursively for each child of the node (in weight, title order).
- *
- * @param $tree
- * A subtree of the book menu hierarchy, rooted at the current page.
- * @param $visit_func
- * A function callback to be called upon visiting a node in the tree.
- *
- * @return
- * The output generated in visiting each node.
- */
-function book_export_traverse($tree, $visit_func) {
- $output = '';
-
- foreach ($tree as $data) {
- // Note- access checking is already performed when building the tree.
- if ($node = node_load($data['link']['nid'])) {
- $children = '';
-
- if ($data['below']) {
- $children = book_export_traverse($data['below'], $visit_func);
- }
-
- if (!empty($visit_func)) {
- $output .= call_user_func($visit_func, $node, $children);
- }
- else {
- // Use the default function.
- $output .= book_node_export($node, $children);
- }
- }
- }
-
- return $output;
-}
-
-/**
* Generates printer-friendly HTML for a node.
*
* @param \Drupal\Core\Entity\EntityInterface $node
diff --git a/core/modules/book/book.pages.inc b/core/modules/book/book.pages.inc
index 4cd7e25..d05a855 100644
--- a/core/modules/book/book.pages.inc
+++ b/core/modules/book/book.pages.inc
@@ -10,81 +10,6 @@
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
- * Page callback: 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().
- *
- * @param $type
- * A string encoding the type of output requested. The following types are
- * currently supported in book module:
- * - html: Printer-friendly HTML.
- * Other types may be supported in contributed modules.
- * @param \Drupal\node\Plugin\Core\Entity\EntityInterface $node
- * The node to export.
- *
- * @return
- * A string representing the node and its children in the book hierarchy in a
- * format determined by the $type parameter.
- *
- * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
- *
- * @see book_menu()
- */
-function book_export($type, EntityInterface $node) {
- $type = drupal_strtolower($type);
-
- $export_function = 'book_export_' . $type;
-
- if (function_exists($export_function)) {
- print call_user_func($export_function, $node);
- }
- else {
- drupal_set_message(t('Unknown export format.'));
- throw new NotFoundHttpException();
- }
-}
-
-/**
- * Generates HTML for export when invoked by book_export().
- *
- * The given node is embedded to its absolute depth in a top level section. For
- * example, a child node with depth 2 in the hierarchy is contained in
- * (otherwise empty)
elements corresponding to depth 0 and depth 1.
- * This is intended to support WYSIWYG output - e.g., level 3 sections always
- * look like level 3 sections, no matter their depth relative to the node
- * selected to be exported as printer-friendly HTML.
- *
- * @param \Drupal\node\Plugin\Core\Entity\Node
- * The node to export.
- *
- * @return
- * A string containing HTML representing the node and its children in
- * the book hierarchy.
- *
- * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
- * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
- */
-function book_export_html(EntityInterface $node) {
- if (user_access('access printer-friendly version')) {
- if (isset($node->book)) {
- $tree = book_menu_subtree_data($node->book);
- $contents = book_export_traverse($tree, 'book_node_export');
- $book_exported_html = array('#theme' => 'book_export_html', '#title' => $node->label(), '#contents' => $contents, '#depth' => $node->book['depth']);
- return drupal_render($book_exported_html);
- }
- else {
- throw new NotFoundHttpException();
- }
- }
- else {
- throw new AccessDeniedHttpException();
- }
-}
-
-/**
* Page callback: Shows the outline form for a single node.
*
* @param \Drupal\Core\Entity\EntityInterface $node
diff --git a/core/modules/book/book.routing.yml b/core/modules/book/book.routing.yml
index 6c8b010..ac3cfd3 100644
--- a/core/modules/book/book.routing.yml
+++ b/core/modules/book/book.routing.yml
@@ -18,3 +18,10 @@ book_settings:
_form: 'Drupal\book\BookSettingsForm'
requirements:
_permission: 'administer site configuration'
+
+book_export:
+ pattern: '/book/export/{type}/{node}'
+ defaults:
+ _content: '\Drupal\book\Controller\BookController::bookExport'
+ requirements:
+ _book_export_access: 'TRUE'
diff --git a/core/modules/book/book.services.yml b/core/modules/book/book.services.yml
index 9d8c140..7030606 100644
--- a/core/modules/book/book.services.yml
+++ b/core/modules/book/book.services.yml
@@ -2,3 +2,9 @@ services:
book.manager:
class: Drupal\book\BookManager
arguments: ['@database', '@plugin.manager.entity']
+ access_check.book_export:
+ class: Drupal\book\Access\BookAccessCheck
+ tags:
+ - { name: access_check }
+ book.export:
+ class: Drupal\book\BookExport
diff --git a/core/modules/book/lib/Drupal/book/Access/BookAccessCheck.php b/core/modules/book/lib/Drupal/book/Access/BookAccessCheck.php
new file mode 100644
index 0000000..8ada281
--- /dev/null
+++ b/core/modules/book/lib/Drupal/book/Access/BookAccessCheck.php
@@ -0,0 +1,34 @@
+getRequirements());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function access(Route $route, Request $request) {
+ return user_access('access printer-friendly version') && node_access('view', $request->attributes->get('node'));
+ }
+
+}
diff --git a/core/modules/book/lib/Drupal/book/BookExport.php b/core/modules/book/lib/Drupal/book/BookExport.php
new file mode 100644
index 0000000..6f47b46
--- /dev/null
+++ b/core/modules/book/lib/Drupal/book/BookExport.php
@@ -0,0 +1,95 @@
+ elements corresponding to depth 0 and depth 1.
+ * This is intended to support WYSIWYG output - e.g., level 3 sections always
+ * look like level 3 sections, no matter their depth relative to the node
+ * selected to be exported as printer-friendly HTML.
+ *
+ * @param \Drupal\node\NodeInterface $node
+ * The node to export.
+ *
+ * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
+ * Thrown when the node was not attached to a book.
+ * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
+ * Thrown when the user does not have access to export a book.
+ *
+ * @internal param $ \Drupal\node\Plugin\Core\Entity\Node
+ * The node to export.
+ *
+ * @return string A string containing HTML representing the node and its children in
+ */
+ public function bookExportHtml(NodeInterface $node) {
+ if (!user_access('access printer-friendly version')) {
+ throw new AccessDeniedHttpException();
+ }
+
+ if (!isset($node->book)) {
+ throw new NotFoundHttpException();
+ }
+
+ $tree = book_menu_subtree_data($node->book);
+ $contents = $this->exportTraverse($tree, 'book_node_export');
+ return theme('book_export_html', array('title' => $node->label(), 'contents' => $contents, 'depth' => $node->book['depth']));
+ }
+
+ /**
+ * Traverses the book tree to build printable or exportable output.
+ *
+ * During the traversal, the $visit_func() callback is applied to each node and
+ * is called recursively for each child of the node (in weight, title order).
+ *
+ * @param array $tree
+ * A subtree of the book menu hierarchy, rooted at the current page.
+ * @param string $visit_func
+ * A function callback to be called upon visiting a node in the tree.
+ *
+ * @return string
+ * The output generated in visiting each node.
+ */
+ protected function exportTraverse($tree, $visit_func) {
+ $output = '';
+
+ foreach ($tree as $data) {
+ // Note- access checking is already performed when building the tree.
+ if ($node = node_load($data['link']['nid'])) {
+ $children = '';
+
+ if ($data['below']) {
+ $children = $this->exportTraverse($data['below'], $visit_func);
+ }
+
+ if (!empty($visit_func)) {
+ $output .= call_user_func($visit_func, $node, $children);
+ }
+ else {
+ // Use the default function.
+ $output .= book_node_export($node, $children);
+ }
+ }
+ }
+
+ return $output;
+ }
+
+}
diff --git a/core/modules/book/lib/Drupal/book/Controller/BookController.php b/core/modules/book/lib/Drupal/book/Controller/BookController.php
index 7b10eaf..2c5248c 100644
--- a/core/modules/book/lib/Drupal/book/Controller/BookController.php
+++ b/core/modules/book/lib/Drupal/book/Controller/BookController.php
@@ -8,8 +8,13 @@
use Drupal\Core\Controller\ControllerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+use Drupal\Component\Utility\Unicode;
+use Drupal\node\NodeInterface;
use Drupal\book\BookManager;
+use Drupal\book\BookExport;
/**
* Controller routines for book routes.
@@ -24,17 +29,25 @@ class BookController implements ControllerInterface {
protected $bookManager;
/**
+ * Book Export Service.
+ *
+ * @var \Drupal\book\BookExport
+ */
+ protected $bookExport;
+
+ /**
* Injects BookManager Service.
*/
public static function create(ContainerInterface $container) {
- return new static($container->get('book.manager'));
+ return new static($container->get('book.manager'), $container->get('book.export'));
}
/**
* Constructs a BookController object.
*/
- public function __construct(BookManager $bookManager) {
+ public function __construct(BookManager $bookManager, BookExport $bookExport) {
$this->bookManager = $bookManager;
+ $this->bookExport = $bookExport;
}
/**
@@ -86,4 +99,40 @@ public function bookRender() {
return drupal_render($item_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().
+ *
+ * @param string $type
+ * A string encoding the type of output requested. The following types are
+ * currently supported in book module:
+ * - html: Printer-friendly HTML.
+ * Other types may be supported in contributed modules.
+ * @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.
+ *
+ * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
+ */
+ public function bookExport($type, NodeInterface $node) {
+ $type = Unicode::strtolower($type);
+
+ // @todo Convert the custom export functionality to serializer.
+ $book_export_service = $this->bookExport;
+ $method = 'bookExport' . $type;
+ if (!method_exists($book_export_service, $method)) {
+ drupal_set_message(t('Unknown export format.'));
+ throw new NotFoundHttpException();
+ }
+
+ return new Response($book_export_service->{$method}($node));
+ }
+
}