Problem/Motivation
STR:
- First create a new book add a series of child pages nested to as deep as 7 to 8 levels.
- Now create a second child page of the top-level book node and set of several child pages of that.
- When attempting to edit a node that has children that go deep enough, there is a fatal error:
[Mon Jan 25 17:23:18.977405 2016] [:error] [pid 27538] [client 206.192.168.17:5717] PHP Fatal error: Call to a member function label() on null in /var/www/html/core/modules/book/src/BookManager.php on line 414</li>
<li>
the recurseTableOfContents function doesn't properly handle the case when it's pruned every node in a particular branch. E.g. it runs through this foreach loop, and every node is below the depth_limit. The break exits the loop, and proceeds through the function.
<?php
foreach ($tree as $data) {
if ($data['link']['depth'] > $depth_limit) {
// Don't iterate through any links on this level.
break;
}
if (!in_array($data['link']['nid'], $exclude)) {
$nids[] = $data['link']['nid'];
}
}
?>
It then crashes within this foreach loop, as it attempts to call Unicode::truncate without verifying if there are any nodes left.
<?php
foreach ($tree as $data) {
$nid = $data['link']['nid'];
if (in_array($nid, $exclude)) {
continue;
}
$toc[$nid] = $indent . '' . Unicode::truncate($nodes[$nid]->label(), 30, TRUE, TRUE);
if ($data['below']) {
$this->recurseTableOfContents($data['below'], $indent . '--', $toc, $exclude, $depth_limit);
}
}
?>
Proposed resolution
add a check on or after the first foreach loop that returns from the function if there aren't any nodes.
<?php
// Return to calling function if all links have been excluded due to depth
if (empty($nids)) {
return;
}
?>
Remaining tasks
Add tests
User interface changes
n/a
API changes
n/a
Data model changes
n/a