31
Мигрируем на Drupal 8! #dckiev14

Drupal 8 migrate!

Embed Size (px)

Citation preview

Мигрируем на Drupal 8!#dckiev14

About usAndy Postnikov http://dgo.to/@andypostPavel Makhrinsky http://dgo.to/@gumanist

More then 2% of all sites

How many sites are running Drupal 6 and 7?

Latest stats

10 Drupal myths

●Box product●Lego●Contrib - themes, modules, libraries●Multilingual●Platform●Support●Community●Evolution

Go Drupal 8

●PHP 5.4 - 5.5, 5.6.2●HTML 5●Libraries - jQuery 2.1 (3.0)●Modules●CDN - REST●Database

Common migration tasks

●Planningo Data mappingo Dependencies managemento Data cleanup

●Chicken 'n Egg handling●Continuous content lifecycle●Progress monitoring●Rollback results

What is the migrate module?

Source => Process => Destination

Migrate vs Feeds

Mostly indentical feature set:●Since 2009 but FeedAPI 2007●feeds is UI-oriented●feeds_tamper vs custom code●feeds has a lot of satelite modules

Migrate in Drupal 8 retrospective

Signed after 6 weeks away from feature freezehttps://www.drupal.org/node/1052692#comment-6620570

Initial patch was commited November 21, 2013https://www.drupal.org/node/2125717#comment-8197259

Drupal 6 to Drupal 8 patch April 23, 2014https://www.drupal.org/node/2121299#comment-8710315

Still in progress of polishinghttps://groups.drupal.org/imp - weekly call

Processing

Mapping

Definition (yml-file)id: migrate_example_peoplesource: plugin: migrate_example_peopledestination: plugin: entity:user md5_passwords: trueprocess: name: - plugin: concat delimiter: . source: - first_name - last_name - plugin: callback callable: - '\Drupal\Component\Utility\Unicode' - strtolower

- plugin: callback callable: trim - plugin: dedupe_entity entity_type: user field: name mail: email pass: pass roles: - plugin: explode delimiter: ';'

source: groups

Chicken and egg

process: tid: tid vid: plugin: migration migration: d6_taxonomy_vocabulary source: vid parent: - plugin: skip_process_on_empty source: parent - plugin: migration migration: d6_taxonomy_term

Dependencies

migration_dependencies: required: - d6_filter_format - d6_user_role - d6_user_picture_entity_display - d6_user_picture_entity_form_display optional: - d6_user_picture_file

Execution flow

class MigrateExecutable { /** Performs an import operation - migrate items from source to destination. */ public function import() { $source = $this->getSource(); $id_map = $this->migration->getIdMap(); $source->rewind(); while ($source->valid()) { $row = $source->current(); $this->processRow($row); $destination_id_values = $destination->import($row, $id_map->lookupDestinationId($this->sourceIdValues)); $id_map->saveIdMapping($row, $destination_id_values, $this->sourceRowStatus, $this->rollbackAction); $source->next(); } }

Source plugins

Provides source rows - mostly custom

1.getIterator(): iterator producing rows2.prepareRow(): add more data to a row3.There are hooks for prepareRow()

MigrateSourceInterface

Source example - core/** * Drupal 6 menu source from database. * * @MigrateSource( * id = "d6_menu", * source_provider = "menu" * ) */class Menu extends DrupalSqlBase {

/** * {@inheritdoc} */ public function query() { $query = $this->select('menu_custom', 'm') ->fields('m', array('menu_name', 'title', 'description')); return $query; }

Source example - custom

public function count() { if (is_array($this->getData())) { return count($this->getData()); } return 0; } public function getIterator() { return new \ArrayIterator($this->getData()); }

protected function getData() { if (!isset($this->data)) { $this->data = array(); foreach ($this->fetchDataFromYandexDirect() as $key => $value) { $this->data[$key] = (array) $value; } } return $this->data; }

Process plugins

●Keys are destination properties●Values are process pipelines●Each pipeline is a series of process plugins +

configuration●There are shorthands

MigrateProcessInterface::transform()

Process pipelines

process: id: - plugin: machine_name source: name - plugin: dedupe_entity entity_type: user_role field: id - plugin: user_update_8002 #custom

Process plugins shipped

Constant values

Plugins: get concat dedupebase iterator skip_row_if_not_set default_value extract

flatten iterator migration skip_process_on_empty skip_row_on_empty static map machine_name dedupe_entity callback

Process plugin example

public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) { $new_value = $this->getTransliteration()->transliterate($value, LanguageInterface::LANGCODE_DEFAULT, '_'); $new_value = strtolower($new_value); $new_value = preg_replace('/[^a-z0-9_]+/', '_', $new_value); return preg_replace('/_+/', '_', $new_value); }

Destination plugins

●Does the actual import●Almost always provided by migrate module●Most common is entity:$entity_typeo entity:nodeo entity:user

●If you are writing one, you are doing it wrong

MigrateDestinationInterface

Destination plugins shipped

●Config●Entity●Null●for custom tables: url_alias, user_data…

destination: plugin: config config_name: user.mail

Destination plugin example

/** * {@inheritdoc} */ public function import(Row $row, array $old_destination_id_values = array()) {

$path = $this->aliasStorage->save( $row->getDestinationProperty('source'), $row->getDestinationProperty('alias'), $row->getDestinationProperty('langcode'), $old_destination_id_values ? $old_destination_id_values[0] : NULL );

return array($path['pid']); }

Demo

●Drush●UI sandbox

Drush or custom code

Recommended way to execute - DRUSH

Custom code: public function submitForm(array &$form, array &$form_state) { /** @var $migration \Drupal\migrate\Entity\MigrationInterface */ $migration = entity_load('migration', $form_state['values']['migration']);

$executable = new MigrateExecutable($migration, $this); $executable->import(); // Display statistics. $this->getStats($form, $form_state); $form_state['rebuild'] = TRUE; }

How to help

Document driven development http://dgo.to/2127611

Open issues of migration system:http://goo.gl/fmVNQl

Drupal groups http://dgo.to/g/impIRC: Freenode #drupal-migrate

Links

https://www.drupal.org/upgrade/migratehttps://www.drupal.org/node/2127611https://groups.drupal.org/impIRC: Freenode #drupal-migrate

Questions & Discussions

Andy Postnikov http://dgo.to/@andypostPavel Makhrinsky http://dgo.to/@gumanist

Kiev 2014