Disclaimer

This is a simple solution that I have implemented because the contrib Nodewords to Metatag solution didn't work for me.

Assumptions

I am using the following modules:

For this to work, I have created a custom class that is suggested for the Drupal to Drupal migration. Nothing special. I do have my legacy Drupal 6 database on the same MySQL server. Also, I have defined the connection to this database in my Drupal 7 settings.php file like so:

$databases = array (
  'default' =>
  array (
    'default' =>
    array (
      'database' => 'drupal7',
      'username' => 'root',
      'password' => 'root',
      'host' => 'localhost',
      'port' => '',
      'driver' => 'mysql',
      'prefix' => '',
    ),
  ),
  'legacy' =>
  array (
    'default' =>
    array (
      'database' => 'drupal6',
      'username' => 'root',
      'password' => 'root',
      'host' => 'localhost',
      'port' => '',
      'driver' => 'mysql',
      'prefix' => '',
    ),
  ),
);

I am running this on a Vagrant -> so those auth perms should be familiar. Of course, your production environment would be different.

Prepare Row Method

My VSCPage6Migration Class contains the prepareRow method as well as a custom query function.

  public function prepareRow($row) {
    // Always include this fragment at the beginning of every prepareRow()
    // implementation, so parent classes can ignore rows.

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

    /**
     * We need to pull the Nodewords from a legacy DB table that has no
     * contemporary Drupal fields.
     */
    $nodewords = $this->queryNodeWords($row->nid);

    /**
     * These are the ones we are interested in keeping.
     */
    $metatags = array(
      'title' => 'metatag_title',
      'description' => 'metatag_description',
      'abstract' => 'metatag_abstract',
      'keywords' => 'metatag_keywords',
      'robots' => 'metatag_robots',
    );
    
    /**
     * Other MetaTag options are:
     *
     * 'metatag_news_keywords',
     * 'metatag_standout',
     * 'metatag_generator',
     * 'metatag_copyright',
     * 'metatag_image_src',
     * 'metatag_canonical',
     * 'metatag_shortlink',
     * 'metatag_publisher',
     * 'metatag_author',
     * 'metatag_original-source',
     * 'metatag_revisit-after',
     */

    /**
     * Because these "fields" do not exist in the Source, we fake it.
     */
    foreach ($metatags as $key => $value) {
      if (!empty($nodewords[$key])) {
        $row->{'nodeword_' . $key} = $nodewords[$key];
      }
      else {
        if ($key == 'title') {
          $row->{'nodeword_' . $key} = $row->title;
        }
        else {
          $row->{'nodeword_' . $key} = '';
        }

      }
    }

    /** 
     * We need to return TRUE so that the Migration knows to implement this
     * method.
     */
    return TRUE;
  }

The helper function is:

  /**
   * Helper function to get all the current Nodewords from the Legacy DB by NID.
   *
   * @param $legacy_nid
   * @return array
   */
  protected function queryNodeWords($legacy_nid) {
    $return = array();

    $query = Database::getConnection('default', 'legacy')
      ->select('nodewords', 'nw')
      ->fields('nw', array('name', 'content'))
      ->condition('nw.id', $legacy_nid, '=');
    $result = $query->execute();

    foreach ($result as $record) {
      $value = unserialize($record->content);
      $return[$record->name] = $value['value'];
    }

    return $return;
  }

Fun stuff.

Implementation in the VSCPage6Migration __construct method

The constructor method is usually where the fields mapping take place.So the following code goes into there.

First, remember to designate what fields you are NOT wanting to map:

    /**
     * Destinations to Ignore.
     */
    $destinations_unmigrated = array(
      'metatag_news_keywords',
      'metatag_standout',
      'metatag_generator',
      'metatag_copyright',
      'metatag_image_src',
      'metatag_canonical',
      'metatag_shortlink',
      'metatag_publisher',
      'metatag_author',
      'metatag_original-source',
      'metatag_revisit-after',
    );
    $this->addUnmigratedDestinations($destinations_unmigrated);

Notice that is ONLY Destinations. NodeWords doesn't use the modern field implementation that is now so common. Therefore, we don't have to add them to $this->addUnmigratedSources($source_unmigrated) - that is why I said I was "faking it" in the comments above.

Second, we get to actually mapping the fields. We did all the prep work above, now let's use it! Again, further along in the __constructor we will add:

    /**
     * Nodewords -> Metatags.
     *
     * Mapping to the real fields in the Destination from the "fake" fields
     * in the Source row.
     */
    $this->addFieldMapping('metatag_title', 'nodeword_title');
    $this->addFieldMapping('metatag_description', 'nodeword_description');
    $this->addFieldMapping('metatag_abstract', 'nodeword_abstract');
    $this->addFieldMapping('metatag_keywords', 'nodeword_keywords');
    $this->addFieldMapping('metatag_robots', 'nodeword_robots');

Here, we are assigning our fake fields (added in the prepareRow) to the real Metatag ones.

Conclusion

This solution is great for smaller projects and not those with 500,000 nodes simply because a select query is expensive. Mike Ryan has a great tutorial on how to override the query function that helped me out alot.

The above code should be good enough to paste into your custom Classes and run ... although you should probably count on it to break the first time around :p

Comments

fcaspani’s picture

Hi,
Your queryNodeWords function not works because SQL query returns a null object, so i correct SQL query and remove unserialize from $record->content (in foreach) :

protected function queryNodeWords($legacy_nid) {
    $return = array();
    $query = Database::getConnection('default', 'legacy')
      ->select('nodewords', 'nw')
      ->fields('nw')
      ->condition('id', $legacy_nid, '=');
    $result = $query->execute();

    foreach ($result as $record) {
      $value = $record->content;
      $return[$record->name] = $value;
    }

    return $return;
  }
Summit’s picture

Hi,

Please add the whole module to this thread to get this working please? I want to use my nodewords on all nodetypes to migrate to the correct metatag fields.
Thanks a lot in advance for your reply!
Greetings, Martijn

Summit’s picture

Hi,
Does anyone have this used? Could he/she attach the whole module please?
Thanks a lot in advance,
greetings, Martijn