Top Banner
Clayton Parker, Senior Developer Migrating From Drupal to Plone with Transmogrifier PLONE SYMPOSIUM EAST 2011
37

Migrating from drupal to plone with transmogrifier

Nov 29, 2014

Download

Technology

Clayton Parker

Transmogrifier is a migration framework that can help you easily migrate from one platform to another. It has been written in a way that allows re-use of migration code through blueprints. In this talk we will walk through the steps necessary to migrate from Drupal, a popular CMS written in PHP, into Plone. We will see how to use the various blueprints available to build a pipeline that prepares and imports the content into Plone
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Migrating from drupal to plone with transmogrifier

Clayton Parker, Senior Developer

Migrating From Drupal to Plone with Transmogrifier

PLONE SYMPOSIUM EAST 2011

Page 2: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Who Am I?

• claytron

• Python dev since 2003

• Plone Core Committer

• Foundation Member

Page 3: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011What will we learn?

• Transmogrifier basics

• Migration Planning Process

• Creating a pipeline

Page 4: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Migrations

• One off scripts

• In multiple places

• Little to no re-usability

Page 5: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Transmogrifier

• A framework for migrations

• Re-usable parts

Page 6: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Basics

• Pipeline

• Blueprints

• Sources

• Section

Page 7: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Sources

• A blueprint

• First item in your pipeline

Page 8: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011

<html><body><h3>Code Sample</h3><p>Replace this text!</p></body></html>

Example Pipeline[transmogrifier]pipeline = csv_file constructor schemaupdater

[csv_file]blueprint = collective.transmogrifier.sections.csvsourcefilename = my.migration.import:my_items.csv

[constructor]blueprint = collective.transmogrifier.sections.constructor

[schemaupdater]blueprint = plone.app.transmogrifier.atschemaupdater

Page 9: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011my_items.csv

_path , _type , title , description/folder1 , Folder , First Folder , This is folder One/folder2 , Folder , Second Folder , This is folder Two/folder1/foo , Document , One Foo , A document named foo/folder2/foo , Document , Two Foo , Another doc named foo

Page 10: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011The Result

Page 11: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Items

• Each item is a mapping

• Keys are fields

• Keys with a leading underscore are controllers

Page 12: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Example Item{'_id': 'a-stronger-connection-to-out-customers', '_path': 'content/stronger-connection-out-customers', '_status': 1L, '_text_mimetype': 'text/html', '_transitions': 'publish', '_type': 'Document', 'allowDiscussion': False, 'creation_date': '2011/05/14 9:20:50', 'effectiveDate': '2011/05/14 9:20:50', 'modification_date': '2011/05/18 9:22:22', 'subject': 'better\ninteresting\nstronger', 'text': '<p>this is some text</p>\r\n', 'title': 'A stronger connection to out customers'}

Page 13: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Migration Strategy

• Investigate the source

• Prepare the destination

• Find Transmogrifier blueprints

• Write the pipeline

Page 14: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Write your own

• Missing blueprint

• Write one

• Contribute it back

Page 15: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011GenericSetup

• Make migration part of your release

• Ability to package migrations

Page 16: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011My Migration

• Drupal backed by MySQL

• transmogrify.sqlalchemy

• Plone 4.0.5

• collective.blog.star

• plone.app.discussion

Page 17: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Package Layoutmy.migration!"" my#   !"" __init__.py#   %"" migration#   !"" __init__.py#   !"" config#   #   !"" articles.cfg#   #   !"" base.cfg#   #   !"" blogs.cfg#   #   !"" comments.cfg#   #   %"" pages.cfg#   !"" configure.zcml#   %"" profiles#      %"" default#      !"" metadata.xml#      %"" transmogrifier.txt!"" setup.cfg%"" setup.py

Page 18: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Registering Configs

<transmogrifier:registerConfig name="my.migration.base" title="My migration base config" description="Base settings for all transmogrifier imports" configuration="config/base.cfg" />

