epub_reader_framework-2.0.0-alpha2/src/Plugin/Block/ReaderNavigationBlock.php

src/Plugin/Block/ReaderNavigationBlock.php
<?php

namespace Drupal\epub_reader_framework\Plugin\Block;

use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Link;
use Drupal\Core\Url;
use Drupal\node\NodeInterface;

/**
 * Provides a Reader Navigation Block.
 *
 * @Block(
 *   id = "reader_navigation_block",
 *   admin_label = @Translation("Reader navigation block"),
 *   category = @Translation("EPUB Reader"),
 * )
 */
class ReaderNavigationBlock extends BlockBase {

  /**
   * {@inheritdoc}
   */
  public function build() {
    $node = \Drupal::routeMatch()->getParameter('node');
    if ($node instanceof NodeInterface) {

      // Get the reader publication.
      $reader_publication = FALSE;
      if ($node->bundle() == 'reader_publication') {
        $reader_publication = $node;
      }
      elseif ($node->bundle() == 'reader_chapter') {
        /** @var \Drupal\node\NodeInterface $reader_publication */
        $reader_publication = $node->field_reader_publication->entity;
      }

      if ($reader_publication) {

        return [
          '#theme' => 'reader_navigation',
          '#chapter_items' => $this->buildChaptersList($reader_publication),
        ];
      }
    }
    return [];
  }

  /**
   * Build the list of chapters.
   *
   * @param \Drupal\node\NodeInterface $publication
   *
   * @return array
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  protected function buildChaptersList(NodeInterface $publication) {

    // Build chapters.
    $chapter_items = [];
    $chapters = $publication->get('field_reader_chapters');
    if ($chapters->count()) {

      // Load all chapter children at once.
      $chapter_children = $this->loadChapterChildren($publication);

      foreach ($chapters as $chapter) {
        $reader_chapter = $chapter->entity;
        if ($reader_chapter instanceof NodeInterface) {
          $chapter_items[] = $this->buildChapterMenuItem($reader_chapter, $chapter_children);
        }
      }
    }

    // Build top level unordered list.
    return [
      '#theme' => 'item_list',
      '#list_type' => 'ul',
      '#items' => $chapter_items,
      '#attributes' => ['class' => ['c-reader-navigation__menu']],
      '#wrapper_attributes' => ['class' => ['c-reader-navigation__menu-wrapper']],
    ];
  }

  /**
   * Build the chapter menu item.
   *
   * @param \Drupal\node\NodeInterface $chapter
   *   The reader chapter.
   * @param array $chapter_children
   *   The chapter children render array.
   *
   * @return array
   *   The chapter menu item.
   */
  protected function buildChapterMenuItem(NodeInterface $chapter, $chapter_children) {
    $renderer = \Drupal::service('renderer');
    $children = $this->buildChapterChildren($chapter, $chapter_children);

    // Container for the link and icon.
    $chapter_menu_item = [
      '#type' => 'container',
    ];

    // Parent link.
    $chapter_label = $chapter->label();
    \Drupal::moduleHandler()->alter('epub_reader_framework_navigation_chapter_label', $chapter_label, $chapter);
    $link = Link::fromTextAndUrl(
      $chapter_label,
      Url::fromUserInput('/node/' . $chapter->id() . '/nojs')
    )->toRenderable();
    $link['#attributes']['class'] = [
      'c-reader-navigation__menu-item-link',
      'use-ajax',
    ];
    // @see https://www.drupal.org/node/956186.
    $link['#attributes']['data-ajax-type'] = ['GET'];
    $chapter_menu_item['link'] = $link;

    // Add the chapter items.
    $wrapper_classes = ['c-reader-navigation__menu-item'];
    if ($children) {
      $icon = [
        '#type' => 'html_tag',
        '#tag' => 'span',
        '#attributes' => [
          'class' => [
            'c-reader-navigation__expand',
            'js-reader-navigation-expand',
          ],
          'tabindex' => "0",
        ],
        'child' => [
          '#type' => 'html_tag',
          '#tag' => 'span',
          '#value' => '&#x2304;',
          '#attributes' => [
            'class' => [
              'c-reader-navigation__expand-icon',
            ],
          ],
        ],
      ];
      $chapter_menu_item['icon'] = $icon;
      $wrapper_classes[] = 'has-children';
      $wrapper_classes[] = 'js-reader-navigation-expand-wrapper';
    }

    \Drupal::moduleHandler()->alter('epub_reader_framework_navigation_chapter_menu_item', $chapter_menu_item);
    return [
      '#markup' => $renderer->render($chapter_menu_item),
      'children' => $children,
      '#wrapper_attributes' => ['class' => $wrapper_classes],
    ];
  }

  /**
   * Load all chapter children at once.
   *
   * @param \Drupal\node\NodeInterface $publication
   *   The reader publication containing the reader chapters.
   *
   * @return array
   *   An array to store children keyed by chapter ID.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  protected function loadChapterChildren(NodeInterface $publication) {
    $chapter_children = [];

    // Get all children of all chapters at once.
    $entity_type_manager = \Drupal::entityTypeManager();
    $reader_chapter_heading_storage = $entity_type_manager->getStorage('reader_chapter_heading');
    $query = $reader_chapter_heading_storage->getQuery();
    $query->condition('reader_publication_id', $publication->id());
    $query->accessCheck();
    if ($reader_chapter_heading_ids = $query->execute()) {
      $count = 1;
      $reader_chapter_headings = $reader_chapter_heading_storage->loadMultiple($reader_chapter_heading_ids);
      foreach ($reader_chapter_headings as $chapter_heading) {
        $reader_chapter_id = $chapter_heading->get('reader_chapter_id')->value;
        if (!isset($chapter_children[$reader_chapter_id])) {
          $chapter_children[$reader_chapter_id] = [];
        }
        \Drupal::moduleHandler()->alter('epub_reader_framework_navigation_chapter_heading', $chapter_heading, $reader_chapter_id, $count);
        $chapter_children[$reader_chapter_id][] = $chapter_heading;
        $count++;
      }
    }
    return $chapter_children;
  }

  /**
   * Build the chapter children render array.
   *
   * @param \Drupal\node\NodeInterface $chapter
   *   The reader chapter.
   * @param $chapter_children
   *   The full list of children keyed by chapter ID.
   *
   * @return array
   *   The render array for the children for this particular reader chapter.
   */
  protected function buildChapterChildren(NodeInterface $chapter, $chapter_children) {
    // Add chapter children links.
    $children = [];
    if (isset($chapter_children[$chapter->id()])) {
      foreach ($chapter_children[$chapter->id()] as $reader_chapter_heading) {
        $http_query = UrlHelper::buildQuery([
          'heading' => $reader_chapter_heading->get('heading')->value,
          'order' => $reader_chapter_heading->get('order')->value,
        ]);

        // Child link.
        $link = Link::fromTextAndUrl(
          $reader_chapter_heading->get('heading')->value,
          Url::fromUserInput('/node/' . $chapter->id() . '/nojs?' . $http_query)
        )->toRenderable();
        $link['#attributes']['class'] = [
          'c-reader-navigation__sub-menu-item-link',
          'use-ajax',
        ];
        // @see https://www.drupal.org/node/956186.
        $link['#attributes']['data-ajax-type'] = ['GET'];
        $children[] = $link;
      }
    }
    return $children;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc