1

In my continued frustration with trying to extend the 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 on the mapping, something like:

->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.

1 Answer 1

1

The 'Undefined property' during migration errors are usually related wrong passing of unprepared rows, sometimes because of typos in the field name. By default prepareKey() is called before prepareRow() and you can specify which source key to use by overriding the default behaviour and by defining your own prepareKey() method in your class. This is especially needed when your source data doesn't have any primary key and you need to define one.

See this post explaining that by the following example:

What the MigrateSQLMap constructor means:

$this->map = new MigrateSQLMap($this->machineName,
             array(
               'muid' => array(
                 'type' => 'int',
                 'not null' => true,
               ),
             ),
             MigrateDestinationUser::getKeySchema()

What this is saying is, take the muid value from your source row and use that to populate sourceid1 in the map table. If you source query has a column which is a unique identifier for each row, you should be using the name of that column instead of muid here. If your source data doesn't have a handy primary key and you need to construct one name muid, then you would do that in prepareKey() instead of prepareRow (NOT by doing it in prepareRow and calling that).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.