Page 19: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Registering Configs

<transmogrifier:registerConfig name="my.migration.pages" title="Drupal pages" description="Import pages from Drupal into Plone" configuration="config/pages.cfg" />

Page 20: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Registering Configs

<transmogrifier:registerConfig name="my.migration.articles" title="Drupal articles" description="Import articles from Drupal into Plone" configuration="config/articles.cfg" />

Page 21: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Registering Configs

<transmogrifier:registerConfig name="my.migration.blogs" title="Drupal blog entries" description="Import blog entries from Drupal into Plone" configuration="config/blogs.cfg" />

Page 22: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Registering Configs

<transmogrifier:registerConfig name="my.migration.comments" title="Drupal comments" description="Import comments from Drupal into Plone" configuration="config/comments.cfg" />

Page 23: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011transmogrifier.txt

my.migration.pagesmy.migration.articlesmy.migration.blogsmy.migration.comments

Page 24: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Package Layoutmy.migration!"" my#   !"" __init__.py#   %"" migration#   !"" __init__.py#   !"" config#   #   !"" articles.cfg#   #   !"" base.cfg#   #   !"" blogs.cfg#   #   !"" comments.cfg#   #   %"" pages.cfg#   !"" configure.zcml#   %"" profiles#      %"" default#      !"" metadata.xml#      %"" transmogrifier.txt!"" setup.cfg%"" setup.py

Page 25: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011base.cfg pipeline[transmogrifier]pipeline = drupal portal_type url_normalizer path publication_state text_mimetype mimetype_encapsulator folders constructor commenting comments schema_update workflow reindex_object

[settings]# Path to use if there isn’t one givenbase_path = other-content# Have to escape python string formatting for when # this gets passed into sqlalchemydate_format = %%Y/%%m/%%d %%k:%%i:%%s

Page 26: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011drupal section

[drupal]blueprint = transmogrify.sqlalchemydsn = mysql://user:password@localhost/drupal-transmog

Page 27: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011articles.cfg[transmogrifier]include = my.migration.base

[drupal]query = SELECT node.title, node.status AS status, GROUP_CONCAT(tag_data.name SEPARATOR '\n') AS subject, FROM_UNIXTIME(node.created, "${settings:date_format}") AS creation_date, FROM_UNIXTIME(node.created, "${settings:date_format}") AS effectiveDate, FROM_UNIXTIME(node.changed, "${settings:date_format}") AS modification_date, body_data.body_value AS text url_alias.alias AS _path FROM node INNER JOIN field_data_field_tags AS tag_field ON tag_field.entity_id = node.nid INNER JOIN taxonomy_term_data AS tag_data ON tag_data.tid = tag_field.field_tags_tid INNER JOIN field_data_body AS body_data ON body_data.entity_id = node.nid INNER JOIN url_alias ON url_alias.source = CONCAT("node/", node.nid) GROUP BY node.title, node.status, node.created, node.changed, body_data.body_value, url_alias.alias;

[portal_type]value = string:Document

Page 28: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011pages.cfg[transmogrifier]include = my.migration.base

[drupal]query = my.migration.base SELECT node.title, node.status AS _status, FROM_UNIXTIME(node.created, "${settings:date_format}") AS creation_date, FROM_UNIXTIME(node.created, "${settings:date_format}") AS effectiveDate, FROM_UNIXTIME(node.changed, "${settings:date_format}") AS modification_date, body_data.body_value AS text, url_alias.alias AS _path FROM node INNER JOIN field_data_body AS body_data ON body_data.entity_id = node.nid INNER JOIN url_alias ON url_alias.source = CONCAT("node/", node.nid) WHERE node.type = "page" GROUP BY node.title, node.status, node.created, node.changed, body_data.body_value, url_alias.alias;

[portal_type]value = string:Document

Page 29: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011blogs.cfg[transmogrifier]include = my.migration.base

