You are here

public function TocBuilder::renderContent in TOC API 8

Renders a table of contents' body.

Parameters

\Drupal\toc_api\TocInterface $toc: A TOC object.

Return value

string The table of content's body content with bookmarked, typed, and custom headers with back to top links.

Overrides TocBuilderInterface::renderContent

1 call to TocBuilder::renderContent()
TocBuilder::buildContent in src/TocBuilder.php
Build a table of contents' body.

File

src/TocBuilder.php, line 34

Class

TocBuilder
Defines a service that builds and renders a table of contents and update an HTML document's headers.

Namespace

Drupal\toc_api

Code

public function renderContent(TocInterface $toc) {
  if (!$toc
    ->isVisible()) {
    return $toc
      ->getSource();
  }
  $dom = Html::load($toc
    ->getContent());
  $options = $toc
    ->getOptions();
  $index = $toc
    ->getIndex();
  foreach ($index as $item) {

    // Get DOM node by id.
    $dom_node = $dom
      ->getElementById($item['id']);

    // Get attributes.
    $attributes = [];
    if ($dom_node
      ->hasAttributes()) {
      foreach ($dom_node->attributes as $attribute) {
        $attributes[$attribute->nodeName] = $attribute->nodeValue;
      }
    }

    // Build the fragment (header) node.
    $build = [];
    $header_level = (int) $dom_node->tagName[1];
    if ($header_level >= $options['top_min'] && $header_level <= $options['top_max']) {
      $build['top'] = [
        '#theme' => 'toc_back_to_top',
        '#toc' => $toc,
        '#item' => $item,
      ];
    }
    $build['header'] = [
      '#theme' => 'toc_header',
      '#toc' => $toc,
      '#item' => $item,
      '#attributes' => $attributes,
    ];
    $fragment_node = $dom
      ->createDocumentFragment();
    $fragment_node
      ->appendXML($this->renderer
      ->render($build));

    // Replace the header node.
    $dom_node->parentNode
      ->replaceChild($fragment_node, $dom_node);
  }

  // Append back to top to the bottom.
  if ($options['top_min'] == $options['header_min']) {
    $build = [
      '#theme' => 'toc_back_to_top',
      '#toc' => $toc,
      '#item' => NULL,
    ];
    $fragment_node = $dom
      ->createDocumentFragment();
    $fragment_node
      ->appendXML($this->renderer
      ->render($build));
    $dom
      ->getElementsByTagName('body')
      ->item(0)
      ->appendChild($fragment_node);
  }
  return Html::serialize($dom);
}