You are here

function menu_link_install in Menu Link (Field) 8

Implements hook_install().

File

./menu_link.install, line 18

Code

function menu_link_install() {
  if (!\Drupal::moduleHandler()
    ->moduleExists('menu_ui') || !\Drupal::moduleHandler()
    ->moduleExists('field')) {
    return;
  }

  // Install a menu_link field to all node types.
  $node_types = NodeType::loadMultiple();
  FieldStorageConfig::create([
    'field_name' => 'menu_link',
    'entity_type' => 'node',
    'type' => 'menu_link',
  ])
    ->save();
  foreach ($node_types as $node_type) {
    FieldConfig::create([
      'field_name' => 'menu_link',
      'entity_type' => 'node',
      'bundle' => $node_type
        ->id(),
    ])
      ->save();
  }

  // Add the form configuration.
  foreach (NodeType::loadMultiple() as $node_type) {

    // Load the corresponding default form  display.
    if ($entity_form_display = EntityFormDisplay::load("node.{$node_type->id()}.default")) {
      $entity_form_display
        ->setComponent('menu_link', [
        'type' => 'menu_link_default',
      ]);
      $entity_form_display
        ->save();
    }
  }

  /** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_tree_storage */
  $menu_tree_storage = \Drupal::service('plugin.manager.menu.link');

  /** @var \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository */
  $entity_repository = \Drupal::service('entity.repository');

  // Find all menu links which point to a node and replace them with a menu link
  // field.
  $old_plugin_id__new_plugin_id_map = [];

  // Ideally we would use $menu_tree_storage->loadLinksByRoute but it doesn't
  // allow you to just specific the route name.
  $menu_ids = \Drupal::database()
    ->query("SELECT id from {menu_tree} WHERE route_name = 'entity.node.canonical'")
    ->fetchAllKeyed(0, 0);

  // Filter out potential other menu links.
  $menu_ids = array_filter($menu_ids, function ($menu_id) {
    return strpos($menu_id, 'menu_link_content:') === 0;
  });
  $links = array_map(function ($menu_plugin_id) use ($menu_tree_storage) {
    return $menu_tree_storage
      ->createInstance($menu_plugin_id, []);
  }, $menu_ids);
  $menu_link_content_to_be_deleted = [];
  foreach ($links as $link) {

    /** @var \Drupal\menu_link_content\MenuLinkContentInterface $menu_link_content */
    $menu_link_content = $entity_repository
      ->loadEntityByUuid('menu_link_content', $link
      ->getDerivativeId());
    $node_id = $link
      ->getRouteParameters()['node'];
    if ($menu_link_content && ($node = Node::load($node_id))) {
      foreach ($node
        ->getTranslationLanguages() as $language) {
        $node_translation = $node
          ->getTranslation($language
          ->getId());
        if ($menu_link_content
          ->hasTranslation($language
          ->getId())) {
          $menu_link_content_translation = $menu_link_content
            ->getTranslation($language
            ->getId());
          $node_translation
            ->set('menu_link', [
            'menu_name' => $menu_link_content
              ->getMenuName(),
            'title' => $menu_link_content_translation
              ->getTitle(),
            'description' => $menu_link_content_translation
              ->getDescription(),
            'parent' => $menu_link_content
              ->getParentId(),
            'weight' => $menu_link_content
              ->getWeight(),
          ]);
        }
        else {
          $node_translation
            ->set('menu_link', [
            'menu_name' => $menu_link_content
              ->getMenuName(),
            'title' => $menu_link_content
              ->getTitle(),
            'description' => $menu_link_content
              ->getDescription(),
            'parent' => $menu_link_content
              ->getParentId(),
            'weight' => $menu_link_content
              ->getWeight(),
          ]);
        }
      }
      $node
        ->save();
      $old_plugin_id__new_plugin_id_map[$link
        ->getPluginId()] = $node
        ->get('menu_link')
        ->first()
        ->getMenuPluginId();
      $menu_link_content_to_be_deleted[] = $link
        ->getDerivativeId();
    }
  }

  // Now update all the parents based upon the mappings we made.
  foreach ($links as $link) {
    $node_id = $link
      ->getRouteParameters()['node'];
    if ($node = Node::load($node_id)) {
      if ($parent_plugin_id = $node
        ->get('menu_link')->parent) {
        if (isset($old_plugin_id__new_plugin_id_map[$parent_plugin_id])) {
          $node
            ->get('menu_link')->parent = $old_plugin_id__new_plugin_id_map[$parent_plugin_id];
          $node
            ->save();
        }
      }
    }
  }

  // And finally we remove the orphan menu_link_content entities.
  foreach ($menu_link_content_to_be_deleted as $uuid) {
    if ($menu_link_content = $entity_repository
      ->loadEntityByUuid('menu_link_content', $uuid)) {
      $menu_link_content
        ->delete();
    }
  }
}