Finds a possible parent for a given menu link entity.
Because the parent of a given link might not exist anymore in the database, we apply a set of heuristics to determine a proper parent:
\Drupal\Core\Entity\EntityInterface $entity: A menu link entity.
array $parent_candidates: An array of menu link entities keyed by mlid.
\Drupal\Core\Entity\EntityInterface|false A menu link entity structure of the possible parent or FALSE if no valid parent has been found.
protected function findParent(EntityInterface $entity, array $parent_candidates = array()) {
$parent = FALSE;
// This item is explicitely top-level, skip the rest of the parenting.
if (isset($entity->plid) && empty($entity->plid)) {
return $parent;
}
// If we have a parent link ID, try to use that.
$candidates = array();
if (isset($entity->plid)) {
$candidates[] = $entity->plid;
}
// Else, if we have a link hierarchy try to find a valid parent in there.
if (!empty($entity->depth) && $entity->depth > 1) {
for ($depth = $entity->depth - 1; $depth >= 1; $depth--) {
$parent_property = "p{$depth}";
$candidates[] = $entity->{$parent_property};
}
}
foreach ($candidates as $mlid) {
if (isset($parent_candidates[$mlid])) {
$parent = $parent_candidates[$mlid];
}
else {
$parent = $this
->load(array(
$mlid,
));
$parent = reset($parent);
}
if ($parent) {
return $parent;
}
}
// If everything else failed, try to derive the parent from the path
// hierarchy. This only makes sense for links derived from menu router
// items (ie. from hook_menu()).
if ($entity->module == 'system') {
// Find the parent - it must be unique.
$parent_path = $entity->link_path;
do {
$parent = FALSE;
$parent_path = substr($parent_path, 0, strrpos($parent_path, '/'));
$query = \Drupal::entityQuery($this->entityType);
$query
->condition('mlid', $entity
->id(), '<>')
->condition('module', 'system')
->condition('menu_name', $entity->menu_name)
->condition('link_path', $parent_path);
$result = $query
->execute();
// Only valid if we get a unique result.
if (count($result) == 1) {
$parent = $this
->load($result);
$parent = reset($parent);
}
} while ($parent === FALSE && $parent_path);
}
return $parent;
}