In my continued frustration with trying to extend the outdated wordpress_migrate module, I have run into another problem with migrate.

Wordpress uses two unique identifiers in it's categories - nicename and term_id. I don't know why. Nicename is used for matching parent categories, and as the unique identifier in blog posts. However, in custom content types that are exported, they use the term_id in their fields. Here's an example:
<wp:category><wp:term_id>41069</wp:term_id><wp:category_nicename><![CDATA[daly]]></wp:category_nicename><wp:category_parent><![CDATA[nt2]]></wp:category_parent><wp:cat_name><![CDATA[Daly]]></wp:cat_name></wp:category>

Currently the nicename is being used as the source id, like so:

$this->map = new MigrateSQLMap($this->machineName,
      array(
        'wp:category_nicename' => array(
          'type' => 'varchar',
          'length' => 255,
          'not null' => TRUE,
          'description' => 'WordPress category machine name',
        ),
      ),
      MigrateDestinationTerm::getKeySchema()
    );

$fields = array(
      'wp:category_nicename' => 'Unique "machine name" of the category',
      'wp:category_parent' => 'Category parent (nicename?)',
      'wp:cat_name' => 'User-friendly category name',
      'wp:category_description' => 'Description of category',
    );

// Construct the source and destination objects.
    $source_options = array(
      'reader_class' => 'MigrateXMLReader',
      'cache_counts' => TRUE,
    );
    $this->source = new MigrateSourceXML($this->wxrFile, '/rss/channel/category',
      'wp:category_nicename', $fields, $source_options, $this->arguments['namespaces']);
    $this->destination = new MigrateDestinationTerm($this->arguments['category_vocabulary']);

However, this is no good for the sourceMigration when I am trying to use the term id. In my head I thought it would logically work like so

$this->map = new MigrateSQLMap($this->machineName,
      array(
        'wp:term_id' => array(
          'type' => 'int',
          'not null' => TRUE,
          'description' => 'WordPress category term id',
        ),
        'wp:category_nicename' => array(
          'type' => 'varchar',
          'length' => 255,
          'not null' => TRUE,
          'description' => 'WordPress category machine name',
        ),
      ),
      MigrateDestinationTerm::getKeySchema()
    );

$fields = array(
      'wp:term_id' => 'Unique id of the category',
      'wp:category_nicename' => 'Unique "machine name" of the category',
      'wp:category_parent' => 'Category parent (nicename?)',
      'wp:cat_name' => 'User-friendly category name',
      'wp:category_description' => 'Description of category',
    );

// Construct the source and destination objects.
    $source_options = array(
      'reader_class' => 'MigrateXMLReader',
      'cache_counts' => TRUE,
    );
    $this->source = new MigrateSourceXML($this->wxrFile, '/rss/channel/category',
      'wp:category_nicename', $fields, $source_options, $this->arguments['namespaces']);
    $this->destination = new MigrateDestinationTerm($this->arguments['category_vocabulary']);

and then
->addMigration('Migration', $source_key = 'wp:term_id');

Or something like that. But there doesn't seem to be any way of doing this that I can figure out. When I create the migration with the two columns as above it creates the source1 and source2 columns as I would expect, but I get a series of these errors:

Could not save to map table due to NULL value for key field wp:category_nicename
Undefined property: stdClass::$wp:category_nicename File /app/docroot/sites/all/modules/contrib/migrate/includes/migration.inc, line 943(file: /app/docroot/sites/all/modules/contrib/migrate/includes/migration.inc, line 943)

Even then, I don't think there's a way to specify which source key to use in addMigration. I can't find an issue that is related that helps me here, trust me I've read them.

Comments

michaelmallett created an issue.

stevesirois@gmail.com’s picture

I stumble in this issue and here's my workaround in 2 steps:

1) You must override the prepareKey() function because, for the XML source class, if you add more then one primary key, the following keys are not included in the $key array because it miss the '->xml->'.

  public function prepareKey($source_key, $row) {
    $key = array();
    foreach ($source_key as $field_name => $field_schema) {
      $key[$field_name] = $row->xml->$field_name;
    }
    return $key;
  }

2) In the prepareRow(), you must re-assign the value of your others keys because it's missing (therefore the error msg vs NULL; here what I got : Could not save to map table due to NULL value for key field no_avis). But, this seems to happen only if you don't update/insert the record!? In my case, my second key field was no_avis so here the snippet of my code in prepareRow() :

  public function prepareRow($row) {

    if (parent::prepareRow($row) === FALSE) {
      return FALSE;
    }

    if ($row->xml->sous_domaine == '99') {
      // Dont update this record but make sure the second primary is present otherwise NULL error msg
      $row->no_avis = $row->xml->no_avis;
      return FALSE;
    } else {
      return TRUE;
    }
  }

Hope this put you on the right track!