Skip to content
Snippets Groups Projects
Commit cbce1780 authored by Simon Bäse's avatar Simon Bäse
Browse files

Issue #3382048: Improve code styling and general fixes after static analysis

parent d2fdd9c0
Branches
Tags 1.0.0-rc2
1 merge request!3Issue #3382048: Improve code styling and general fixes after static analysis
......@@ -4,18 +4,20 @@ namespace Drupal\custom_book_block;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceProviderBase;
use Drupal\Core\DependencyInjection\ServiceProviderInterface;
use Symfony\Component\DependencyInjection\Reference;
/**
* Defines a book manager which extends the core BookManager class.
*/
class CustomBookBlockServiceProvider extends ServiceProviderBase implements ServiceProviderInterface {
class CustomBookBlockServiceProvider extends ServiceProviderBase {
/**
* {@inheritdoc}
*/
public function alter(ContainerBuilder $container) {
$definition = $container->getDefinition('book.manager');
$definition->setClass('Drupal\custom_book_block\expandBookManager');
$definition->setClass(ExpandBookManager::class)
->addArgument(new Reference('current_route_match'));
}
}
......@@ -3,25 +3,73 @@
namespace Drupal\custom_book_block;
use Drupal\book\BookManager;
use Drupal\book\BookOutlineStorageInterface;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\Template\Attribute;
use Drupal\Core\Url;
use Drupal\Core\Language\LanguageInterface;
use Drupal\node\NodeInterface;
// Override BookManager service.
/**
* Overrides class for BookManager service.
*/
class ExpandBookManager extends BookManager {
/**
* The current route match.
*
* @var \Drupal\Core\Routing\RouteMatchInterface
*/
protected $routeMatch;
class expandBookManager extends BookManager {
/**
* Constructs an ExpandBookManager object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\StringTranslation\TranslationInterface $translation
* The string translation service.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The config factory.
* @param \Drupal\book\BookOutlineStorageInterface $book_outline_storage
* The book outline storage.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer.
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* The language manager.
* @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
* The entity repository service.
* @param \Drupal\Core\Cache\CacheBackendInterface $backend_chained_cache
* The book chained backend cache service.
* @param \Drupal\Core\Cache\CacheBackendInterface $memory_cache
* The book memory cache service.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, TranslationInterface $translation, ConfigFactoryInterface $config_factory, BookOutlineStorageInterface $book_outline_storage, RendererInterface $renderer, LanguageManagerInterface $language_manager, EntityRepositoryInterface $entity_repository, CacheBackendInterface $backend_chained_cache, CacheBackendInterface $memory_cache, RouteMatchInterface $route_match) {
parent::__construct($entity_type_manager, $translation, $config_factory, $book_outline_storage, $renderer, $language_manager, $entity_repository, $backend_chained_cache, $memory_cache);
$this->routeMatch = $route_match;
}
/**
* {@inheritdoc}
*/
public function bookTreeAllData($bid, $link = NULL, $max_depth = NULL, $always_expand = 0) {
$tree = &drupal_static(__METHOD__, []);
$language_interface = \Drupal::languageManager()->getCurrentLanguage();
$language_interface = $this->languageManager->getCurrentLanguage();
// Use $nid as a flag for whether the data being loaded is for the whole
// tree.
$nid = isset($link['nid']) ? $link['nid'] : 0;
$nid = $link['nid'] ?? 0;
// Generate a cache ID (cid) specific for this $bid, $link, $language, and
// depth.
$cid = 'book-links:' . $bid . ':all:' . $nid . ':' . $language_interface->getId() . ':' . (int) $max_depth;
......@@ -32,8 +80,10 @@ class expandBookManager extends BookManager {
'min_depth' => 1,
'max_depth' => $max_depth,
];
if ($nid) {
$active_trail = $this->getActiveTrailIds($bid, $link);
$active_trail = $this->getActiveTrailIds((string) $bid, $link);
// Setting the 'expanded' value to $active_trail would be same as core.
if ($always_expand) {
$tree_parameters['expanded'] = [];
......@@ -53,29 +103,25 @@ class expandBookManager extends BookManager {
}
/**
* Builds the #items property for a book tree's renderable array.
*
* Helper function for ::bookTreeOutput().
*
* @param array $tree
* A data structure representing the tree.
*
* @return array
* The value to use for the #items property of a renderable menu.
* {@inheritdoc}
*/
protected function buildItems(array $tree) {
$items = [];
$langcode = \Drupal::languageManager()->getCurrentLanguage()->getId();
$node = \Drupal::routeMatch()->getParameter('node');
$langcode = $this->languageManager->getCurrentLanguage()->getId();
$node = $this->routeMatch->getParameter('node');
foreach ($tree as $data) {
$element = [];
$inner_node = \Drupal::entityTypeManager()->getStorage('node')->load($data['link']['nid']);
$inner_node = $this->entityTypeManager
->getStorage('node')
->load($data['link']['nid']);
// Generally we only deal with visible links, but just in case.
if (!$data['link']['access']) {
continue;
}
// Set a class for the <li> tag. Since $data['below'] may contain local
// tasks, only set 'expanded' to true if the link also has children within
// the current book.
......@@ -101,26 +147,26 @@ class expandBookManager extends BookManager {
// If the node is not translated then make the path <front>.
if ($inner_node instanceof NodeInterface) {
if (!$inner_node->hasTranslation($langcode)) {
$element['url'] = Url::fromRoute('<front>');
$element['url'] = Url::fromRoute('<front>');
}
else {
$element['url'] = Url::fromUri('entity:node/' . $data['link']['nid'], [
'language' => $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT),
'language' => $this->languageManager
->getCurrentLanguage(LanguageInterface::TYPE_CONTENT),
]);
}
}
$element['in_active_trail'] = FALSE;
if ($node instanceof NodeInterface) {
if ($data['link']['nid'] == $node->id()) {
$element['in_active_trail'] = TRUE;
}
if (($node instanceof NodeInterface) && $data['link']['nid'] == $node->id()) {
$element['in_active_trail'] = TRUE;
}
$element['localized_options'] = !empty($data['link']['localized_options']) ? $data['link']['localized_options'] : [];
$element['localized_options']['set_active_class'] = TRUE;
$element['below'] = $data['below'] ? $this->buildItems($data['below']) : [];
$element['original_link'] = $data['link'];
// Index using the link's unique nid.
$items[$data['link']['nid']] = $element;
}
......
......@@ -2,14 +2,11 @@
namespace Drupal\custom_book_block\Plugin\Block;
use Drupal\book\BookManagerInterface;
use Drupal\book\Plugin\Block\BookNavigationBlock;
// use Drupal\Core\Cache\Cache;
use Drupal\Component\Utility\SortArray;
use Drupal\Core\Form\FormStateInterface;
use Drupal\custom_book_block\ExpandBookManager;
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.
......@@ -22,28 +19,14 @@ use Drupal\Core\Entity\EntityStorageInterface;
*/
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' => "",
'block_mode' => 'all pages',
'target_book' => '',
'max_levels' => '',
'always_expand' => 1,
];
}
......@@ -54,7 +37,7 @@ class CustomBookNavigationBlock extends BookNavigationBlock {
public function blockForm($form, FormStateInterface $form_state) {
$form = parent::blockForm($form, $form_state);
$options = ['' => "Show all"];
$options = ['' => 'Show all'];
foreach ($this->bookManager->getAllBooks() as $book_id => $book) {
$options[$book_id] = $book['title'];
}
......@@ -63,20 +46,22 @@ class CustomBookNavigationBlock extends BookNavigationBlock {
'#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."),
'#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."),
'#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."),
'#description' => $this->t('If unchecked, will only be expanded in context.'),
];
return $form;
......@@ -97,92 +82,92 @@ class CustomBookNavigationBlock extends BookNavigationBlock {
* {@inheritdoc}
*/
public function build() {
$current_bid = 0;
$book_manager = $this->bookManager;
if (!$book_manager instanceof ExpandBookManager) {
return [];
}
$current_book_id = 0;
$node = $this->routeMatch->getParameter('node');
if ($node instanceof NodeInterface && !empty($node->book['bid'])) {
$current_bid = $node->book['bid'];
$current_book_id = $node->book['bid'];
}
$max_levels = $this->configuration['max_levels'] ?: NULL;
$target_book = $this->configuration['target_book'];
$target_book_id = $this->configuration['target_book'];
$always_expand = $this->configuration['always_expand'];
if ($this->configuration['block_mode'] == 'all pages') {
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']);
uasort($books, [SortArray::class, 'sortByWeightElement']);
foreach ($books as $book_id => $book) {
// If a target book which is not this one, continue.
if ($target_book && $book_id != $target_book) {
if ($target_book_id && $book_id != $target_book_id) {
continue;
}
// If only displaying the top node, no need to do additional queries.
if ($max_levels == 1) {
$book_node = $this->nodeStorage->load($book_id);
if (!$book_node instanceof NodeInterface) {
continue;
}
$book['access'] = $book_node->access('view');
$pseudo_tree[0]['link'] = $book;
$book_menus[$book_id] = $this->bookManager->bookTreeOutput($pseudo_tree);
$book_menus[$book_id] = $book_manager->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);
$data = $book_manager->bookTreeAllData($book_id, $book, $max_levels, $always_expand);
$book_menus[$book_id] = $book_manager->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) {
if ($book_menus[$book_id]['#items'][$book_id]['original_link']['bid'] == $current_book_id) {
$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) {
elseif ($current_book_id) {
// If not 'all pages' and a target book which is not this one, return.
if ($target_book && $current_bid != $target_book) {
if ($target_book_id && $current_book_id != $target_book_id) {
return [];
}
// Only display this block when the user is browsing a book and do
// not show unpublished books.
$nid = \Drupal::entityQuery('node')
$nid = $this->nodeStorage->getQuery()
->accessCheck(TRUE)
->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);
$tree = $book_manager->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']);
$below = $book_manager->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;
// }
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment