Closed (fixed)
Project:
Livre
Version:
1.0.x-dev
Component:
Code
Priority:
Normal
Category:
Bug report
Assigned:
Unassigned
Reporter:
Created:
13 Dec 2025 at 15:48 UTC
Updated:
28 Dec 2025 at 18:44 UTC
Jump to comment: Most recent
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:
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]
Turn this into a patch/Merge request for book and test it.
The token should work as expected.
None
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
Comment #2
joseph.olstadComment #6
joseph.olstadMerged since book 3.0.x is going to do this OO+, there won't be a conflict.