Problem/Motivation

A major use case for redirects is supporting legacy URLs after migrating content.

Proposed resolution

We can provide a handler for the Migrate module. This way, a developer can add a mapping with a simple one-line addition to their migrate class:

<?php
$this
->addFieldMapping('migrate_redirects', 'old_legacy_path');
?>

Remaining tasks

Patch reviews

User interface changes

none

API changes

The patch implements hook_migrate_api(), and adds a migrate.inc file containing the handler. The autoloader will make sure that migrate.inc is only loaded when needed.

Files: 
CommentFileSizeAuthor
#69 redirect-migrate-support-1116408-69.patch4.78 KBkostajh
PASSED: [[SimpleTest]]: [MySQL] 101 pass(es).
[ View ]
#68 redirect-migrate-support-1116408-68.patch4.75 KBkostajh
PASSED: [[SimpleTest]]: [MySQL] 101 pass(es).
[ View ]
#67 redirect-migrate-support-1116408-67.patch4.12 KBkostajh
PASSED: [[SimpleTest]]: [MySQL] 101 pass(es).
[ View ]
#65 redirect-migrate-support-1116408-65.patch3.9 KBrvilar
PASSED: [[SimpleTest]]: [MySQL] 101 pass(es).
[ View ]
#59 redirect-migrate-support-1116408-59.patch3.88 KBmikeker
PASSED: [[SimpleTest]]: [MySQL] 101 pass(es).
[ View ]
#59 redirect-migrate-support-1116408.diff893 bytesmikeker
PASSED: [[SimpleTest]]: [MySQL] 101 pass(es).
[ View ]
#53 redirect-migration-support-1116408-53.patch4.39 KBjamsilver
PASSED: [[SimpleTest]]: [MySQL] 101 pass(es).
[ View ]
#52 migrate_redirect-1116408-52.patch3.84 KBbrockfanning
PASSED: [[SimpleTest]]: [MySQL] 101 pass(es).
[ View ]
#45 migrate_redirect-1116408-44.patch3.71 KBmikeryan
PASSED: [[SimpleTest]]: [MySQL] 101 pass(es).
[ View ]
#42 Screenshot.png206.58 KBCaptainSully
#40 migrate_redirect-1116408-40.patch3.63 KBrbayliss
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch migrate_redirect-1116408-40.patch. Unable to apply patch. See the log in the details link for more information.
[ View ]
#39 migrate_redirect-1116408-39.patch3.49 KBMatt V.
PASSED: [[SimpleTest]]: [MySQL] 102 pass(es).
[ View ]
#34 migrate_redirect-1116408-34.patch3.49 KBmikeryan
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch migrate_redirect-1116408-34.patch. Unable to apply patch. See the log in the details link for more information.
[ View ]
#22 1116408_22_migrate_redirect.patch3.29 KBmikeryan
PASSED: [[SimpleTest]]: [MySQL] 102 pass(es).
[ View ]
#21 1116408_21_migrate_redirect.patch3.48 KBmikeryan
PASSED: [[SimpleTest]]: [MySQL] 102 pass(es).
[ View ]
#19 1116408_19_migrate_redirect.patch3.63 KBmikeryan
PASSED: [[SimpleTest]]: [MySQL] 102 pass(es).
[ View ]
#16 1116408_16_migrate_redirect.patch7.68 KBmarcusx
PASSED: [[SimpleTest]]: [MySQL] 102 pass(es).
[ View ]
#14 1116408_14_migrate_redirect.patch7.82 KBmarcusx
PASSED: [[SimpleTest]]: [MySQL] 102 pass(es).
[ View ]
#12 1116408_12_migrate_redirect_fix.patch1.27 KBmarcusx
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1116408_12_migrate_redirect_fix.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots.
[ View ]
#11 1116408_11_migrate_redirect_fix.patch819 bytesmarcusx
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1116408_11_migrate_redirect_fix.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots.
[ View ]
#9 1116408_9_migrate_redirect_fix.patch586 bytesmarcusx
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1116408_9_migrate_redirect_fix.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots.
[ View ]
#6 1116408_migrate_redirect.patch2.53 KBgrendzy
PASSED: [[SimpleTest]]: [MySQL] 102 pass(es).
[ View ]

Comments

