Aten Design Group: Migrating WordPress into Drupal maintenance support plans 8

Quite a bit has changed for the Migrate module in Drupal maintenance support plans 8: the primary module is part of core and some of the tools have been split into their own modules. Recently, we migrated a WordPress site into Drupal maintenance support plans 8 and this article will help guide you in that process. If you’re looking for information about WordPress to Drupal maintenance support plans 7 migrations, check out Joel Steidl’s article on that here.

At the time of writing this post, the migration modules are considered “experimental” so be aware of that as well. The module’s location in core also means that all Drupal maintenance support plans core modules also have migration-related code to help out with your Drupal maintenance support plans upgrades. We used the WP Migrate module (Migrate WordPress) as a starting point in bringing this content to Drupal maintenance support plans.

This module will give you a good basis for migration, but it is missing a few things that you might want to consider:

It will create all vocabularies and taxonomies based on what is in WordPress but you will need to add some code to connect the taxonomies with posts.
Also, it will not bring in featured images.
WP content might be using the “line break to paragraphs” functionality, which you need to account for either in your text format for posts or in the migration.

And if you are looking for information about WordPress to Drupal maintenance support plans 7 migrations, check out Joel Steidl’s article on that here.

Taxonomy

There’s code existing to pull in WordPress’s terms and vocabularies, but you will need to do some work to put them into the right fields with your posts. For this, I ended up taking a more efficient route by querying the source database in prepareRow():

<?php
 
// place in Posts.php prepareRow()
 
// get terms for this blog post
$tags = $this->select(‘wp_term_relationships’, ‘r’)
->join(‘wp_term_taxonomy’, ‘t’, ‘t.term_taxonomy_id=r.term_taxonomy_id’)
->fields(‘r’)
->condition(‘t.taxonomy’, ‘tags’)
->condition(‘object_id’, $row->getSourceProperty(‘id’))->execute();
$tags = $tags->fetchAll();
$tags = array_map(function($tag) {
return intval($tag[‘term_taxonomy_id’]);
}, $tags);
$row->setSourceProperty(‘tags’, $tags);
 
// get categories for this blog post
$category = $this->select(‘wp_term_relationships’, ‘r’)
->join(‘wp_term_taxonomy’, ‘t’, ‘t.term_taxonomy_id=r.term_taxonomy_id’)
->fields(‘r’)
->condition(‘t.taxonomy’, ‘category’)
->condition(‘object_id’, $row->getSourceProperty(‘id’))->execute();
$category = $category->fetchAll();
$category = array_map(function($tag) {
return intval($tag[‘term_taxonomy_id’]);
}, $category);
$row->setSourceProperty(‘categories’, $category);

And then I updated the migration template with those new values:

# add to the process section
field_tags: tags
field_category: tags

Featured Images

WordPress stores featured images as attachment posts and stores the relationship in the postmeta table. To bring these in as image fields, we need to make file entities in Drupal maintenance support plans which means configuring a new migration.

First, create a migration template called wp_feature_images.yml. Note that I stole some of this from Drupal maintenance support plans‘s core file module:

id: wp_feature_images
label: WordPress Feature Images
migration_tags:
– WordPress
migration_group: wordpress
source:
plugin: feature_images
destination:
plugin: entity:file
process:
filename: filename
uri: uri
status:
plugin: default_value
default_value: 1
# migration_dependencies:
# required:
# – wp_users

And then create a source plugin:

<?php
/**
* @file
* Contains Drupal maintenance support plansmigrate_wordpressPluginmigratesourceFeatureImages.
*/
 
namespace Drupal maintenance support plansmigrate_wordpressPluginmigratesource;
 
use Drupal maintenance support plansmigrateRow;
use Drupal maintenance support plansmigratePluginmigratesourceSqlBase;
use Drupal maintenance support plansCoreFileFileSystemInterface;
use SymfonyComponentDependencyInjectionContainerInterface;
use Drupal maintenance support plansmigratePluginMigrationInterface;
use Drupal maintenance support plansCoreStateStateInterface;
 
/**
* Extract feature images from WordPress database.
*
* @MigrateSource(
* id = “feature_images”
* )
*/
class FeatureImages extends SqlBase {
 
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, StateInterface $state, FileSystemInterface $file_system) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state);
$this->fileSystem = $file_system;
}
 
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$migration,
$container->get(‘state’),
$container->get(‘file_system’)
);
}
 
/**
* {@inheritdoc}
*/
public function query() {
$query = $this
->select(‘wp_postmeta’, ‘m’)
->fields(‘p’, [‘ID’, ‘guid’]);
$query->join(‘wp_posts’, ‘p’, ‘p.ID=m.meta_value’);
$query
->condition(‘m.meta_key’, ‘_thumbnail_id’, ‘=’)
->condition(‘p.post_type’, ‘attachment’, ‘=’)
->condition(‘p.guid’, ”, ‘<>’)
// this prevents some duplicates to get the count closer to even
->groupBy(‘ID, guid’);
return $query;
}
 
