SlideShare una empresa de Scribd logo
1 de 37
Descargar para leer sin conexión
Migrating From Drupal
    to Plone with
    Transmogrifier
   Clayton Parker, Senior Developer
       PLONE SYMPOSIUM EAST 2011
Who Am I?                 PLONE SYMPOSIUM EAST 2011




• claytron
• Python dev since 2003
• Plone Core Committer
• Foundation Member
What will we learn?            PLONE SYMPOSIUM EAST 2011




• Transmogrifier basics
• Migration Planning Process
• Creating a pipeline
Migrations                    PLONE SYMPOSIUM EAST 2011




• One off scripts
• In multiple places
• Little to no re-usability
Transmogrifier                  PLONE SYMPOSIUM EAST 2011




• A framework for migrations
• Re-usable parts
Basics         PLONE SYMPOSIUM EAST 2011




• Pipeline
• Blueprints
• Sources
• Section
Sources                         PLONE SYMPOSIUM EAST 2011




• A blueprint
• First item in your pipeline
Example Pipeline                                PLONE SYMPOSIUM EAST 2011




 [transmogrifier]
 pipeline =
     csv_file
     constructor
     schemaupdater
        <html>
        <body>
 [csv_file]
        <h3>Code Sample</h3>
 blueprint = collective.transmogrifier.sections.csvsource
        <p>Replace this text!</p>
 filename = my.migration.import:my_items.csv
        </body>
        </html>
 [constructor]
 blueprint = collective.transmogrifier.sections.constructor

 [schemaupdater]
 blueprint = plone.app.transmogrifier.atschemaupdater
my_items.csv                                                 PLONE SYMPOSIUM EAST 2011




_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
The Result   PLONE SYMPOSIUM EAST 2011
Items                                    PLONE SYMPOSIUM EAST 2011




• Each item is a mapping
• Keys are fields
• Keys with a leading underscore are controllers
Example Item                                       PLONE SYMPOSIUM EAST 2011




{'_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': 'betterninterestingnstronger',
 'text': '<p>this is some text</p>rn',
 'title': 'A stronger connection to out customers'}
Migration Strategy                PLONE SYMPOSIUM EAST 2011




• Investigate the source
• Prepare the destination
• Find Transmogrifier blueprints
• Write the pipeline
Write your own         PLONE SYMPOSIUM EAST 2011




• Missing blueprint
• Write one
• Contribute it back
GenericSetup                            PLONE SYMPOSIUM EAST 2011




• Make migration part of your release
• Ability to package migrations
My Migration                PLONE SYMPOSIUM EAST 2011




• Drupal backed by MySQL
• transmogrify.sqlalchemy
• Plone 4.0.5
• collective.blog.star
• plone.app.discussion
Package Layout                               PLONE SYMPOSIUM EAST 2011


    my.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
Registering Configs                               PLONE SYMPOSIUM EAST 2011




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




<transmogrifier:registerConfig
    name="my.migration.pages"
    title="Drupal pages"
    description="Import pages from Drupal into Plone"
    configuration="config/pages.cfg"
    />
Registering Configs                               PLONE SYMPOSIUM EAST 2011




<transmogrifier:registerConfig
    name="my.migration.articles"
    title="Drupal articles"
    description="Import articles from Drupal into Plone"
    configuration="config/articles.cfg"
    />
Registering Configs                               PLONE SYMPOSIUM EAST 2011




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




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




    my.migration.pages
    my.migration.articles
    my.migration.blogs
    my.migration.comments
Package Layout                               PLONE SYMPOSIUM EAST 2011


    my.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
