首页 » bug飞 » drupal9 使用CustomBookNavigationBlock报错:Call to a member function getCurrentRequest() on null in Drupal\d8module\Plugin\Block\CustomBookNavigationBlock->build()

使用CustomBookNavigationBlock,报错:Call to a member function getCurrentRequest() on null in Drupald8modulePluginBlockCustomBookNavigationBlock->build()

替换CustomBookNavigationBlock如下:

<?php

namespace Drupal\custom_book_block\Plugin\Block;

use Drupal\book\BookManagerInterface;
use Drupal\book\Plugin\Block\BookNavigationBlock;
// use Drupal\Core\Cache\Cache;
use Drupal\Core\Form\FormStateInterface;
use Drupal\node\NodeInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\Core\Entity\EntityStorageInterface;

/**
 * Provides a custom 'Book navigation' block.
 *
 * @Block(
 *   id = "custom_book_navigation",
 *   admin_label = @Translation("Custom book navigation"),
 *   category = @Translation("Menus")
 * )
 */
class CustomBookNavigationBlock extends BookNavigationBlock {

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('current_route_match'),
      $container->get('book.manager'),
      $container->get('entity_type.manager')->getStorage('node')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'block_mode' => "all pages",
      'target_book' => "",
      'max_levels' => "",
      'always_expand' => 1,
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function blockForm($form, FormStateInterface $form_state) {
    $form = parent::blockForm($form, $form_state);

    $options = ['' => "Show all"];
    foreach ($this->bookManager->getAllBooks() as $book_id => $book) {
      $options[$book_id] = $book['title'];
    }
    $form['target_book'] = [
      '#type' => 'radios',
      '#title' => $this->t('Book to display'),
      '#options' => $options,
      '#default_value' => $this->configuration['target_book'],
      '#description' => $this->t("If left empty, all books will be shown."),
    ];
    $form['max_levels'] = [
      '#type' => 'number',
      '#title' => $this->t('Maximum levels to show'),
      '#min' => 0,
      '#default_value' => $this->configuration['max_levels'],
      '#description' => $this->t("If set to zero, all levels will be shown."),
    ];
    $form['always_expand'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Always expand the menu'),
      '#default_value' => $this->configuration['always_expand'],
      '#description' => $this->t("If unchecked, will only be expanded in context."),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function blockSubmit($form, FormStateInterface $form_state) {
    parent::blockSubmit($form, $form_state);

    $this->configuration['target_book'] = $form_state->getValue('target_book');
    $this->configuration['max_levels'] = $form_state->getValue('max_levels');
    $this->configuration['always_expand'] = $form_state->getValue('always_expand');
  }

  /**
   * {@inheritdoc}
   */
  public function build() {
    $current_bid = 0;

    $node = $this->routeMatch->getParameter('node');
    if ($node instanceof NodeInterface && !empty($node->book['bid'])) {
      $current_bid = $node->book['bid'];
    }
    $max_levels = $this->configuration['max_levels'] ?: NULL;
    $target_book = $this->configuration['target_book'];
    $always_expand = $this->configuration['always_expand'];

    if ($this->configuration['block_mode'] == 'all pages') {
      $book_menus = [];
      $pseudo_tree = [0 => ['below' => FALSE]];
      $books = $this->bookManager->getAllBooks();
      uasort($books, ['Drupal\Component\Utility\SortArray', 'sortByWeightElement']);
      foreach ($books as $book_id => $book) {
        // If a target book which is not this one, continue.
        if ($target_book && $book_id != $target_book) {
          continue;
        }
        // If only displaying the top node, no need to do additional queries.
        if ($max_levels == 1) {
          $book_node = $this->nodeStorage->load($book_id);
          $book['access'] = $book_node->access('view');
          $pseudo_tree[0]['link'] = $book;
          $book_menus[$book_id] = $this->bookManager->bookTreeOutput($pseudo_tree);
        }
        else {
          // Retrieve the full menu, to the specified depth.
          $data = $this->bookManager->bookTreeAllData($book_id, $book, $max_levels, $always_expand);
          $book_menus[$book_id] = $this->bookManager->bookTreeOutput($data);
          $book_menus[$book_id]['#items'][$book_id]['in_active_trail'] = FALSE;
          if ($book_menus[$book_id]['#items'][$book_id]['original_link']['bid'] == $current_bid) {
            $book_menus[$book_id]['#items'][$book_id]['in_active_trail'] = TRUE;
          }
        }
        $book_menus[$book_id] += [
          '#book_title' => $book['title'],
        ];
      }
      if ($book_menus) {
        return [
          '#theme' => 'book_all_books_block',
        ] + $book_menus;
      }
    }
    elseif ($current_bid) {
      // If not 'all pages' and a target book which is not this one, return.
      if ($target_book && $current_bid != $target_book) {
        return [];
      }
      // Only display this block when the user is browsing a book and do
      // not show unpublished books.
      $nid = \Drupal::entityQuery('node')
        ->condition('nid', $node->book['bid'], '=')
        ->condition('status', NodeInterface::PUBLISHED)
        ->execute();

      // Only show the block if the user has view access for the top-level node.
      if ($nid) {
        $tree = $this->bookManager->bookTreeAllData($node->book['bid'], $node->book, $max_levels, $always_expand);
        // There should only be one element at the top level.
        $data = array_shift($tree);
        $below = $this->bookManager->bookTreeOutput($data['below']);
        if (!empty($below)) {
          return $below;
        }
      }
    }
    return [];
  }

  /**
   * {@inheritdoc}
   */
  // public function getCacheContexts() {
  //   return Cache::mergeContexts(parent::getCacheContexts(), ['route.book_navigation']);
  // }

  /**
   * {@inheritdoc}
   *
   * @todo Make cacheable in https://www.drupal.org/node/2483181
   */
  // public function getCacheMaxAge() {
  //   return 0;
  // }

}

区别参考这个链接: https://www.drupal.org/files/issues/2021-07-01/call-to-a-member-function-3221656-2.patch

添加新评论