Project:Migrate» Migrate Extras
Component:Code» Miscellaneous
Category:support» feature

Support for contrib modules would go into the Migrate Extras module.

I could add migration support to Redirect.module itself?

In the end I just wrote a small module to catch urls of the old format, look up the id in the migration db and redirect to the new node. But I'm not sure what the best way to write a generic migration/redirect mechanism would be.

Project:Migrate Extras» Redirect
Version:7.x-2.x-dev» 7.x-1.x-dev
Component:Miscellaneous» Code

Yes, Dave, you certainly could:-).

Not sure how this should manifest in either the Redirect or Migrate modules, if either, but here is the code i'm using in a custom migration module that extends Migrate of course and also makes use of Redirect.

In the include file for the class that extends the BaseMigration class, most of the action is in a class extending MigrateDestinationHandler, show second.

<?php
/**
* Migrate tt news from Typo3 to Press release content type.
*/
class ExamplePressReleaseMigration extends BaseMigration {
  public function
__construct() {
   
parent::__construct();
// ... bunch of stuff not relevant here, but crucially including in the query the field that has the current path alias:
     
->fields('txalias', array('value_alias'))
// ... and more stuff, including this:
   
$this->addFieldMapping('migrate_pathalias', 'value_alias');
// ... and in this case there was a need to construct the alias from possibly multiple fields:
 
public function prepareRow($currentRow) {
   
$currentRow->value_alias = example_migrate_news_path($currentRow->value_alias, 366);
  }
}
class
ExampleMigratePathHandler extends MigrateDestinationHandler {
  public function
__construct() {
   
$this->registerTypes(array('node'));
  }
  public function
fields() {
    return array(
     
'migrate_pathalias' => t('Array of existing paths for the TYPO3 page.'),
    );
  }
 
// Alternately, we could add redirects to the node array in the prepare
  // method, most likely, but going with the more aggressive way first.
 
public function complete($entity, stdClass $row) {
   
// If there's no alias in the source data, we have no choice but to bail.
   
if (!isset($entity->migrate_pathalias)) {
      return;
    }
    if (!
is_array($entity->migrate_pathalias)) {
     
$entity->migrate_pathalias = array($entity->migrate_pathalias);
    }
   
// Construct the destination ('redirect') path for nodes.
   
if (isset($entity->nid)) {
     
$destination = 'node/' . $entity->nid;
    }
   
// If we cannot determine the path of the present entity, bail.
   
if (!isset($destination)) {
      return;
    }
   
// Establish defaults and make the redirects with the above values.
   
$redirect_defaults = array(
     
'uid' => 2,
     
'status_code' => 301,
    );
   
$redirect = new stdClass();
   
redirect_object_prepare($redirect, $redirect_defaults);
   
$redirect->redirect = $destination;
    foreach (
$entity->migrate_pathalias as $path) {
     
$redirect->source = $path;
     
redirect_save($redirect);
    }
  }
}
?>

Status:Active» Needs review
StatusFileSize
new2.53 KB
PASSED: [[SimpleTest]]: [MySQL] 102 pass(es).
[ View ]

To use this handler, simply add a mapping to your migrate class like so:

<?php
$this
->addFieldMapping('migrate_redirects', 'old_legacy_path');
?>

Title:How to add redirected urls to migrated nodesSupport migrate module: redirect old urls to migrated nodes

Awesome, this is exactly what we need. I'll be testing soon and will report back.

Status:Needs review» Needs work
StatusFileSize
new586 bytes
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1116408_9_migrate_redirect_fix.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots.
[ View ]

Redirect is not saved. Because the entity_uri can not been determined due to wrong argument 'entity type'. Acctually this is not the entity type it is the entity_type_bundle_type or whatever it is called by the entity api. e.g. in a page node migration this is 'page' not 'node'. I have no idea if we can get the migrate destination type at this place to make this generic for nodes and users or whatever. For most cases 'node' would work fine.

Patch for the patched version enclosed.

<?php
 
public function complete($entity, stdClass $row) {
    
//wrong assumtion due to the variable name '$entity' $entity->type holds the nodetype, 'page' in my case
     // but we need to put 'node' or 'user' in the argument for entity_uri
   
if (($destination = entity_uri('node', $entity)) && !empty($entity->migrate_redirects)) {
      if (!
is_array($entity->migrate_redirects)) {
       
$entity->migrate_redirects = array($entity->migrate_redirects);
      }
      foreach (
$entity->migrate_redirects as $path) {
       
$redirect_defaults = array(
         
'uid' => $entity->uid,
         
'status_code' => 301,
         
'language' => $entity->language,
        );
       
$redirect = new stdClass();
       
redirect_object_prepare($redirect, $redirect_defaults);
       
$redirect->redirect = $destination['path'];
       
$parsed = redirect_parse_url($path);
       
$redirect->source = $parsed['path'];
       
$redirect->source_options['query'] = $parsed['query'];
       
redirect_save($redirect);
      }
    }
  }
?>

Hm, that is a puzzle: the handler in #6 works, but only because $entity->uri was already set by the time entity_uri() was called. As a result the (incorrect) type parameter was ignored.
I'd like to avoid hard-coding "node", so that it could work for other entities. I'm not sure what's the best way to handle this. We could just refer to $entity->uri directly, but I don't know if that's guaranteed to be set.

StatusFileSize
new819 bytes
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1116408_11_migrate_redirect_fix.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots.
[ View ]

I totaly agree that hardcoding 'node' is a bad idea. I had no time to figure out how I can get this information from migrate yesterday and needed this working. I suggest this better solution.

<?php
...
  public function
complete($entity, stdClass $row) {
   
//Looking up the destination entity type for the current Migration
   
$migration = Migration::currentMigration();
   
$destination = $migration->getDestination();
   
$entity_type = $destination->getEntityType();
    if ((
$destination = entity_uri($entity_type, $entity)) && !empty($entity->migrate_redirects)) {
      if (!
is_array($entity->migrate_redirects)) {
       
$entity->migrate_redirects = array($entity->migrate_redirects);
      }
...
?>

Patch against the patched version. Sorry for that, I know there is a way to create a follow up patch, I have to read git documentation about how this works again.

StatusFileSize
new1.27 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1116408_12_migrate_redirect_fix.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots.
[ View ]

Aehm maybe we should also rename the variable "$destination->$redirect_destination" to avoid confusion.

<?php
 
public function complete($entity, stdClass $row) {
   
//Looking up the destination entity type for the current Migration
   
$migration = Migration::currentMigration();
   
$destination = $migration->getDestination();
   
$entity_type = $destination->getEntityType();
    if ((
$redirect_destination = entity_uri($entity_type, $entity)) && !empty($entity->migrate_redirects)) {
      if (!
is_array($entity->migrate_redirects)) {
       
$entity->migrate_redirects = array($entity->migrate_redirects);
      }
      foreach (
$entity->migrate_redirects as $path) {
       
$redirect_defaults = array(
         
'uid' => $entity->uid,
         
'status_code' => 301,
         
'language' => $entity->language,
        );
       
$redirect = new stdClass();
       
redirect_object_prepare($redirect, $redirect_defaults);
       
$redirect->redirect = $redirect_destination['path'];
       
$parsed = redirect_parse_url($path);
       
$redirect->source = $parsed['path'];
       
$redirect->source_options['query'] = $parsed['query'];
       
redirect_save($redirect);
      }
    }
  }
?>

marcusx: oh, that's excellent. I'll work on a re-roll.

BTW - do you happen to know if $entity->uid and $entity->language are valid for other entity types? Or are those node properties?

Status:Needs work» Needs review
StatusFileSize
new7.82 KB
PASSED: [[SimpleTest]]: [MySQL] 102 pass(es).
[ View ]

Added validation before the redirect is saved because I got some database errors due to duplicate entries if the redirect was already existing. There is also a proper error message in the migration if this happens.

I created a complete reroll of #6 #12 and the additional changes for the validation.

This patch is against the latest dev from git.

Status:Needs review» Needs work

Thanks for the re-roll. Can you please remove tabs and trailing whitespace?

Status:Needs work» Needs review
StatusFileSize
new7.68 KB
PASSED: [[SimpleTest]]: [MySQL] 102 pass(es).
[ View ]

Here we go... sorry for the inconvenience

Status:Needs review» Needs work

Ahhh damn it! I can't set the current Migration here.

If I use

drush mfd MyMigration

I get an Fatal error.
Fatal error: Call to a member function getDestination() on a non-object in /mnt/hgfs/bk/htdocs/sites/all/modules/contrib/redirect/migrate.inc on line 19

What is quite clear because at this point there is no "current" Migration.

<?php
 
public function __construct() {
   
$this->registerTypes(array('entity'));
   
//set current migration data that all other methods can use
   
$this->migration = Migration::currentMigration();
   
$this->destination = $this->migration->getDestination();  //Line 19
   
$this->entity_type = $this->destination->getEntityType();
  }
?>

I will rework this a soon as I can, but in case s.o. else has time I just want to document it.

This would be a much appreciated addition.
Thank you all for the excellent work!

Status:Needs work» Needs review
StatusFileSize
new3.63 KB
PASSED: [[SimpleTest]]: [MySQL] 102 pass(es).
[ View ]

So close! Just needed to put off pulling stuff dependent on the active migration to complete() (note we now have a static message display function that will work anywhere without a Migration object).

Status:Needs review» Needs work

Oops! Caching the entity_type breaks when running a sequence of disparate migrations, since there's only one handler instance ever, not one per entity type... New patch coming.

Status:Needs work» Needs review
StatusFileSize
new3.48 KB
PASSED: [[SimpleTest]]: [MySQL] 102 pass(es).
[ View ]

StatusFileSize
new3.29 KB
PASSED: [[SimpleTest]]: [MySQL] 102 pass(es).
[ View ]

Some tweaks, in particular saving messages as informationals in the migrate message table rather than spewing them out.

Status:Needs review» Reviewed & tested by the community

Patch #22 seems to be working quite well. Thanks for the great work!

Before committing, I just want to make sure it's properly credited - I just added the final tweaks, grendzy and marcusx did most of the work.

Should the file not be called redirect.migrate.inc for consistency with other projects?

StatusFileSize
new3.7 KB
PASSED: [[SimpleTest]]: [MySQL] 102 pass(es).
[ View ]

Patch #22 is also missing the hook_migrate_api(). I've added that in and renamed the file "redirect.migrate.inc" to be consistant with every other module implementing migrate support.

I haven't contributed anything new to this patch, credit goes to marcusx and grendzy and others.

Sweet, so this is passing, but can I get a little hint on how to test it out?

I'm working on a migration currently, and one of my content types (let's say article) is migrating fine. I also have the:

<?php
$this
->addFieldMapping('path', 'path');
?>

I've applied the patch, and have it applied cleanly with patch p1 < *.patch.

What do I add to my current node migration?

Edit:
I'm migrating from path_redirect

sirkitree: addFieldMapping() is all. The first parameter is literally 'migrate_redirects', and the second parameter is the name of a field in your source data.

This worked perfectly for me. Thank you, saved me so much time.

#26 doesn't work as expected, then enabled migrate extras and pathauto module. I use following code for migration:

//We generate new URL during migration
    $this->addFieldMapping('pathauto')
         ->defaultValue(1);
    //We save redirect from old legacy URL to new legacy URL
    $this->addFieldMapping('migrate_redirects', 'old_url');

But in redirect.migrate.inc in complete function I have entity:

stdClass Object
(
[title] => Nissan cars
...
[migrate_redirects] => ?go=obzor&amp;oid=7
[type] => articles
...
[path] => Array
(
[pathauto] => 1
[alias] =>
)
...

My old url - ?go=obzor&oid=7 and my new url should be /article/1 but I got /node/1. How can I tell to MigrateRedirectEntityHandler pathauto generated alias?

Priority:Normal» Critical
Status:Reviewed & tested by the community» Needs work

As I wrote, patches #22, #26 needs work to integrate with pathauto. When I go to url /?go=obzor&oid=7 then it 301 redirect to /node/1 and then it 301 redirect /article/1. I think its because pathauto runs after node creation and migrate redirect runs before.

Priority:Critical» Normal
Status:Needs work» Reviewed & tested by the community

Pathauto generation does not have anything to do with this issue.

Besides, it should already work just fine if pathauto is configured correctly. In my case I was fine not adding anything to my migration classes, because the path is usually created automatically during node save...

When I go to url /?go=obzor&oid=7 then it 301 redirect to /node/1 and then it 301 redirect /article/1.

This sounds like it is working, no? What is it that you're expecting?

Status:Reviewed & tested by the community» Needs work

No, it should set redirect from /?go=obzor&oid=7 to /article/1 in redirect module, but I have /?go=obzor&oid=7 to /node/1 and in path auto /node/1 to /article/1. And when I run migrate, I have a lot of notices here http://site.local/#overlay=admin/content/migrate/messages/NodeArticles like this:
Undefined index: path File /Users/macspro/Sites/site.local/sites/all/modules/migrate_extras/redirect.migrate.inc, line 73(file: /Users/macspro/Sites/site.local/sites/all/modules/migrate_extras/redirect.migrate.inc, line 73)

It happens because pathauto runs after we generate redirect with redirect.migrate.inc. As you can see in #30 (I have following data in complete function in redirect.migrate.inc):

stdClass Object
(
[title] => Nissan cars
...
[migrate_redirects] => ?go=obzor&amp;oid=7
[type] => articles
...
[path] => Array
(
[pathauto] => 1
[alias] =>
)
...

Status:Needs work» Needs review
StatusFileSize
new3.49 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch migrate_redirect-1116408-34.patch. Unable to apply patch. See the log in the details link for more information.
[ View ]

@dillix: I see no problem with the indirect 301 redirect, everything ends up as it should be. We don't know if and when pathauto will be creating an alias (and note that in migrations many people disable pathauto during migration and generate aliases in batch afterwards), so it's simplest and safest to just establish the redirect to the canonical address - it all works out in the end.

As for the notices, your paths don't have a 'path' component, just a query string - this updated patch should address it. Also note that I've moved hook_migrate_api() to the migrate.inc file, no need to have it in .module.

Status:Needs review» Needs work

The last submitted patch, migrate_redirect-1116408-34.patch, failed testing.

Title:Support migrate module: redirect old urls to migrated nodesSupport migrate module: Destination handler class

I have just created another issue about migrate, which is not exactly the same of this at #1607038: Support migrate module: Individual destination class

As I mention there, I could merge the code here if maintainers thinks it's better.

Status:Needs work» Needs review

#34: migrate_redirect-1116408-34.patch queued for re-testing.

Status:Needs review» Needs work

The last submitted patch, migrate_redirect-1116408-34.patch, failed testing.

Status:Needs work» Needs review
StatusFileSize
new3.49 KB
PASSED: [[SimpleTest]]: [MySQL] 102 pass(es).
[ View ]

Here's an updated patch that is applying cleanly for me.

StatusFileSize
new3.63 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch migrate_redirect-1116408-40.patch. Unable to apply patch. See the log in the details link for more information.
[ View ]

This works nicely, but as grendzy pointed out above, it requires you to map UID and language, which don't exist for all entities (taxonomy terms, for example). This patch adds isset() checks on these two properties.

Also, more generally, does it even make sense that the redirect would get the UID and language of the entity?

Status:Needs review» Needs work

The last submitted patch, migrate_redirect-1116408-40.patch, failed testing.

StatusFileSize
new206.58 KB

I've tried the patches in #26 and #39, and in both cases I'm running into a problem where in the 'from' field of the redirect it parses the url such that there is a '/' in front. This is a problem since the beginning of the path is forced to be "http://localhost/drupal1/".

So if "http://localhost/drupal1/scholars/index" goes through the migration, I end up with
"http://localhost/drupal1//scholars/index" instead, and the // results in a page not found.

screenshot attached

39 worked for me - helped create redirects for over 2000 nodes. Thanks!

This worked great for me. Using something like the following called from prepareRow() to lookup path_redirect module redirects.

<?php
 
/**
   * Return old redirect for given row.
   */
 
public function getRedirect(&$row) {
   
migrate_instrument_start('MyMigration: get redirect');
   
$old_redirect = 'node/' . $row->nid;
   
$results = $this->getConnection()
      ->
select('path_redirect', 'pr')
      ->
fields('pr', array('source'))
      ->
condition('pr.redirect', $old_redirect)
      ->
execute();
    if (!empty(
$results)) {
      foreach (
$results as $result) {
       
$row->redirect[] = $result->source;
      }
    }
   
migrate_instrument_stop('MyMigration: get redirect');
  }
?>

Status:Needs work» Needs review
StatusFileSize
new3.71 KB
PASSED: [[SimpleTest]]: [MySQL] 101 pass(es).
[ View ]

For Migrate 2.5 and greater, handlers should be explicitly registered in hook_migrate_api().

Tested the patch in #45, works great. Just one question on the syntax: how would I write a field mapping rule to import multiple legacy redirects for 1 node?

#45 worked perfectly for me, thanks

@brunodbo - not a matter of syntax, what you need to do is populate the source field in your mapping with an array of the redirects you want (presumably in prepareRow).

#45 worked great for me, as well. I love that it implements the rollback too. Thanks everyone for putting this together!

Status:Needs review» Reviewed & tested by the community

At this point, I think we can consider it reviewed and tested ;-)

Status:Reviewed & tested by the community» Needs work

I just noticed a minor issue when adding redirects for users (users which had in turn been created through another migration). The entity->language was apparently set as an empty string, so it was passing the "isset" conditional. Apparently redirects don't work if the language column is a blank string. It's an easy fix, just have to also test for blank strings. I will try to post my fix as a patch, just a temporary heads up until I get the time.

Status:Needs work» Needs review
StatusFileSize
new3.84 KB
PASSED: [[SimpleTest]]: [MySQL] 101 pass(es).
[ View ]

Very sorry for the delay, here is that patch I promised above.

StatusFileSize
new4.39 KB
PASSED: [[SimpleTest]]: [MySQL] 101 pass(es).
[ View ]

The patch in #52 did not work for me (using Migrate 2.5 - the latest stable version). Wrapping a line of the hook_migrate_api() implementation in an array did the trick. Turning:

+++ b/redirect.migrate.incundefined
@@ -0,0 +1,104 @@
+    'api' => 2,
+    'destination handlers' => 'MigrateRedirectEntityHandler',
+  );
+  return $api;
+}

Into:

+++ b/redirect.migrate.incundefined
@@ -0,0 +1,104 @@
+    'api' => 2,
+    'destination handlers' => array(
+      'MigrateRedirectEntityHandler',
+    ),
+  );
+  return $api;
+}

