Newer
Older
<?php
/**
* @file
* Contains \Drupal\book\BookExport.
*/
namespace Drupal\book;
Angie Byron
committed
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\node\NodeInterface;
/**
* Provides methods for exporting book to different formats.
*
* If you would like to add another format, swap this class in container.
*/
class BookExport {
/**
catch
committed
* The node storage.
catch
committed
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $nodeStorage;
/**
Alex Pott
committed
* The node view builder.
Alex Pott
committed
* @var \Drupal\Core\Entity\EntityViewBuilderInterface
Alex Pott
committed
protected $viewBuilder;
/**
* The book manager.
*
* @var \Drupal\book\BookManagerInterface
*/
protected $bookManager;
/**
* Constructs a BookExport object.
*
Angie Byron
committed
* @param \Drupal\Core\Entity\EntityManagerInterface $entityManager
* The entity manager.
* @param \Drupal\book\BookManagerInterface $book_manager
* The book manager.
public function __construct(EntityManagerInterface $entityManager, BookManagerInterface $book_manager) {
catch
committed
$this->nodeStorage = $entityManager->getStorage('node');
Alex Pott
committed
$this->viewBuilder = $entityManager->getViewBuilder('node');
$this->bookManager = $book_manager;
}
/**
* 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) <div> 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 \Exception
* Thrown when the node was not attached to a book.
*
* @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)) {
throw new \Exception();
}
$tree = $this->bookManager->bookSubtreeData($node->book);
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
$contents = $this->exportTraverse($tree, array($this, 'bookNodeExport'));
return array(
'#theme' => 'book_export_html',
'#title' => $node->label(),
'#contents' => $contents,
'#depth' => $node->book['depth'],
);
}
/**
* Traverses the book tree to build printable or exportable output.
*
* During the traversal, the 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 callable $callable
* A callback to be called upon visiting a node in the tree.
*
* @return string
* The output generated in visiting each node.
*/
protected function exportTraverse(array $tree, $callable) {
// If there is no valid callable, use the default callback.
$callable = !empty($callable) ? $callable : array($this, 'bookNodeExport');
$output = '';
foreach ($tree as $data) {
// Note- access checking is already performed when building the tree.
if ($node = $this->nodeStorage->load($data['link']['nid'])) {
$children = $data['below'] ? $this->exportTraverse($data['below'], $callable) : '';
$callable_output = call_user_func($callable, $node, $children);
$output .= drupal_render($callable_output);
}
}
return $output;
}
/**
* Generates printer-friendly HTML for a node.
*
* @param \Drupal\node\NodeInterface $node
* The node that will be output.
* @param string $children
* (optional) All the rendered child nodes within the current node. Defaults
* to an empty string.
*
* @return array
* A render array for the exported HTML of a given node.
*
* @see \Drupal\book\BookExport::exportTraverse()
*/
protected function bookNodeExport(NodeInterface $node, $children = '') {
Alex Pott
committed
$build = $this->viewBuilder->view($node, 'print', NULL);
unset($build['#theme']);
// @todo Rendering should happen in the template using render().
$node->rendered = drupal_render($build);
return array(
'#theme' => 'book_node_export_html',
'#node' => $node,
'#children' => $children,
);
}
}