I've a content type with CCK Link field in my old site.
How can I migrate data from this field (title and URL) to Link field in D7 site using Migrate module?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mikeryan’s picture

Project: Migrate » Migrate Extras
Version: 7.x-2.0-beta2 » 7.x-2.x-dev
Component: Code » CCK

Support for contrib modules would go into Migrate Extras.

To do this, you would need to implement a destination handler. For examples, the best place to look is in the migrate module, in plugins/destinations/fields.inc, where the support for core CCK fields is.

royjs’s picture

FileSize
954 bytes

I did a little something implemeting a MigrateFieldHandler. The problem with using a MigrateFieldHandler is that the fields have already been added so you're stuck with one field to fill two values (title and url). What I did, (which is sort of a hack) is concat the two values with a pipe (|) in my query and split them in the prepare method.

I joined the code to this post. All you have to do is change the file extension to .inc, copy it in the migrate_extras directory and add it in the migrate_extras.info list of files.

I also tried to use a MigrateDestinationHandler but I couldn't figure out how to remove the field added by the FieldsNodeHandler. And after I added my two new fields I wasn't sure how to deal with them in the prepare method either. I think the best would be to find a way to implement a MigrateFieldHandler that could split the field so it can have two mappings, one for his url column and one for his title column.

zabelc’s picture

FileSize
1.5 KB

@royjs I like the idea of being able to map different parts of the link field using separate top-level fields; but in the interim it strikes me that you might be able to meet this need without field concatenation by using arguments similar to the way the text and summary field supports an attribute for the summary or excerpt. The client side of this API is demonstrated in the BeerNodeMigration (around line 343 of beer.inc) in the way the body excerpt is mapped. Perhaps you could default to supporting the url via the normal mapping, and allow the title field to be mapped as an argument.

All that said, I tried your patch, and needed to modify a few things to get it to work (it may be because I'm currently pointing to the Dev stream of the migrate module). I've attached my updated version to this comment.

royjs’s picture

FileSize
997 bytes

Thanks a lot, that's exactly the kind of solution I was looking for.

I changed the class to use an argument. You'll have to change a few things to make it work on 7.x-2.x-dev since I'm using 6.x-2.x-dev.

It can be used like this (title and url being the fields names in the source database) :

$arguments = MigrateLinkFieldHandler::arguments(array('source_field' => 'title'));
$this->addFieldMapping('field_url', 'url')
->arguments($arguments);

BTMash’s picture

@zabelc, how do you work with multiple values in the arguments? That is one part that I have been struggling with over the course of this. Any help you can provide w/ your solution would be helpful :)

Edit: Nevermind - seems like you went with the separator route which would work :)

mikeryan’s picture

Status: Active » Needs work

See also #943140: Support migration into phone fields.

The argument handling looks wrong - in the function, $arguments['source_field'] should hold the name of the source field containing the desired title value.

royjs’s picture

I'm not sure to understand what you mean when you say that the argument handling looks wrong.
The file I submitted in #4 works fine for me.

Are you talking about the MigrateLinkFieldHandler argument ?
If I'm not mistaken, in my example this line :
$arguments = MigrateLinkFieldHandler::arguments(array('source_field' => 'title'));
means that MigrateLinkFieldHandler will receive an argument containing the value of the 'title' source field, which is what we need. Of course you have to change 'title' to the name of the field for the link's title in your source database.

damien_vancouver’s picture

I've fixed up the patch from #4 so that it has correct (Migrate 7.x-2.x style) argument handling code.

I also added some comments in link.migrate.inc showing how to use it.

The attached patch is against 7.x-2.0-rc1 (but will probably work for 7.x-2.x as well, or I can reroll if needed).
The MigrateFieldHandler is implemented in link.migrate.inc, which is included from migrate_extras.info.

Instructions on use, from the comments:

/* The main mapped source field is inserted into the URL of the link.
 * If you also have a title for the link, you should create
 * a MigrateLinkFieldHandler::arguments object and
 * pass it either a mapping for the link title, or a string to
 * use as all the titles.  
 * 
 * The example field mapping code below shows how to import URLs:
 *              - with no title, just the URL value
 *              - with the title mapped from another source field
 *              - with a literal string title shared by all imported links
 * 
 * Note that these code snippets must go into your Migration
 * subclass's constructor - see the migrate_example module
 * for an example of how and where to use field mappings.
 * 
 *  // Import source field "url" containing an URL into 
 *  // destination field field_link with no title:
 *  $this->addFieldMapping('field_link', 'url');
 *  
 *  // Import source field "url" containing an URL into
 *  // destination field: field_link, using 
 *  // source field "url_title" as the title:
 *  $arguments = MigrateLinkFieldHandler::arguments(array('source_field' => 'url_title'));
 *  $this->addFieldMapping('field_link', 'url')
 *       ->arguments($arguments);
 *       
 *  // Import source field "url" containing an URL into
 *  // destination field: field_link, using
 *  // the static string: "View Details" as the title:
 *  arguments = MigrateLinkFieldHandler::arguments('View Details');
 *  $this->addFieldMapping('field_link', 'url')
 *       ->arguments($arguments);
 */
damien_vancouver’s picture

ack, some bad grammar in my comments.. fixed for attached #9 patch.

rt_davies’s picture

Thanks everyone for the contributions. I've almost got patch #9 working for me, with one minor problem. I don't know if it's my mapping or the field handler. In short, the field mapping has a separator on it, which is working for the URL, but not for the title.

Do I need to add a separator to the arguments array or something?

Mapping:
$arguments = MigrateLinkFieldHandler::arguments(array('source_field' => 'ext_ref_titles'));
$this->addFieldMapping('field_external_refs', 'ext_ref_urls')
->arguments($arguments)
->separator('|');

Result in my field table:
URL Title
http://example.com/dest1.html Title 1|Title 2
http://example.com/dest2.html Title 1|Title 2

FrequenceBanane’s picture

With #9 patch, I get the following error message : Fatal error: Declaration of MigrateLinkFieldHandler::prepare() must be compatible with that of MigrateFieldHandler::prepare() in [...]/sites/all/modules/migrate_extras/link.inc on line 85

With the last release of Migrte, MigrateFieldHandler::prepare() seems to have changed and so must do MigrateLinkFieldHandler::prepare()

grendzy’s picture

Status: Needs review » Closed (duplicate)

According to the migrate project page, adding the handler to the link module directly is preferred. Given that the link maintainer has already opened #1010850: Update MigrateFieldHandler to work with migrate-7.x-2.4 and later, I think this should be marked as a duplicate.

philipz’s picture

I removed stdClass from first argument of prepare function and it fixed problem #11.

commonpike’s picture

Given that its still (2 years later) not in the link module, and its pretty hard to uninstall / upgrade the link module to a *-dev version on working site, it would be nice if this code was in the extras ... i'm glad its here and i'm patching.