MIGRATING 8.1.x DATA TO Ready! DRUPAL 8
about.me Nacho Sánchez CTO@ @isholgueras nacho@letshackity.com drupal.org/u/isholgueras http://www.isholgueras.com
STEPS 1. Requirements 2. Anatomy of a migration 3. Migration Framework 4. D2D migrations
1. REQUIREMENTS
1. Migrate is in core! REQUIREMENTS Three new modules ▸ Migrate Take care! Handles migrations. Framework. It’s in experimental! ▸ Migrate Drupal Contains migrations from D6 & D7. ▸ Migrate Drupal UI The older migrate update (new in 8.1.x).
1. Migrate in core! REQUIREMENTS But … how can I execute that migration. UI is not ready? No Drush command?
1. REQUIREMENTS So... Contrib!
1. Needed REQUIREMENTS ▸ Drupal 8.1.x ▸ Drush 8 ▸ Migrate tools (contrib) ▸ Migrate Plus (contrib)
2. ANATOMY OF A MIGRATION
Workflow 2. ANATOMY OF A MIGRATION PROCESS SOURCE DESTINATION PROCESS PROCESS
In files 2. 2. ANATOMY OF ANATOMY OF A MIGRATION A MIGRATION PLUGINS DEFINITIONS PHP Files Yaml Files. Core files or custom Custom files files Types: - Source - Process - Destination - Builder - ID Map
2. ANATOMY OF A MIGRATION The easiest example
DEFINITIONS 2. config/install/migrate_plus.migration.article_node.yml ANATOMY OF id: article_node A MIGRATION label: Migrate posts from CakePHP to Drupal 8 source: plugin: article_node key: legacy #target: legacy destination: plugin: entity:node process: type: plugin: default_value default_value: article nid: id title: title 'body/value': description uid: user_id status: plugin: default_value default_value: true created: plugin: callback source: created callable: strtotime migration_dependencies: {} #new in 8.1.x
PLUGINS 2. src/Plugin/migrate/source/ArticleNode.php ANATOMY OF A MIGRATION <?php namespace .. use .. /** * Source plugin for beer content. public function fields() { * $fields = [ * @MigrateSource( 'id' => $this->t("Article ID"), * id = "article_node" // ... * ) ]; */ return $fields; class ArticleNode extends SqlBase { } public function getIds() { public function query() { return [ $query = $this->select 'id' => [ ('articles','a') 'type' => 'integer', ->fields('a', [ 'alias' => 'a', 'id', ], 'user_id', ]; 'title', } 'description', } 'created', ]); return $query; }
CONFIGURATION 2. sites/local/settings.php ANATOMY OF A MIGRATION <?php //By default [‘default’][‘migration’] $databases['legacy']['default'] = array( 'database' => 'old_app', 'username' => 'dev', 'password' => 'dev', 'prefix' => '', 'host' => 'localhost', 'port' => '3306', 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql', 'driver' => 'mysql', );
EXECUTION 2. Only with Drush8 (8.1-dev) and migrate_tools enabled ANATOMY OF A MIGRATION vagrant@dev $ drush8 migrate-status Group: my_group Status Total Imported Unprocessed Last imported article_node Idle 128 0 128 vagrant@dev $ drush8 migrate-import article_node; d8 ms Processed 128 item (128 created, 0 updated, 0 failed, 0 ignored) - done with 'article_node' [status] Group: my_group Status Total Imported Unprocessed Last imported article_node Idle 128 128 0 2016-02-22 12:34:38 vagrant@dev $ drush8 migrate-rollback article_node; d8 ms Rolled back 128 items - done with 'article_node' Group: my_group Status Total Imported Unprocessed Last imported article_node Idle 128 0 128 2016-02-22 12:34:38
2. Too easy! ANATOMY OF A MIGRATION
3. MIGRATION FRAMEWORK
0.- KNOWLEDGE 3. MIGRATION Source Plugin: FRAMEWORK Most - SqlBase Process Plugin: used - ProcessPluginBase Destination Plugin: - DestinationBase More plugins in: core/modules/migrate/src/Plugin/migrate
0.- KNOWLEDGE 3. MIGRATION FRAMEWORK prepareRow !== transform - extends SqlBase - extends - Before execution ProcessPluginBase - During execution
1.- SOURCE 3. MIGRATION FRAMEWORK We tell here to SqlBase: - Which Database is the Source . #migrate_plus.migration.article_node.yml source: plugin: article_node key: legacy #target: legacy #settings.php $databases['key']['target'] = array(
1.- SOURCE 3. - And which Plugin will make the Query MIGRATION FRAMEWORK <?php public function fields() { namespace $fields = [ Drupal\cm_migrate\Plugin\migrate\source; 'id' => $this->t("Article ID"), use ... // ... /** ]; * Source plugin for articles content. return $fields; * } * @MigrateSource( public function getIds() { * id = "article_node" return [ * ) 'id' => [ */ 'type' => 'integer', class ArticleNode extends SqlBase { 'alias' => 'a', ], public function query() { ]; $query = $this->select('articles', 'a') } ->fields('a', [ public function prepareRow(Row $row) { 'id', $id = $row->getSourceProperty('id'); 'user_id', //print $id . PHP_EOL; 'title', //print_r($row); 'description', $row->setSourceProperty('user_id', 1); 'created', return parent::prepareRow($row); ]); } return $query; } }
2.- DESTINATION 3. MIGRATION FRAMEWORK How and where to save the data - Where to save the data. #migrate_plus.migration.article_node.yml destination: plugin: entity:node - entity:<place-here-an-entity>
2.- DESTINATION 3. MIGRATION FRAMEWORK Need more destination plugins? Search for “ destination: ” in core
3.- ID MAPPING 3. MIGRATION How Migrate associate old row with new row. FRAMEWORK public function getIds() { return [ 'id' => [ 'type' => 'string', 'alias' => 'u', ], ]; }
4.- PROCESS 3. MIGRATION How we transform each field, each file or data. FRAMEWORK - Map fields : Same value as origin. - Modify : Change o process the value - Add : Create new fields from other fields or calculate these fields.
4.- PROCESS 3. MIGRATION Map fields . Values are equal in both sides FRAMEWORK public function query() { #common mapping $query = $this process: ->select('articles', 'a') title: title ->fields('a', [ 'created', 'title', 'id', 'body', 'user_id', ]); return $query; }
4.- PROCESS 3. MIGRATION DefaultValue . Add a default value FRAMEWORK public function query() { #default value $query = $this process: ->select('articles', 'a') type: ->fields('a', [ plugin: default_value 'created', default_value: article 'title', 'body/format': 'id', plugin: default_value 'body', default_value: plain_text 'user_id', ]); return $query; }
4.- PROCESS 3. MIGRATION Callable . Values are similars but a transform is FRAMEWORK needed with a php function public function query() { #'Callable.php' core plugin $query = $this process: ->select('articles', 'a') created: ->fields('a', [ 'created_date', plugin: callback 'title', source: created_date 'id', callable: strtotime 'body', 'user_id', ]); return $query; }
4.- PROCESS 3. MIGRATION DedupeEntity . Values in destination cannot be FRAMEWORK equals, but in origin could be. public function query() { # DedupeEntity.php' core $query = $this # plugin ->select('users', 'u') process: ->fields('u', [ name: 'user_id', plugin: dedupe_entity 'user_name', source: user_name 'mail', entity_type: user ]); field: name return $query; postfix: _ } # admin_1, _2, ...
4.- PROCESS 3. MIGRATION Migration . Values from other migration. FRAMEWORK Magic! # ArticleNode.php # Migration as plugin public function query() { process: $query = $this field_tags: ->select('articles', 'a') plugin: migration ->fields('a', [ migration: tags_node fields() 'created_date', source: terms 'title', migration_dependencies: 'id', required: 'body', - tags_node 'user_id', ]); return $query; }
4.- PROCESS 3. MIGRATION Migration . Values from other migration. FRAMEWORK Magic! # ArticleNode.php # ArticleNode.php public function fields() { public function prepareRow(Row $row) { $fields = [ $terms = $this->select('terms') 'terms' => $this->t //... ("New field terms"), ->fetchCol(); // ... //print_r($terms); ]; $row->setSourceProperty('terms', return $fields; $terms); } return parent::prepareRow($row); } }
4.- PROCESS 3. MIGRATION Migration . Values from other migration. FRAMEWORK Magic! # TagsNode.php #migrate_plus.migration. public function query() { tags_node.yml // code source: ->fields('terms', [ plugin: tags_node 'parent_term', destination: 'term']); plugin: entity:taxonomy_term } process: name: term parent: plugin: migration migration: tags_node source: parent_term
4.- PROCESS 3. MIGRATION CustomPlugins . Values are related but a FRAMEWORK custom transform for data is needed public function query() { #CustomUUID.php' custom plugin $query = $this process: ->select('articles', 'a') uid: ->fields('a', [ plugin: custom_uuid 'created_date', source: user_id 'title', 'id', 'body', 'user_id', ]); return $query; }
Recommend
More recommend