base.cfg pipeline                                   PLONE SYMPOSIUM EAST 2011


    [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 given
    base_path = other-content
    # Have to escape python string formatting for when
    # this gets passed into sqlalchemy
    date_format = %%Y/%%m/%%d %%k:%%i:%%s
drupal section                                 PLONE SYMPOSIUM EAST 2011




  [drupal]
  blueprint = transmogrify.sqlalchemy
  dsn = mysql://user:password@localhost/drupal-transmog
articles.cfg                                                                PLONE SYMPOSIUM EAST 2011



 [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
pages.cfg                                                                   PLONE SYMPOSIUM EAST 2011



  [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
blogs.cfg                                                                   PLONE SYMPOSIUM EAST 2011


  [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
comments.cfg                                                               PLONE SYMPOSIUM EAST 2011


 [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_type
 value = string:plone.app.discussion
base.cfg overrides                                         PLONE SYMPOSIUM EAST 2011




 [path]
 blueprint = collective.transmogrifier.sections.inserter
 # only add a path if one does not exist
 condition = python:'_path' not in item and not '_parent_path' in item
 key = string:_path
 # Add the value in the extended configuration
 value = string:${settings:base_path}/${item/_id}

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

 [commenting]
 blueprint = collective.transmogrifier.sections.inserter
 key = string:allowDiscussion
 # default to false
 value = python:False
Content Creation                                          PLONE SYMPOSIUM EAST 2011




 [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
Item Modification                                         PLONE SYMPOSIUM EAST 2011




 [publication_state]
 blueprint = collective.transmogrifier.sections.inserter
 condition = python:'_status' in item and item['_status'] == 1
 key = string:_transitions
 value = string:publish

 [text_mimetype]
 # This could probably be taken from the database as well
 blueprint = collective.transmogrifier.sections.inserter
 key = string:_text_mimetype
 value = string:text/html

 [mimetype_encapsulator]
 blueprint = plone.app.transmogrifier.mimeencapsulator
 key = text
 mimetype = python:item.get('_%s_mimetype', key)
 field = key
 condition = mimetype
PLONE SYMPOSIUM EAST 2011




DEMO
Links                                              PLONE SYMPOSIUM EAST 2011




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

• plone.app.transmogrifier
http://pypi.python.org/pypi/plone.app.transmogrifier/
Useful Sources and            PLONE SYMPOSIUM EAST 2011



Blueprints
• plone.app.transmogrifier
• transmogrify.filesystem
• transmogrify.sqlalchemy
• transmogrify.webcrawler
• quintagroup.transmogrifier
• transmogrify.comments
Check out
          .co m/d emos
s ixfeetup

Más contenido relacionado

La actualidad más candente

Beauty and Power of Go
Beauty and Power of GoBeauty and Power of Go
Beauty and Power of GoFrank Müller
 
What's new in PHP 5.5
What's new in PHP 5.5What's new in PHP 5.5
What's new in PHP 5.5Tom Corrigan
 
7 Common mistakes in Go and when to avoid them
7 Common mistakes in Go and when to avoid them7 Common mistakes in Go and when to avoid them
7 Common mistakes in Go and when to avoid themSteven Francia
 
A new way to develop with WordPress!
A new way to develop with WordPress!A new way to develop with WordPress!
A new way to develop with WordPress!David Sanchez
 
Introducing PHP Latest Updates
Introducing PHP Latest UpdatesIntroducing PHP Latest Updates
Introducing PHP Latest UpdatesIftekhar Eather
 
Something about Golang
Something about GolangSomething about Golang
Something about GolangAnton Arhipov
 
Exploring Clojurescript
Exploring ClojurescriptExploring Clojurescript
Exploring ClojurescriptLuke Donnet
 
Node.js basics
Node.js basicsNode.js basics
Node.js basicsBen Lin
 
The GO Language : From Beginners to Gophers
The GO Language : From Beginners to GophersThe GO Language : From Beginners to Gophers
The GO Language : From Beginners to GophersAlessandro Sanino
 
Groovy & Grails: Scripting for Modern Web Applications
Groovy & Grails: Scripting for Modern Web ApplicationsGroovy & Grails: Scripting for Modern Web Applications
Groovy & Grails: Scripting for Modern Web Applicationsrohitnayak
 
Concurrency in go
Concurrency in goConcurrency in go
Concurrency in goborderj
 
RDSDataSource: Мастер-класс по Dip
RDSDataSource: Мастер-класс по DipRDSDataSource: Мастер-класс по Dip
RDSDataSource: Мастер-класс по DipRAMBLER&Co
 
How to Scrap Any Website's content using ScrapyTutorial of How to scrape (cra...
How to Scrap Any Website's content using ScrapyTutorial of How to scrape (cra...How to Scrap Any Website's content using ScrapyTutorial of How to scrape (cra...
How to Scrap Any Website's content using ScrapyTutorial of How to scrape (cra...Anton
 
Web Crawling with NodeJS
Web Crawling with NodeJSWeb Crawling with NodeJS
Web Crawling with NodeJSSylvain Zimmer
 

La actualidad más candente (20)

Beauty and Power of Go
Beauty and Power of GoBeauty and Power of Go
Beauty and Power of Go
 
What's new in PHP 5.5
What's new in PHP 5.5What's new in PHP 5.5
What's new in PHP 5.5
 
PHP7 Presentation
PHP7 PresentationPHP7 Presentation
PHP7 Presentation
 
7 Common mistakes in Go and when to avoid them
7 Common mistakes in Go and when to avoid them7 Common mistakes in Go and when to avoid them
7 Common mistakes in Go and when to avoid them
 
A new way to develop with WordPress!
A new way to develop with WordPress!A new way to develop with WordPress!
A new way to develop with WordPress!
 
The new features of PHP 7
The new features of PHP 7The new features of PHP 7
The new features of PHP 7
 
Introducing PHP Latest Updates
Introducing PHP Latest UpdatesIntroducing PHP Latest Updates
Introducing PHP Latest Updates
 
Something about Golang
Something about GolangSomething about Golang
Something about Golang
 
Exploring Clojurescript
Exploring ClojurescriptExploring Clojurescript
Exploring Clojurescript
 
Node.js basics
Node.js basicsNode.js basics
Node.js basics
 
New Design of OneRing
New Design of OneRingNew Design of OneRing
New Design of OneRing
 
Testing con spock
Testing con spockTesting con spock
Testing con spock
 
The GO Language : From Beginners to Gophers
The GO Language : From Beginners to GophersThe GO Language : From Beginners to Gophers
The GO Language : From Beginners to Gophers
 
Groovy & Grails: Scripting for Modern Web Applications
Groovy & Grails: Scripting for Modern Web ApplicationsGroovy & Grails: Scripting for Modern Web Applications
Groovy & Grails: Scripting for Modern Web Applications
 
Txjs
TxjsTxjs
Txjs
 
Concurrency in go
Concurrency in goConcurrency in go
Concurrency in go
 
RDSDataSource: Мастер-класс по Dip
RDSDataSource: Мастер-класс по DipRDSDataSource: Мастер-класс по Dip
RDSDataSource: Мастер-класс по Dip
 
How to Scrap Any Website's content using ScrapyTutorial of How to scrape (cra...
How to Scrap Any Website's content using ScrapyTutorial of How to scrape (cra...How to Scrap Any Website's content using ScrapyTutorial of How to scrape (cra...
How to Scrap Any Website's content using ScrapyTutorial of How to scrape (cra...
 
groovy & grails - lecture 4
groovy & grails - lecture 4groovy & grails - lecture 4
groovy & grails - lecture 4
 
Web Crawling with NodeJS
Web Crawling with NodeJSWeb Crawling with NodeJS
Web Crawling with NodeJS
 

Similar a Migrating from drupal to plone with transmogrifier

Pyramid Lighter/Faster/Better web apps
Pyramid Lighter/Faster/Better web appsPyramid Lighter/Faster/Better web apps
Pyramid Lighter/Faster/Better web appsDylan Jay
 
Mojolicious - A new hope
Mojolicious - A new hopeMojolicious - A new hope
Mojolicious - A new hopeMarcus Ramberg
 
Python Code Camp for Professionals 3/4
Python Code Camp for Professionals 3/4Python Code Camp for Professionals 3/4
Python Code Camp for Professionals 3/4DEVCON
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Hugo Hamon
 
Drupal 8 Configuration Management
Drupal 8 Configuration ManagementDrupal 8 Configuration Management
Drupal 8 Configuration ManagementPhilip Norton
 
WordPress as the Backbone(.js)
WordPress as the Backbone(.js)WordPress as the Backbone(.js)
WordPress as the Backbone(.js)Beau Lebens
 
GDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineGDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineYared Ayalew
 
Flask intro - ROSEdu web workshops
Flask intro - ROSEdu web workshopsFlask intro - ROSEdu web workshops
Flask intro - ROSEdu web workshopsAlex Eftimie
 
Building Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSBuilding Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSAntonio Peric-Mazar
 
Frameworks da nova Era PHP FuelPHP
Frameworks da nova Era PHP FuelPHPFrameworks da nova Era PHP FuelPHP
Frameworks da nova Era PHP FuelPHPDan Jesus
 
An Introduction to Tornado
An Introduction to TornadoAn Introduction to Tornado
An Introduction to TornadoGavin Roy
 
Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4DEVCON
 
Building a real life application in node js
Building a real life application in node jsBuilding a real life application in node js
Building a real life application in node jsfakedarren
 
TYPO3 Extension development using new Extbase framework
TYPO3 Extension development using new Extbase frameworkTYPO3 Extension development using new Extbase framework
TYPO3 Extension development using new Extbase frameworkChristian Trabold
 
Twas the night before Malware...
Twas the night before Malware...Twas the night before Malware...
Twas the night before Malware...DoktorMandrake
 
Drupal 8 configuration management
Drupal 8 configuration managementDrupal 8 configuration management
Drupal 8 configuration managementAlexander Tkachev
 
Angular JS2 Training Session #2
Angular JS2 Training Session #2Angular JS2 Training Session #2
Angular JS2 Training Session #2Paras Mendiratta
 

Similar a Migrating from drupal to plone with transmogrifier (20)

Pyramid Lighter/Faster/Better web apps
Pyramid Lighter/Faster/Better web appsPyramid Lighter/Faster/Better web apps
Pyramid Lighter/Faster/Better web apps
 
Mojolicious - A new hope
Mojolicious - A new hopeMojolicious - A new hope
Mojolicious - A new hope
 
Python Code Camp for Professionals 3/4
Python Code Camp for Professionals 3/4Python Code Camp for Professionals 3/4
Python Code Camp for Professionals 3/4
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2
 
Symfony2 revealed
Symfony2 revealedSymfony2 revealed
Symfony2 revealed
 
PhpBB meets Symfony2
PhpBB meets Symfony2PhpBB meets Symfony2
PhpBB meets Symfony2
 
Drupal 8 Configuration Management
Drupal 8 Configuration ManagementDrupal 8 Configuration Management
Drupal 8 Configuration Management
 
WordPress as the Backbone(.js)
WordPress as the Backbone(.js)WordPress as the Backbone(.js)
WordPress as the Backbone(.js)
 
GDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineGDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App Engine
 
Flask intro - ROSEdu web workshops
Flask intro - ROSEdu web workshopsFlask intro - ROSEdu web workshops
Flask intro - ROSEdu web workshops
 
Building Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSBuilding Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJS
 
Frameworks da nova Era PHP FuelPHP
Frameworks da nova Era PHP FuelPHPFrameworks da nova Era PHP FuelPHP
Frameworks da nova Era PHP FuelPHP
 
An Introduction to Tornado
An Introduction to TornadoAn Introduction to Tornado
An Introduction to Tornado
 
Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4
 
Flask – Python
Flask – PythonFlask – Python
Flask – Python
 
Building a real life application in node js
Building a real life application in node jsBuilding a real life application in node js
Building a real life application in node js
 
TYPO3 Extension development using new Extbase framework
TYPO3 Extension development using new Extbase frameworkTYPO3 Extension development using new Extbase framework
TYPO3 Extension development using new Extbase framework
 
Twas the night before Malware...
Twas the night before Malware...Twas the night before Malware...
Twas the night before Malware...
 
Drupal 8 configuration management
Drupal 8 configuration managementDrupal 8 configuration management
Drupal 8 configuration management
 
Angular JS2 Training Session #2
Angular JS2 Training Session #2Angular JS2 Training Session #2
Angular JS2 Training Session #2
 

Más de Clayton Parker

Customizing Your Shell With Dotfiles
Customizing Your Shell With DotfilesCustomizing Your Shell With Dotfiles
Customizing Your Shell With DotfilesClayton Parker
 
Fuzzy Feelings for Fuzzy Matching
Fuzzy Feelings for Fuzzy MatchingFuzzy Feelings for Fuzzy Matching
Fuzzy Feelings for Fuzzy MatchingClayton Parker
 
Exploring Code with Pry!
Exploring Code with Pry!Exploring Code with Pry!
Exploring Code with Pry!Clayton Parker
 
Zen and the Art of Python
Zen and the Art of PythonZen and the Art of Python
Zen and the Art of PythonClayton Parker
 
So you think you can pdb?
So you think you can pdb?So you think you can pdb?
So you think you can pdb?Clayton Parker
 
Managing Chaos: Merging 120 Sites into a single Plone Multisite Solution
Managing Chaos: Merging 120 Sites into a single Plone Multisite SolutionManaging Chaos: Merging 120 Sites into a single Plone Multisite Solution
Managing Chaos: Merging 120 Sites into a single Plone Multisite SolutionClayton Parker
 
Current State of Python Packaging
Current State of Python PackagingCurrent State of Python Packaging
Current State of Python PackagingClayton Parker
 
Notre Dame Seamless Syndication with Lineage
Notre Dame Seamless Syndication with LineageNotre Dame Seamless Syndication with Lineage
Notre Dame Seamless Syndication with LineageClayton Parker
 
Pioneer a Strategic Change in Content Organization with Plone
Pioneer a Strategic Change in Content Organization with PlonePioneer a Strategic Change in Content Organization with Plone
Pioneer a Strategic Change in Content Organization with PloneClayton Parker
 
Using Buildout, GenericSetup and a Policy Package to Rule the World
Using Buildout, GenericSetup and a Policy Package to Rule the WorldUsing Buildout, GenericSetup and a Policy Package to Rule the World
Using Buildout, GenericSetup and a Policy Package to Rule the WorldClayton Parker
 
Make Plone Search Act Like Google Using Solr
Make Plone Search Act Like Google Using SolrMake Plone Search Act Like Google Using Solr
Make Plone Search Act Like Google Using SolrClayton Parker
 
Buildout for the Future
Buildout for the FutureBuildout for the Future
Buildout for the FutureClayton Parker
 
LDAP and Active Directory Authentication in Plone
LDAP and Active Directory Authentication in PloneLDAP and Active Directory Authentication in Plone
LDAP and Active Directory Authentication in PloneClayton Parker
 
Code with Style - PyOhio
Code with Style - PyOhioCode with Style - PyOhio
Code with Style - PyOhioClayton Parker
 
Using Buildout to Develop and Deploy Python Projects
Using Buildout to Develop and Deploy Python ProjectsUsing Buildout to Develop and Deploy Python Projects
Using Buildout to Develop and Deploy Python ProjectsClayton Parker
 
Generic Setup De-Mystified
Generic Setup De-MystifiedGeneric Setup De-Mystified
Generic Setup De-MystifiedClayton Parker
 
Buildout: Fostering Repeatability
Buildout: Fostering RepeatabilityBuildout: Fostering Repeatability
Buildout: Fostering RepeatabilityClayton Parker
 

Más de Clayton Parker (20)

Customizing Your Shell With Dotfiles
Customizing Your Shell With DotfilesCustomizing Your Shell With Dotfiles
Customizing Your Shell With Dotfiles
 
Vim for Mere Mortals
Vim for Mere MortalsVim for Mere Mortals
Vim for Mere Mortals
 
Fuzzy Feelings for Fuzzy Matching
Fuzzy Feelings for Fuzzy MatchingFuzzy Feelings for Fuzzy Matching
Fuzzy Feelings for Fuzzy Matching
 
Exploring Code with Pry!
Exploring Code with Pry!Exploring Code with Pry!
Exploring Code with Pry!
 
Zen and the Art of Python
Zen and the Art of PythonZen and the Art of Python
Zen and the Art of Python
 
So you think you can pdb?
So you think you can pdb?So you think you can pdb?
So you think you can pdb?
 
Managing Chaos: Merging 120 Sites into a single Plone Multisite Solution
Managing Chaos: Merging 120 Sites into a single Plone Multisite SolutionManaging Chaos: Merging 120 Sites into a single Plone Multisite Solution
Managing Chaos: Merging 120 Sites into a single Plone Multisite Solution
 
Current State of Python Packaging
Current State of Python PackagingCurrent State of Python Packaging
Current State of Python Packaging
 
Notre Dame Seamless Syndication with Lineage
Notre Dame Seamless Syndication with LineageNotre Dame Seamless Syndication with Lineage
Notre Dame Seamless Syndication with Lineage
 
Pioneer a Strategic Change in Content Organization with Plone
Pioneer a Strategic Change in Content Organization with PlonePioneer a Strategic Change in Content Organization with Plone
Pioneer a Strategic Change in Content Organization with Plone
 
Using Buildout, GenericSetup and a Policy Package to Rule the World
Using Buildout, GenericSetup and a Policy Package to Rule the WorldUsing Buildout, GenericSetup and a Policy Package to Rule the World
Using Buildout, GenericSetup and a Policy Package to Rule the World
 
Make Plone Search Act Like Google Using Solr
Make Plone Search Act Like Google Using SolrMake Plone Search Act Like Google Using Solr
Make Plone Search Act Like Google Using Solr
 
Buildout for the Future
Buildout for the FutureBuildout for the Future
Buildout for the Future
 
Buildout future
Buildout futureBuildout future
Buildout future
 
LDAP and Active Directory Authentication in Plone
LDAP and Active Directory Authentication in PloneLDAP and Active Directory Authentication in Plone
LDAP and Active Directory Authentication in Plone
 
Code with Style - PyOhio
Code with Style - PyOhioCode with Style - PyOhio
Code with Style - PyOhio
 
Code with style
Code with styleCode with style
Code with style
 
Using Buildout to Develop and Deploy Python Projects
Using Buildout to Develop and Deploy Python ProjectsUsing Buildout to Develop and Deploy Python Projects
Using Buildout to Develop and Deploy Python Projects
 
Generic Setup De-Mystified
Generic Setup De-MystifiedGeneric Setup De-Mystified
Generic Setup De-Mystified
 
Buildout: Fostering Repeatability
Buildout: Fostering RepeatabilityBuildout: Fostering Repeatability
Buildout: Fostering Repeatability
 

Último

ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDEADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDELiveplex
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7DianaGray10
 
Building AI-Driven Apps Using Semantic Kernel.pptx
Building AI-Driven Apps Using Semantic Kernel.pptxBuilding AI-Driven Apps Using Semantic Kernel.pptx
Building AI-Driven Apps Using Semantic Kernel.pptxUdaiappa Ramachandran
 
How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?IES VE
 
Bird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemBird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemAsko Soukka
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8DianaGray10
 
NIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopNIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopBachir Benyammi
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.YounusS2
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPathCommunity
 
Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024D Cloud Solutions
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfAijun Zhang
 
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfJamie (Taka) Wang
 
Introduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxIntroduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxMatsuo Lab
 
VoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXVoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXTarek Kalaji
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...DianaGray10
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaborationbruanjhuli
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UbiTrack UK
 
Videogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfVideogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfinfogdgmi
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdfPedro Manuel
 
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsIgniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsSafe Software
 

Último (20)

ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDEADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7
 
Building AI-Driven Apps Using Semantic Kernel.pptx
Building AI-Driven Apps Using Semantic Kernel.pptxBuilding AI-Driven Apps Using Semantic Kernel.pptx
Building AI-Driven Apps Using Semantic Kernel.pptx
 
How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?
 
Bird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemBird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystem
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8
 
NIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopNIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 Workshop
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation Developers
 
Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdf
 
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
 
Introduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxIntroduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptx
 
VoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXVoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBX
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
 
Videogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfVideogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdf
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdf
 
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsIgniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
 

Migrating from drupal to plone with transmogrifier

  • 1. Migrating From Drupal to Plone with Transmogrifier Clayton Parker, Senior Developer PLONE SYMPOSIUM EAST 2011
  • 2. Who Am I? PLONE SYMPOSIUM EAST 2011 • claytron • Python dev since 2003 • Plone Core Committer • Foundation Member
  • 3. What will we learn? PLONE SYMPOSIUM EAST 2011 • Transmogrifier basics • Migration Planning Process • Creating a pipeline
  • 4. Migrations PLONE SYMPOSIUM EAST 2011 • One off scripts • In multiple places • Little to no re-usability
  • 5. Transmogrifier PLONE SYMPOSIUM EAST 2011 • A framework for migrations • Re-usable parts
  • 6. Basics PLONE SYMPOSIUM EAST 2011 • Pipeline • Blueprints • Sources • Section
  • 7. Sources PLONE SYMPOSIUM EAST 2011 • A blueprint • First item in your pipeline
  • 8. Example Pipeline PLONE SYMPOSIUM EAST 2011 [transmogrifier] pipeline = csv_file constructor schemaupdater <html> <body> [csv_file] <h3>Code Sample</h3> blueprint = collective.transmogrifier.sections.csvsource <p>Replace this text!</p> filename = my.migration.import:my_items.csv </body> </html> [constructor] blueprint = collective.transmogrifier.sections.constructor [schemaupdater] blueprint = plone.app.transmogrifier.atschemaupdater
  • 9. my_items.csv PLONE SYMPOSIUM EAST 2011 _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
  • 10. The Result PLONE SYMPOSIUM EAST 2011
  • 11. Items PLONE SYMPOSIUM EAST 2011 • Each item is a mapping • Keys are fields • Keys with a leading underscore are controllers
  • 12. Example Item PLONE SYMPOSIUM EAST 2011 {'_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': 'betterninterestingnstronger', 'text': '<p>this is some text</p>rn', 'title': 'A stronger connection to out customers'}
  • 13. Migration Strategy PLONE SYMPOSIUM EAST 2011 • Investigate the source • Prepare the destination • Find Transmogrifier blueprints • Write the pipeline
  • 14. Write your own PLONE SYMPOSIUM EAST 2011 • Missing blueprint • Write one • Contribute it back
  • 15. GenericSetup PLONE SYMPOSIUM EAST 2011 • Make migration part of your release • Ability to package migrations
  • 16. My Migration PLONE SYMPOSIUM EAST 2011 • Drupal backed by MySQL • transmogrify.sqlalchemy • Plone 4.0.5 • collective.blog.star • plone.app.discussion
  • 17. Package Layout PLONE SYMPOSIUM EAST 2011 my.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
  • 18. Registering Configs PLONE SYMPOSIUM EAST 2011 <transmogrifier:registerConfig name="my.migration.base" title="My migration base config" description="Base settings for all transmogrifier imports" configuration="config/base.cfg" />
  • 19. Registering Configs PLONE SYMPOSIUM EAST 2011 <transmogrifier:registerConfig name="my.migration.pages" title="Drupal pages" description="Import pages from Drupal into Plone" configuration="config/pages.cfg" />
  • 20. Registering Configs PLONE SYMPOSIUM EAST 2011 <transmogrifier:registerConfig name="my.migration.articles" title="Drupal articles" description="Import articles from Drupal into Plone" configuration="config/articles.cfg" />
  • 21. Registering Configs PLONE SYMPOSIUM EAST 2011 <transmogrifier:registerConfig name="my.migration.blogs" title="Drupal blog entries" description="Import blog entries from Drupal into Plone" configuration="config/blogs.cfg" />
  • 22. Registering Configs PLONE SYMPOSIUM EAST 2011 <transmogrifier:registerConfig name="my.migration.comments" title="Drupal comments" description="Import comments from Drupal into Plone" configuration="config/comments.cfg" />
  • 23. transmogrifier.txt PLONE SYMPOSIUM EAST 2011 my.migration.pages my.migration.articles my.migration.blogs my.migration.comments
  • 24. Package Layout PLONE SYMPOSIUM EAST 2011 my.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
  • 25. base.cfg pipeline PLONE SYMPOSIUM EAST 2011 [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 given base_path = other-content # Have to escape python string formatting for when # this gets passed into sqlalchemy date_format = %%Y/%%m/%%d %%k:%%i:%%s
  • 26. drupal section PLONE SYMPOSIUM EAST 2011 [drupal] blueprint = transmogrify.sqlalchemy dsn = mysql://user:password@localhost/drupal-transmog
  • 27. articles.cfg PLONE SYMPOSIUM EAST 2011 [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
  • 28. pages.cfg PLONE SYMPOSIUM EAST 2011 [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
  • 29. blogs.cfg PLONE SYMPOSIUM EAST 2011 [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
  • 30. comments.cfg PLONE SYMPOSIUM EAST 2011 [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_type value = string:plone.app.discussion
  • 31. base.cfg overrides PLONE SYMPOSIUM EAST 2011 [path] blueprint = collective.transmogrifier.sections.inserter # only add a path if one does not exist condition = python:'_path' not in item and not '_parent_path' in item key = string:_path # Add the value in the extended configuration value = string:${settings:base_path}/${item/_id} [portal_type] blueprint = collective.transmogrifier.sections.inserter key = string:_type # We will add the value in the extended config, but we need a # default set here value = string: [commenting] blueprint = collective.transmogrifier.sections.inserter key = string:allowDiscussion # default to false value = python:False
  • 32. Content Creation PLONE SYMPOSIUM EAST 2011 [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
  • 33. Item Modification PLONE SYMPOSIUM EAST 2011 [publication_state] blueprint = collective.transmogrifier.sections.inserter condition = python:'_status' in item and item['_status'] == 1 key = string:_transitions value = string:publish [text_mimetype] # This could probably be taken from the database as well blueprint = collective.transmogrifier.sections.inserter key = string:_text_mimetype value = string:text/html [mimetype_encapsulator] blueprint = plone.app.transmogrifier.mimeencapsulator key = text mimetype = python:item.get('_%s_mimetype', key) field = key condition = mimetype
  • 34. PLONE SYMPOSIUM EAST 2011 DEMO
  • 35. Links PLONE SYMPOSIUM EAST 2011 • collective.transmogrifier http://pypi.python.org/pypi/collective.transmogrifier/ • plone.app.transmogrifier http://pypi.python.org/pypi/plone.app.transmogrifier/
  • 36. Useful Sources and PLONE SYMPOSIUM EAST 2011 Blueprints • plone.app.transmogrifier • transmogrify.filesystem • transmogrify.sqlalchemy • transmogrify.webcrawler • quintagroup.transmogrifier • transmogrify.comments
  • 37. Check out .co m/d emos s ixfeetup