Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\book;
|
Chris@0
|
4
|
Chris@18
|
5 use Drupal\Core\Entity\EntityTypeManagerInterface;
|
Chris@0
|
6 use Drupal\node\NodeInterface;
|
Chris@0
|
7
|
Chris@0
|
8 /**
|
Chris@0
|
9 * Provides methods for exporting book to different formats.
|
Chris@0
|
10 *
|
Chris@0
|
11 * If you would like to add another format, swap this class in container.
|
Chris@0
|
12 */
|
Chris@0
|
13 class BookExport {
|
Chris@0
|
14
|
Chris@0
|
15 /**
|
Chris@0
|
16 * The node storage.
|
Chris@0
|
17 *
|
Chris@0
|
18 * @var \Drupal\Core\Entity\EntityStorageInterface
|
Chris@0
|
19 */
|
Chris@0
|
20 protected $nodeStorage;
|
Chris@0
|
21
|
Chris@0
|
22 /**
|
Chris@0
|
23 * The node view builder.
|
Chris@0
|
24 *
|
Chris@0
|
25 * @var \Drupal\Core\Entity\EntityViewBuilderInterface
|
Chris@0
|
26 */
|
Chris@0
|
27 protected $viewBuilder;
|
Chris@0
|
28
|
Chris@0
|
29 /**
|
Chris@0
|
30 * The book manager.
|
Chris@0
|
31 *
|
Chris@0
|
32 * @var \Drupal\book\BookManagerInterface
|
Chris@0
|
33 */
|
Chris@0
|
34 protected $bookManager;
|
Chris@0
|
35
|
Chris@0
|
36 /**
|
Chris@0
|
37 * Constructs a BookExport object.
|
Chris@0
|
38 *
|
Chris@18
|
39 * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
Chris@18
|
40 * The entity type manager.
|
Chris@0
|
41 * @param \Drupal\book\BookManagerInterface $book_manager
|
Chris@0
|
42 * The book manager.
|
Chris@0
|
43 */
|
Chris@18
|
44 public function __construct(EntityTypeManagerInterface $entity_type_manager, BookManagerInterface $book_manager) {
|
Chris@18
|
45 $this->nodeStorage = $entity_type_manager->getStorage('node');
|
Chris@18
|
46 $this->viewBuilder = $entity_type_manager->getViewBuilder('node');
|
Chris@0
|
47 $this->bookManager = $book_manager;
|
Chris@0
|
48 }
|
Chris@0
|
49
|
Chris@0
|
50 /**
|
Chris@0
|
51 * Generates HTML for export when invoked by book_export().
|
Chris@0
|
52 *
|
Chris@0
|
53 * The given node is embedded to its absolute depth in a top level section. For
|
Chris@0
|
54 * example, a child node with depth 2 in the hierarchy is contained in
|
Chris@0
|
55 * (otherwise empty) <div> elements corresponding to depth 0 and depth 1.
|
Chris@0
|
56 * This is intended to support WYSIWYG output; for instance, level 3 sections
|
Chris@0
|
57 * always look like level 3 sections, no matter their depth relative to the
|
Chris@0
|
58 * node selected to be exported as printer-friendly HTML.
|
Chris@0
|
59 *
|
Chris@0
|
60 * @param \Drupal\node\NodeInterface $node
|
Chris@0
|
61 * The node to export.
|
Chris@0
|
62 *
|
Chris@0
|
63 * @return array
|
Chris@0
|
64 * A render array representing the HTML for a node and its children in the
|
Chris@0
|
65 * book hierarchy.
|
Chris@0
|
66 *
|
Chris@0
|
67 * @throws \Exception
|
Chris@0
|
68 * Thrown when the node was not attached to a book.
|
Chris@0
|
69 */
|
Chris@0
|
70 public function bookExportHtml(NodeInterface $node) {
|
Chris@0
|
71 if (!isset($node->book)) {
|
Chris@0
|
72 throw new \Exception();
|
Chris@0
|
73 }
|
Chris@0
|
74
|
Chris@0
|
75 $tree = $this->bookManager->bookSubtreeData($node->book);
|
Chris@0
|
76 $contents = $this->exportTraverse($tree, [$this, 'bookNodeExport']);
|
Chris@0
|
77 return [
|
Chris@0
|
78 '#theme' => 'book_export_html',
|
Chris@0
|
79 '#title' => $node->label(),
|
Chris@0
|
80 '#contents' => $contents,
|
Chris@0
|
81 '#depth' => $node->book['depth'],
|
Chris@0
|
82 '#cache' => [
|
Chris@0
|
83 'tags' => $node->getEntityType()->getListCacheTags(),
|
Chris@0
|
84 ],
|
Chris@0
|
85 ];
|
Chris@0
|
86 }
|
Chris@0
|
87
|
Chris@0
|
88 /**
|
Chris@0
|
89 * Traverses the book tree to build printable or exportable output.
|
Chris@0
|
90 *
|
Chris@0
|
91 * During the traversal, the callback is applied to each node and is called
|
Chris@0
|
92 * recursively for each child of the node (in weight, title order).
|
Chris@0
|
93 *
|
Chris@0
|
94 * @param array $tree
|
Chris@0
|
95 * A subtree of the book menu hierarchy, rooted at the current page.
|
Chris@0
|
96 * @param callable $callable
|
Chris@0
|
97 * A callback to be called upon visiting a node in the tree.
|
Chris@0
|
98 *
|
Chris@0
|
99 * @return string
|
Chris@0
|
100 * The output generated in visiting each node.
|
Chris@0
|
101 */
|
Chris@0
|
102 protected function exportTraverse(array $tree, $callable) {
|
Chris@0
|
103 // If there is no valid callable, use the default callback.
|
Chris@0
|
104 $callable = !empty($callable) ? $callable : [$this, 'bookNodeExport'];
|
Chris@0
|
105
|
Chris@0
|
106 $build = [];
|
Chris@0
|
107 foreach ($tree as $data) {
|
Chris@0
|
108 // Note- access checking is already performed when building the tree.
|
Chris@0
|
109 if ($node = $this->nodeStorage->load($data['link']['nid'])) {
|
Chris@0
|
110 $children = $data['below'] ? $this->exportTraverse($data['below'], $callable) : '';
|
Chris@0
|
111 $build[] = call_user_func($callable, $node, $children);
|
Chris@0
|
112 }
|
Chris@0
|
113 }
|
Chris@0
|
114
|
Chris@0
|
115 return $build;
|
Chris@0
|
116 }
|
Chris@0
|
117
|
Chris@0
|
118 /**
|
Chris@0
|
119 * Generates printer-friendly HTML for a node.
|
Chris@0
|
120 *
|
Chris@0
|
121 * @param \Drupal\node\NodeInterface $node
|
Chris@0
|
122 * The node that will be output.
|
Chris@0
|
123 * @param string $children
|
Chris@0
|
124 * (optional) All the rendered child nodes within the current node. Defaults
|
Chris@0
|
125 * to an empty string.
|
Chris@0
|
126 *
|
Chris@0
|
127 * @return array
|
Chris@0
|
128 * A render array for the exported HTML of a given node.
|
Chris@0
|
129 *
|
Chris@0
|
130 * @see \Drupal\book\BookExport::exportTraverse()
|
Chris@0
|
131 */
|
Chris@0
|
132 protected function bookNodeExport(NodeInterface $node, $children = '') {
|
Chris@0
|
133 $build = $this->viewBuilder->view($node, 'print', NULL);
|
Chris@0
|
134 unset($build['#theme']);
|
Chris@0
|
135
|
Chris@0
|
136 return [
|
Chris@0
|
137 '#theme' => 'book_node_export_html',
|
Chris@0
|
138 '#content' => $build,
|
Chris@0
|
139 '#node' => $node,
|
Chris@0
|
140 '#children' => $children,
|
Chris@0
|
141 ];
|
Chris@0
|
142 }
|
Chris@0
|
143
|
Chris@0
|
144 }
|