Problem/Motivation

Livre is based off of book 3.0.x and the token module which provides the book tokens is not aware of book 3.0.x. The token module assumes you're using book 1.0.x.

How to fix this? Well, here it goes:

Steps to reproduce

Proposed resolution

Add mymodule.token.inc to mymodule

use Drupal\Core\Render\BubbleableMetadata;
use Drupal\node\NodeInterface;

/**
 * Implements hook_token_info().
 */
function mymodule_token_info() {

  return [
    'types' => [
      'node' => [
        'name' => t('Node'),
        'description' => t('Node tokens extended for Livre/Book 3.x.'),
      ],
    ],
    'tokens' => [
      'node' => [
        'book:parents:join-path' => [
          'name' => t('Book parents joined as path'),
          'description' => t('Titles of ancestor book pages, joined as a path.'),
        ],
      ],
    ],
  ];
}

/**
 * Implements hook_tokens().
 */
function mymodule_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {

  $replacements = [];

  if ($type !== 'node' || empty($data['node']) || !$data['node'] instanceof NodeInterface) {
    return $replacements;
  }

  /** @var \Drupal\node\NodeInterface $node */
  $node = $data['node'];

  /** @var \Drupal\book\BookManagerInterface $book_manager */
  $book_manager = \Drupal::service('book.manager');

  // --- 1. Load book link for THIS node ---
  $book_link = $book_manager->loadBookLink($node->id());

  if (!$book_link) {
    return $replacements; // Not part of a book.
  }

  // --- 2. Load the parent link if pid > 0 ---
  $parent_link = [];
  if (!empty($book_link['pid'])) {
    $parent_link = $book_manager->loadBookLink($book_link['pid']) ?: [];
  }

  // --- 3. Get parent chain array ---
  // Returns array: ['depth'=>X, 'p1'=>nid, 'p2'=>nid, ...]
  $parents = $book_manager->getBookParents($book_link, $parent_link);

  $depth = $parents['depth'] ?? 0;

  // --- 4. Build clean path segments from ancestor titles ---
  $titles = [];
  if ($depth > 0) {
    $node_storage = \Drupal::entityTypeManager()->getStorage('node');
    $cleaner = \Drupal::service('pathauto.alias_cleaner');

    $current_nid = $node->id();

    for ($i = 1; $i <= $depth; $i++) {
      $key = 'p' . $i;

      if (!empty($parents[$key]) && $parents[$key] != $current_nid) {
        if ($parent = $node_storage->load($parents[$key])) {
          $titles[] = $cleaner->cleanString($parent->label());
        }
      }
    }
  }


  // The final joined path.
  $joined_path = implode('/', $titles);

  foreach ($tokens as $name => $original) {
    if ($name === 'book:parents:join-path') {
      $replacements[$original] = $joined_path;
    }
  }

  return $replacements;
}

Now with this implemented correctly, the following pathauto pattern is functional:
[node:book:parents:join-path]/[node:title]

Remaining tasks

Turn this into a patch/Merge request for book and test it.

User interface changes

The token should work as expected.

API changes

None

Issue fork livre-3563005

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

joseph.olstad created an issue. See original summary.

joseph.olstad’s picture

  • joseph.olstad committed d30f02d0 on 1.0.x
    fix: #3563005 token support -The token module is not aware of livre/...

  • joseph.olstad committed 6f64919e on 1.0.x
    fix: #3563005 token support -The token module is not aware of livre/...
joseph.olstad’s picture

Assigned: joseph.olstad » Unassigned
Status: Active » Fixed

Merged since book 3.0.x is going to do this OO+, there won't be a conflict.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.