Patch rerolled and attached.

Patch in #53 works for me.

Patch 53 worked for me. Thank you very much.

Status:Reviewed & tested by the community» Needs review

patch 53 works, thx. Tested on nodes and files.

Status:Needs review» Reviewed & tested by the community

Status:Needs review» Reviewed & tested by the community

Status:Reviewed & tested by the community» Needs review
StatusFileSize
new893 bytes
PASSED: [[SimpleTest]]: [MySQL] 101 pass(es).
[ View ]
new3.88 KB
PASSED: [[SimpleTest]]: [MySQL] 101 pass(es).
[ View ]

The patch in #53 includes a leading slash for absolute URLs. For example, "http://example.com/foo" ends up saving a redirect of "/foo" instead of "foo". (Note: the UI prevents leading slashes from being added to redirects).

The attached patch is #53 plus an ltrim() on the parsed path. Interdiff attached, or @line 81:

<?php
$redirect
->source = isset($parsed['path']) ? $parsed['path'] : '';
?>

becomes

<?php
$redirect
->source = isset($parsed['path']) ? ltrim($parsed['path'], '/') : '';
?>

#53 worked for me on nodes. Really appreciate the work on this.

Status:Needs review» Needs work

#59 is working great for me.
Thanks!!

Very minor docs changes:

