Wordpress to Drupal 8 migration setup
Here’s an example of an existing WordPress site, which has registered users with comments, anonymous comments and an archive of previous postings with metadata (tags) that we will import. We’ll finish with this posting displayed in Drupal 8 version of the blog.
The following tables in Wordpress are relevant to the migration:
- wp_posts (contains blog posts and pages)
- wp_comments (comments)
- wp_users (users)
- wp_terms (categories - taxonomy)
We will started writing our migration module using Migration API (migrate) that comes packaged with D8 core. As usual in Drupal 8 module development, we had .info.yml, files, which uses the Symfony 2 YAML to map data types into an XML-like schema for easy migration from one environment to another, and traditional Drupal .module files. The only thing worth noting here is a dependency on the migrate module in our info.yml file.
For each Entity migration (users, posts, comments) we created 2 more files:
- A YAML file containing ID, Source, Destination and Mapping (Process). Put this under MODULE_ROOT/config/install/
- A Source Plugin used to fetch/process Wordpress data. Put this underMODULE_ROOT/src/Plugin/migrate/source/
Code breakdown
Users
Let start understanding things by migrating Users first. Here is the complete user YAML file for this migration. Let’s break it down:
In this migrate.migration.users.yml file, ID, Source, Destination and Process (field mapping) are important keys.
label: Wordpress Users
migration_groups:
- Wordpress
ID key is ‘users’ which has been referred in manifest_wordpress.yml and also in Source Plugin (User.php) as part of Annotation.
plugin: users
Source key is referring to Source Plugin (User.php) created by us to fetch Wordpress users data, which we will see shortly in detail.
plugin: entity:user
Destination key is user entity as defined by Migration API.
uid: id
name: user_login
pass: user_pass
mail: user_email
status:
-
plugin: default_value
default_value: 1
created:
-
plugin: callback
callable: strtotime
source: user_registered
Process is key to mapping source (Wordpress) and destination (Drupal) fields. Some fields are mapped directly like ‘id’ with ‘sid’ while some fields are pre-processed by Migration API before being assigned to a destination field. For instance, ‘user_registered’ will be processed by PHP function strtotime() before it’s value gets assigned to destination field, because the target Drupal site must recognize those users as registered to associate their previous activity in WordPress with their Drupal activity on the new site. We can even write our own process plugins if required.
Now let’s look at Source Plugin (Users.php) which has been used to fetch the Wordpress users data,
/**
* @file
* Contains \Drupal\migrate_wordpress\Plugin\migrate\source\Users.
*/
namespace Drupal\migrate_wordpress\Plugin\migrate\source;
use Drupal\migrate\Row;
use Drupal\migrate\Plugin\SourceEntityInterface;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* Extracts users from Wordpress database.
*
* @MigrateSource(
* id = "users"
* )
*/
Remember the id field in the YAML file? The id field tells Drupal that this class should be used to process data for that migration set, taking the results of “users” in WordPress and adding them to a new table in the Drupal database, wp_users.
/**
* {@inheritdoc}
*/
public function query() {
return $this->select('wp_users', 'u')
->fields('u', array_keys($this->userFields()));
}
The query() method is used to fetch records from Wordpress database table (wp_users).
* Returns the User fields to be migrated.
*
* @return array
* Associative array having field name as key and description as value.
*/
protected function userFields() {
$fields = array(
'id' => $this->t('User ID'),
'user_login' => $this->t('Username'),
'user_pass' => $this->t('Password'),
'user_email' => $this->t('Email address'),
'user_registered' => $this->t('Created time'),
);
return $fields;
}
/**
* {@inheritdoc}
*/
public function fields() {
$fields = $this->userFields();
}
userFields() method is called in query() and fields() methods. It contains the list of fields that describe a WordPress user along with their field descriptions.
* {@inheritdoc}
*/
public function bundleMigrationRequired() {
return false;
}
/**
* {@inheritdoc}
*/
public function entityTypeId() {
return 'users';
}
/**
* {@inheritdoc}
*/
public function getIds() {
return array(
'id' => array(
'type' => 'integer',
'alias' => 'u',
),
);
}
As we are also implementing an interface SourceEntityInterface, we need to define 2 more methods namelybundleMigrationRequired() and entityTypeId() to map user-generated content, such as postings and comments, to Drupal. The getIds() method is used to return the key field for this Entity.
Posts
The Posts Entity migration (YAML, Source Plugin) is quite similar to User Entity migration. There is one additional method prepareRow() defined in post migration source plugin. This method gets called for each row to do an additional processing of the source data.
$post_type = $row->getSourceProperty('post_type');
$type = $post_type == 'page' ? 'page' : 'article';
$row->setSourceProperty('type', $type);
return parent::prepareRow($row);
}
In this method, we are first checking the post type of source data and based on that we set the ‘type’ property. As we have two types of posts in Wordpress (Pages, Blogs posts) we want to map them to two content types in Drupal (Basic page, Article). The ‘type’ property is available in the post-migration YAML file Process step, as discussed above, and we have mapped it to the Drupal content type field.
Comments
The Comments Entity migration is more or less similar to Users and Posts migration. There are some following additions in Comments migration YAML file which are quite interesting to know.
-
plugin: skip_process_on_empty
source: user_id
-
plugin: migration
migration: users
'comment_body/value': comment_content
'comment_body/format': 'basic_html'
migration_dependencies:
required:
- posts
- users
Here we are using ‘skip_process_on_empty’ plugin which means skip the process if the source value is empty. As key fields can have different values in source and destination databases so we are using migration plugin to map ‘user_id’ field with ‘uid’ field. This will look for destination id in migration map tables for given source id (user_id).
Next, the ‘comment_body’ field is a text field and made up of two fields in Drupal 8, so we must map the Wordpress ‘comment_content’ field to value field and mapping basic html to format field. Next we have defined comment migration dependencies to posts and users which means comments will be migrated once both posts and users are already migrated.
Putting it all together
Finally you can run the migration using 'migrate-manifest' drush command as below. Make sure to run this command in Drush 7.
The manifest_wordpress.yml is a YAML file which contains reference to IDs of each migration (users, posts, comments etc.).
- posts
- users
- comments
Finished: WordPress postings shown in Drupal
We do Drupal development
Go to our Drupal page!