protected function MenuLinkStorageController::findParent

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:

  • use the passed parent link if specified and existing.
  • else, use the first existing link down the previous link hierarchy
  • else, for system menu links (derived from hook_menu()), reparent based on the path hierarchy.

Parameters

\Drupal\Core\Entity\EntityInterface $entity: A menu link entity.

array $parent_candidates: An array of menu link entities keyed by mlid.

Return value

\Drupal\Core\Entity\EntityInterface|false A menu link entity structure of the possible parent or FALSE if no valid parent has been found.

1 call to MenuLinkStorageController::findParent()
MenuLinkStorageController::preSave in drupal/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php
Overrides DatabaseStorageController::preSave().

File

drupal/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php, line 473
Contains \Drupal\menu_link\MenuLinkStorageController.

Class

MenuLinkStorageController
Controller class for menu links.

Namespace

Drupal\menu_link

Code

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;
}