/**
* {@inheritdoc}
*/
public function fields() {
$fields = array(
‘ID’ => $this->t(‘The file ID.’),
‘guid’ => $this->t(‘The file path’),
);
return $fields;
}
 
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
$url = $row->getSourceProperty(‘guid’);
$parsed_url = parse_url($url);
$filename = basename($parsed_url[‘path’]);
$row->setSourceProperty(‘filename’, $filename);
$public_path = ‘public://’ . $parsed_url[‘path’];
$row->setSourceProperty(‘uri’, $public_path);
 
// download the file if it does not exist
if (!file_exists($public_path)) {
$public_dirname = dirname($public_path);
 
// create directories if necessary
if (!file_exists($public_dirname)) {
$this->fileSystem->mkdir($public_dirname, 0775, TRUE);
}
 
// try to download it
$copied = @copy($url, $public_path);
if (!$copied) {
return FALSE;
}
}
return parent::prepareRow($row);
}
 
/**
* {@inheritdoc}
*/
public function bundleMigrationRequired() {
return FALSE;
}
 
/**
* {@inheritdoc}
*/
public function getIds() {
return array(
‘ID’ => array(
‘type’ => ‘integer’,
‘alias’ => ‘p’,
),
);
}
 
}

In Migrate, the template defines what source, processing, and fields are created. The source plugin is used by that migration to allow you to specify what is created. The source plugin above will get the feature images for posts, but also try and download the image into Drupal maintenance support plans‘s files directory.

You can add this as a dependency for the wp_posts migration. A word of warning though: if one migration (Migration A) depends on a different migration (Migration B), all of the content from A must be migrated before B can be run. If there are images that cannot be resolved for some reason (maybe leftover DB references after an image or post is deleted), this might stop the migration because the dependency cannot be resolved.

And finally, you will also need to add “wp_feature_images” to your manifest_wordpress.yml before running the migration.

Converting content

So far we have updated migration source plugins, but there are also process plugins, which can be used to change row values. As mentioned, the WP content often uses the autop filter to create paragraph/line breaks automatically so we need to change those to HTML for Drupal maintenance support plans. (You can also just use this functionality in your text format and skip this step if having this on will not cause issues with other content)

First, create a “src/Plugin/migrate/process” directory if one does not exist in the module and add this processor:

<?php
 
namespace Drupal maintenance support plansmigrate_wordpressPluginmigrateprocess;
 
use Drupal maintenance support plansmigrateMigrateExecutableInterface;
use Drupal maintenance support plansmigrateProcessPluginBase;
use Drupal maintenance support plansmigrateRow;
 
/**
* Apply the automatic paragraph filter to content
*
* @MigrateProcessPlugin(
* id = “wp_content”
* )
*/
class WpContent extends ProcessPluginBase {
 
/**
* {@inheritdoc}
*
* Split the ‘administer nodes’ permission from ‘access content overview’.
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
return _filter_autop($value);
}
 
}

Then, update the “process” section of “wp_posts.yml” to include this processor:

‘body/value’:
plugin: wp_content
source: post_content

All of this should put you on the road to getting WordPress content migrated into a Drupal maintenance support plans 8 site, although you’ll probably have to adjust code to your specific circumstances along the way.
Source: New feed

This article was republished from its original source.
Call Us: 1(800)730-2416

Pixeldust is a 20-year-old web development agency specializing in Drupal and WordPress and working with clients all over the country. With our best in class capabilities, we work with small businesses and fortune 500 companies alike. Give us a call at 1(800)730-2416 and let’s talk about your project.

FREE Drupal SEO Audit

Test your site below to see which issues need to be fixed. We will fix them and optimize your Drupal site 100% for Google and Bing. (Allow 30-60 seconds to gather data.)

Powered by

Aten Design Group: Migrating WordPress into Drupal maintenance support plans 8

On-Site Drupal SEO Master Setup

We make sure your site is 100% optimized (and stays that way) for the best SEO results.

With Pixeldust On-site (or On-page) SEO we make changes to your site’s structure and performance to make it easier for search engines to see and understand your site’s content. Search engines use algorithms to rank sites by degrees of relevance. Our on-site optimization ensures your site is configured to provide information in a way that meets Google and Bing standards for optimal indexing.

This service includes:

  • Pathauto install and configuration for SEO-friendly URLs.
  • Meta Tags install and configuration with dynamic tokens for meta titles and descriptions for all content types.
  • Install and fix all issues on the SEO checklist module.
  • Install and configure XML sitemap module and submit sitemaps.
  • Install and configure Google Analytics Module.
  • Install and configure Yoast.
  • Install and configure the Advanced Aggregation module to improve performance by minifying and merging CSS and JS.
  • Install and configure Schema.org Metatag.
  • Configure robots.txt.
  • Google Search Console setup snd configuration.
  • Find & Fix H1 tags.
  • Find and fix duplicate/missing meta descriptions.
  • Find and fix duplicate title tags.
  • Improve title, meta tags, and site descriptions.
  • Optimize images for better search engine optimization. Automate where possible.
  • Find and fix the missing alt and title tag for all images. Automate where possible.
  • The project takes 1 week to complete.