+++ b/redirect.migrate.incundefined
@@ -0,0 +1,106 @@
+   * Validate a redirect.

"summary lines must start with a third person singular present tense verb" ("Validates") and should have an extra newline.

+++ b/redirect.migrate.incundefined
@@ -0,0 +1,106 @@
+   * This function is simmilar to the validate function in the

"simmilar" should be "similar"

These patches don't appear to be working for me. I've tried both #53 and #59. I'm using Redirect 7.x-1.0-rc1. After migrating my Wordpress site to Drupal and having pathauto generate new aliases, when I point my browser to any of my old paths on my new Drupal site, it takes me to the front page of my blog rather than giving me a 301 HTTP code.

I noticed that when I migrated my content and chose the option "Have pathauto generate new aliases," I got this message: "You have the Redirect module enabled. To be able to generate redirects for your imported WordPress content, you need to patch Redirect." This was displaying after I'd patched Redirect. Does this message go away after patching, or no? I'm not getting an option to generate redirects. Does this indicate that the patch hasn't worked?

My husband (oseldman) has also suggested that due to the format of my Wordpress paths (for example: http://littleenglishgirl.com/?p=1171) this method of redirecting may not work at all - does anyone have similar paths, and if so, did this method work? If not, is there something else I can try? Thanks.

I realized I was patching 7.x-1.0-rc1 rather than the dev version. I patched the dev version with #59 and the option to generate redirects appeared.

Even with the patch seemingly working, redirects still aren't being generated. Any thoughts as to why that might be happening? Sorry for bombarding the issue queue. Thanks.

Status:Needs work» Needs review
StatusFileSize
new3.9 KB
PASSED: [[SimpleTest]]: [MySQL] 101 pass(es).
[ View ]

This is the patch in #59 with fixes from #61 applied and with coder review done. It works for me.

PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'xJMoIg4sq_0tnmtrrKRhOC6-2F1yga28A75jvr3tXCY' for key 'hash': INSERT INTO {redirect} (hash, type, source, source_options, redirect, redirect_options, language, status_code, count, access) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9); Array ( [:db_insert_placeholder_0] => xJMoIg4sq_0tnmtrrKRhOC6-2F1yga28A75jvr3tXCY [:db_insert_placeholder_1] => redirect [:db_insert_placeholder_2] => magazines/quiltsandmore/qam-table-contents-old_1.html [:db_insert_placeholder_3] => a:0:{} [:db_insert_placeholder_4] => node/32553 [:db_insert_placeholder_5] => a:0:{} [:db_insert_placeholder_6] => und [:db_insert_placeholder_7] => 0 [:db_insert_placeholder_8] => 0 [:db_insert_placeholder_9] => 0 ) in drupal_write_record() (line 7158 of /app/web/divinecaroline.com/includes/common.inc).

