Chris@0: requestStack = $request_stack; Chris@0: $this->bookManager = $book_manager; Chris@0: $this->nodeStorage = $node_storage; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { Chris@0: return new static( Chris@0: $configuration, Chris@0: $plugin_id, Chris@0: $plugin_definition, Chris@0: $container->get('request_stack'), Chris@0: $container->get('book.manager'), Chris@0: $container->get('entity.manager')->getStorage('node') Chris@0: ); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function defaultConfiguration() { Chris@0: return [ Chris@0: 'block_mode' => "all pages", Chris@0: ]; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function blockForm($form, FormStateInterface $form_state) { Chris@0: $options = [ Chris@0: 'all pages' => $this->t('Show block on all pages'), Chris@0: 'book pages' => $this->t('Show block only on book pages'), Chris@0: ]; Chris@0: $form['book_block_mode'] = [ Chris@0: '#type' => 'radios', Chris@0: '#title' => $this->t('Book navigation block display'), Chris@0: '#options' => $options, Chris@0: '#default_value' => $this->configuration['block_mode'], Chris@0: '#description' => $this->t("If Show block on all pages is selected, the block will contain the automatically generated menus for all of the site's books. If Show block only on book pages is selected, the block will contain only the one menu corresponding to the current page's book. In this case, if the current page is not in a book, no block will be displayed. The Page specific visibility settings or other visibility settings can be used in addition to selectively display this block."), Chris@0: ]; Chris@0: Chris@0: return $form; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function blockSubmit($form, FormStateInterface $form_state) { Chris@0: $this->configuration['block_mode'] = $form_state->getValue('book_block_mode'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function build() { Chris@0: $current_bid = 0; Chris@0: Chris@0: if ($node = $this->requestStack->getCurrentRequest()->get('node')) { Chris@0: $current_bid = empty($node->book['bid']) ? 0 : $node->book['bid']; Chris@0: } Chris@0: if ($this->configuration['block_mode'] == 'all pages') { Chris@0: $book_menus = []; Chris@0: $pseudo_tree = [0 => ['below' => FALSE]]; Chris@0: foreach ($this->bookManager->getAllBooks() as $book_id => $book) { Chris@0: if ($book['bid'] == $current_bid) { Chris@0: // If the current page is a node associated with a book, the menu Chris@0: // needs to be retrieved. Chris@0: $data = $this->bookManager->bookTreeAllData($node->book['bid'], $node->book); Chris@0: $book_menus[$book_id] = $this->bookManager->bookTreeOutput($data); Chris@0: } Chris@0: else { Chris@0: // Since we know we will only display a link to the top node, there Chris@0: // is no reason to run an additional menu tree query for each book. Chris@0: $book['in_active_trail'] = FALSE; Chris@0: // Check whether user can access the book link. Chris@0: $book_node = $this->nodeStorage->load($book['nid']); Chris@0: $book['access'] = $book_node->access('view'); Chris@0: $pseudo_tree[0]['link'] = $book; Chris@0: $book_menus[$book_id] = $this->bookManager->bookTreeOutput($pseudo_tree); Chris@0: } Chris@0: $book_menus[$book_id] += [ Chris@0: '#book_title' => $book['title'], Chris@0: ]; Chris@0: } Chris@0: if ($book_menus) { Chris@0: return [ Chris@0: '#theme' => 'book_all_books_block', Chris@0: ] + $book_menus; Chris@0: } Chris@0: } Chris@0: elseif ($current_bid) { Chris@0: // Only display this block when the user is browsing a book and do Chris@0: // not show unpublished books. Chris@0: $nid = \Drupal::entityQuery('node') Chris@0: ->condition('nid', $node->book['bid'], '=') Chris@0: ->condition('status', NodeInterface::PUBLISHED) Chris@0: ->execute(); Chris@0: Chris@0: // Only show the block if the user has view access for the top-level node. Chris@0: if ($nid) { Chris@0: $tree = $this->bookManager->bookTreeAllData($node->book['bid'], $node->book); Chris@0: // There should only be one element at the top level. Chris@0: $data = array_shift($tree); Chris@0: $below = $this->bookManager->bookTreeOutput($data['below']); Chris@0: if (!empty($below)) { Chris@0: return $below; Chris@0: } Chris@0: } Chris@0: } Chris@0: return []; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getCacheContexts() { Chris@0: return Cache::mergeContexts(parent::getCacheContexts(), ['route.book_navigation']); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: * Chris@0: * @todo Make cacheable in https://www.drupal.org/node/2483181 Chris@0: */ Chris@0: public function getCacheMaxAge() { Chris@0: return 0; Chris@0: } Chris@0: Chris@0: }