[drupal]query = SELECT node.title, node.satus AS _status, FROM_UNIXTIME(node.created, "${settings:date_format}") AS creation_date, FROM_UNIXTIME(node.created, "${settings:date_format}") AS effectiveDate, FROM_UNIXTIME(node.created, "${settings:date_format}") AS modification_date, body_data.body_value AS text, url_alias.alias AS _path FROM node INNER JOIN field_data_body AS body_data ON body_data.entity_id = node.nid INNER JOIN url_alias ON url_alias.source = CONCAT("node/", node.nid) WHERE node.type = "blog" GROUP BY node.title, node.status, node.created, node.changed, body_data.body_value, url_alias.alias;

[portal_type]value = string:BlogEntry

[commenting]value = python:True

Page 30: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011comments.cfg[transmogrifier]include = my.migration.base

[drupal]query = my.migration.base SELECT comment.subject AS title, FROM_UNIXTIME(comment.created, "${settings:date_format}") AS published, FROM_UNIXTIME(comment.changed, "${settings:date_format}") AS updated, comment.name AS author_name, body_data.comment_body_value AS text, url_alias.alias AS _parent_path FROM comment INNER JOIN field_data_comment_body AS body_data ON body_data.entity_id = comment.cid INNER JOIN node ON node.nid = comment.nid INNER JOIN url_alias ON url_alias.source = CONCAT("node/", node.nid) GROUP BY comment.subject, comment.created, comment.changed, comment.name, body_data.comment_body_value, url_alias.alias;

[portal_type]# Override the portal type to use the "comment_type"key = string:_comment_typevalue = string:plone.app.discussion

Page 31: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011base.cfg overrides[path]blueprint = collective.transmogrifier.sections.inserter# only add a path if one does not existcondition = python:'_path' not in item and not '_parent_path' in itemkey = string:_path# Add the value in the extended configurationvalue = string:${settings:base_path}/${item/_id}

[portal_type]blueprint = collective.transmogrifier.sections.inserterkey = string:_type# We will add the value in the extended config, but we need a# default set herevalue = string:

[commenting]blueprint = collective.transmogrifier.sections.inserterkey = string:allowDiscussion# default to falsevalue = python:False

Page 32: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Content Creation

[comments]blueprint = transmogrify.comments

[folders]blueprint = collective.transmogrifier.sections.folders

[constructor]blueprint = collective.transmogrifier.sections.constructor

[schema_update]blueprint = plone.app.transmogrifier.atschemaupdater

[workflow]blueprint = plone.app.transmogrifier.workflowupdater

[reindex_object]blueprint = plone.app.transmogrifier.reindexobject

Page 33: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Item Modification[publication_state]blueprint = collective.transmogrifier.sections.insertercondition = python:'_status' in item and item['_status'] == 1key = string:_transitionsvalue = string:publish

[text_mimetype]# This could probably be taken from the database as wellblueprint = collective.transmogrifier.sections.inserterkey = string:_text_mimetypevalue = string:text/html

[mimetype_encapsulator]blueprint = plone.app.transmogrifier.mimeencapsulatorkey = textmimetype = python:item.get('_%s_mimetype', key)field = keycondition = mimetype

Page 34: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011

DEMO

Page 35: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Links

• collective.transmogrifier

http://pypi.python.org/pypi/collective.transmogrifier/

• plone.app.transmogrifier

http://pypi.python.org/pypi/plone.app.transmogrifier/

Page 36: Migrating from drupal to plone with transmogrifier

PLONE SYMPOSIUM EAST 2011Useful Sources and Blueprints• plone.app.transmogrifier

• transmogrify.filesystem

• transmogrify.sqlalchemy

• transmogrify.webcrawler

• quintagroup.transmogrifier

• transmogrify.comments

Page 37: Migrating from drupal to plone with transmogrifier

Check out

sixfeetup.com/demos