I guess, there might be multiple redirects in redirect table..

In migration, how to solve it.

As we are using Html (Static files) to Drupal migration.

StatusFileSize
new4.12 KB
PASSED: [[SimpleTest]]: [MySQL] 101 pass(es).
[ View ]

This version of the patch in #65 fixes some Coder complaints, and also allows for multiple redirects. Checking $entity for "migrate_redirects", at least in my environment, would only ever return one redirect to evaluate. Checking $row->migrate_redirects however returned an array of redirects defined in my mapping, which correctly saved multiple redirects for a given entity.

StatusFileSize
new4.75 KB
PASSED: [[SimpleTest]]: [MySQL] 101 pass(es).
[ View ]

Sorry, use this one instead. This works in my environment for cases with one or multiple redirects.

StatusFileSize
new4.78 KB
PASSED: [[SimpleTest]]: [MySQL] 101 pass(es).
[ View ]

Found another issue. Here's a new version of the patch.

Issue summary:View changes

add summary

Issue summary:View changes
Status:Needs review» Reviewed & tested by the community

I ran this through a handful of redirect migrations using the structure:

$this->addFieldMapping('migrate_redirects', 'old_path')
        ->defaultValue('MigrateRedirectEntity');

What I tested:
Redirects on Users
Redirects on Nodes
Redirects on Terms
Redirects using a separator (comma)
Redirects that produced the error "The source path is already being redirected."

Code looks solid as well. I think this is good to commit!

I have just used this patch for the second time now and it works fine.

Also think it is good to commit.

I am adding a related issue: #1607038: Support migrate module: Individual destination class.

The patch works as expected so far, updating migrated taxonomy terms.

Any chance this could get committed?

+1 from me. I'm using this patch for Migrate support, and I've had no problems. Works as advertised!

I've used this several times as well without issues.

Status:Reviewed & tested by the community» Needs work

+++ b/redirect.migrate.inc
@@ -0,0 +1,139 @@
+        $redirect->redirect = $redirect_destination['path'];
+        $parsed = redirect_parse_url($path);
+        $redirect->source = isset($parsed['path']) ? ltrim($parsed['path'], '/') : '';
+        if (!empty($parsed['query'])) {
+          $redirect->source_options['query'] = $parsed['query'];
+        }

Shouldn't there be a redirect_parse_url on the destination path? In case it has query string parameters?