Перенаправление устаревшего URL-адреса


Я перенес сайт, не использующий Drupal, на Drupal. Теперь мне нужно убедиться, что некоторые устаревшие URL-адреса перенаправляются на правильный URL-адрес узла.
Узел имеет идентификатор узла (nid), устаревший идентификатор (field_leg_id), идентификатор элемента (item_id), заголовок (headline_of_the_item) и текст.

Устаревший URL-адрес example.com/type1/201203080034 следует перенаправить на новый URL-адрес example.com/type1/2012/03/08/headline_of_the_item/item_id .

201203080034 - это устаревший идентификатор соответствует 20120308 в новом URL-адресе.

Как перенаправить пользователей на новый узел, если у меня есть только устаревший идентификатор?
обновление

 // Redirect based on legacy ID.
$query = db_query("select lid.entity_id, lid.field_legacy_id_value, sid.field_site_content_id_value     
                   from field_data_field_legacy_id lid     
                   inner join field_revision_field_site_content_id sid on lid.entity_id = sid.entity_id          
                   where lid.field_legacy_id_value = $content_id       
                   LIMIT 1");

while ($row = db_fetch_object($query)) {
  $s_id = $row->sid.field_site_content_id_value;
  $item = node_load($s_id);
  if ($item) {
    drupal_goto("node/{$item->nid}", array(), 301);
  }
}

}

Это дает мне 500 ошибок. Пытался отладить его, но безуспешно.

Обновление на основе @greendemiurge Ниже - это то, что сработало для меня.

   function my_item_redirect_item() {
       $args = arg();
       $content_id = end($args);
       $item = my_item_by_legacy_id($content_id);
      if ($item) {
         drupal_goto("node/{$item->nid}", array(), 301);
      }
   }

   function my_item_by_legacy_id($id) {
   // First, check if we have an imported item with this $id (field_legacy_id).
   $query = new EntityFieldQuery();

   $query->entityCondition('entity_type', 'node')
         ->fieldCondition('field_legacy_id', 'value', $id, '=')
         ->range(0, 1)
         ->addMetaData('account', user_load(1));

   $result = $query->execute();

   if (isset($result['node'])) {
      $nids = array_keys($result['node']);
      return node_load($nids[0]);
   }

 // Check if there is a node with Nid = $id
 return node_load($id);
} 
Author: mamesaye, 2016-04-22

2 answers

Первый вопрос по этому поводу: сколько URL-адресов вам нужно перенаправить? Если это небольшое число, вам может быть лучше использовать .htaccess. Я сомневаюсь, что это так, учитывая ваши модели поведения.

Следующий вопрос заключается в том, достаточно ли информации в старом шаблоне для разрешения текущего узла, или вам нужно создать сопоставления самостоятельно?

Если информации достаточно, возможно, можно использовать перенаправление соответствия - https://www.drupal.org/project/match_redirect . Если это не так именно то, что вам нужно, вы можете реализовать в этом модуле некоторый пользовательский код, основанный на match_redirect_init().

Редактировать
Вышеприведенных дополнений мне достаточно, чтобы сделать пару предложений: Во-первых, запрос было бы лучше выполнить в виде запроса db_select или поля сущности по стандартным причинам. Более важно, что гораздо эффективнее, если это возможно, позволить SQL выполнять сопоставление, а не цикл while.

Во-вторых, крючок, который, кажется, лучше всего подходит для меня, это hook_menu_get_item_alter(). Другие, у кого больше опыта в маршрутизации меню, возможно, захотят дать некоторые отзывы об этом подходе, но для меня он работает в изолированной среде.

Итак, предполагая, что модуль называется "пользовательский", это то, что, кажется, работает для меня:

function custom_menu_get_item_alter(&$router_item, $path, $original_map) {
  $query = new EntityFieldQuery();

  // $path is everything after your base URL. I am assuming that this is what
  // you have in field_legacy_id.
  $query
    ->entityCondition('entity_type', 'node', '=')
    ->propertyCondition('status', 1, '=')
    ->fieldCondition('field_legacy_id', $path);

  $results = $query->execute();
  $results = array_keys($results['node']);
  $result = reset($results);

  if (!empty($result)) {
    $node = node_load($result);

    // This will retain your aliased path if you are using one. Important for
    // SEO, especially if you are using a 301.
    $path = drupal_get_path_alias("node/{$node}");
    drupal_goto($path, array(), 301);
  }
}

Я не смог протестировать это заранее, используя описанную вами настройку, поэтому, возможно, потребуется некоторая настройка. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

 2
Author: greendemiurge, 2016-04-25 15:28:43

Это работает для меня. Мне нужно проверить current_path, чтобы убедиться, что это параметр необработанного URL, и menu_get_item, чтобы убедиться, что мы смотрим на случайный URL, а не на /node/10 vs 1234-legacy-url.

function legacyredirect_menu_get_item_alter(&$router_item, $path, $original_map) {
    $query = new EntityFieldQuery();

    $path = current_path();

    $query
        ->entityCondition('entity_type', 'node', '=')
        ->propertyCondition('status', 1, '=')
        ->addTag('nicedpq')
        ->fieldCondition('field_legacy_content_id', 'value', $path);
    $results = $query->execute();

    if (isset($results['node'])  && !menu_get_item($path)) {
        $results = array_keys($results['node']);
        $result = reset($results);
        if (!empty($result)) {
            $node = node_load($result);

            // This will retain your aliased path if you are using one. Important for
            // SEO, especially if you are using a 301.
            $path2 = drupal_get_path_alias("node/" . $node->nid);
            header("Location: $path2", 301);
            exit;
        }
    }
}
 1
Author: tenken, 2016-04-25 17:30:45