The Myths The Myths* *, Musts Musts* * and Migraines and - - PowerPoint PPT Presentation

the myths the myths musts musts and migraines and
SMART_READER_LITE
LIVE PREVIEW

The Myths The Myths* *, Musts Musts* * and Migraines and - - PowerPoint PPT Presentation

The Myths The Myths* *, Musts Musts* * and Migraines and Migraines* * of Migrations of Migrations Marc van Gend Marc van Gend @marcvangend Drupal Tech Talk Drupal Tech Talk April 26, ezCompany, Tilburg April 26, ezCompany, Tilburg


slide-1
SLIDE 1

The Myths The Myths* *, Musts Musts* * and Migraines and Migraines* *

  • f Migrations
  • f Migrations
slide-2
SLIDE 2

Marc van Gend Marc van Gend

@marcvangend

slide-3
SLIDE 3

Drupal Tech Talk Drupal Tech Talk April 26, ezCompany, Tilburg April 26, ezCompany, Tilburg

slide-4
SLIDE 4

Who are you? Who are you?

Developers Project managers Site owners ("the client") None of the above

* * * *

slide-5
SLIDE 5

Quiz Quiz

The key to a successful migration is...

  • A. Good clean source data
  • B. A committed, cooperating client
  • C. Plenty of development time
slide-6
SLIDE 6

You were right! You were right! You were right! You were right!

Everybody was right! Everybody was right!

slide-7
SLIDE 7

Non-Drupal to Drupal migrations Non-Drupal to Drupal migrations

Source - Process - Destination Setup My First Migration™ Source data Process plugins Project context Tips

* * * * * * *

slide-8
SLIDE 8

*Myth Myth Migrations are Complicated Migrations are Complicated

slide-9
SLIDE 9

Source. Source. Process. Process. Destination. Destination.

Migrations are straight-forward. Literally.

slide-10
SLIDE 10

Source Source

Database, File, URL... 1 result per migration item Defines unique Source ID

* * *

PHP: class MySourcePlugin extends SourcePluginBase Drupal Console: drupal generate:plugin:migrate:source {}

slide-11
SLIDE 11

Process Process

Get, Concat, MigrateLookup, custom... Assigns values to fields Chainable

* * *

PHP: class MyProcessPlugin extends ProcessPluginBase {} Drupal Console: drupal generate:plugin:migrate:process

slide-12
SLIDE 12

Destination Destination

Node, Term, User, Redirect, Setting, custom... Writes collected data to Drupal DB Can support rollback Maps Source ID -> Destination ID

* * * *

PHP: class MyDestinationPlugin extends DestinationBase {} Drupal Console: (nope)

slide-13
SLIDE 13

*Must Must The right tools The right tools

Modules Tools Custom module Test site

* * * *

slide-14
SLIDE 14

Modules Modules

Migrate (core) Migrate (core)

Migrate API and base functionality Continuous migrations with ID mapping

Migrate Plus Migrate Plus

Define migrations as config entities Additional plugins and enhancements Data parsers and authentication Examples

Migrate Tools Migrate Tools

Drush commands and UI

slide-15
SLIDE 15

Tools Tools

Drush Drush

Import migration config Run migrations Rollback, reset, status, etc.

Drupal Console Drupal Console

Create plugins

Database manager Database manager

PhpStorm, phpMyAdmin

slide-16
SLIDE 16

Custom module Custom module

migrate_demo ├── migrate_demo.info.yml ├── config │ └── install │ ├── migrate_plus.migration.demo_node_article.yml │ └── migrate_plus.migration_group.demo.yml └── src └── Plugin └── migrate ├── process │ └── TitleCleanup.php └── source └── DemoNodeArticle.php

slide-17
SLIDE 17

Demo Site Demo Site

Source Source

Music database (Chinook): Artist ⪪ Album

Drupal Drupal

Artist: Title Album: Title, Artist, Release date, URL

* *

slide-18
SLIDE 18

My First Migration™ My First Migration™

Migrate Group Migration Go!

* * *

slide-19
SLIDE 19

*Must Must Handwritten YAML Handwritten YAML

# Enough about you, let's talk about me! name: Marc favorites: music: dEUS beer:

  • IPA
  • Triple

colleagues:

  • name: Dirk

role: Support engineer

  • name: Joyce

role: Drupal developer

slide-20
SLIDE 20

Migration groups Migration groups

Groups migrations (duh!) Import all migrations in group Shared configuration

* * *

slide-21
SLIDE 21
slide-22
SLIDE 22

Migration group config Migration group config

migrate_demo/config/install/migrate_plus.migration_group.demo.yml id: demo label: Demo Imports description: A few demo imports, to demonstrate how to implement migrations. source_type: SQL database shared_configuration: source: key: migrate dependencies: enforced: module:

  • migrate_demo
slide-23
SLIDE 23

Migration source: DB settings Migration source: DB settings

settings.php $databases['migrate']['default'] = array ( 'database' => 'migrate_demo_source', 'username' => 'migrate_demo_source', 'password' => 'Secret!', 'prefix' => '', 'host' => '127.0.0.1', 'port' => '3306', 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql', 'driver' => 'mysql', );

slide-24
SLIDE 24

Migration source: source plugin Migration source: source plugin

migrate_demo/src/Plugin/migrate/source/DemoNodeArtist.php /** * Source plugin for artist content. * * @MigrateSource( * id = "demo_node_artist" * ) */ class DemoNodeArtist extends SqlBase { migrate_demo/src/Plugin/migrate/source/DemoNodeArtist.php

slide-25
SLIDE 25

/** * {@inheritdoc} */ public function query() { $query = $this->select('Artist', 'a')

  • >fields('a', [

'ArtistId', 'Name', ]); return $query; } migrate_demo/src/Plugin/migrate/source/DemoNodeArtist.php

slide-26
SLIDE 26

/** * {@inheritdoc} */ public function fields() { $fields = [ 'ArtistId' => $this->t('Artist ID'), 'Name' => $this->t('Artist name'), ]; return $fields; } migrate_demo/src/Plugin/migrate/source/DemoNodeArtist.php

slide-27
SLIDE 27

Migration config Migration config

migrate_demo/config/install/migrate_plus.migration.demo_node_artist.yml id: demo_node_artist # Migration ID label: Artists # Human name migration_group: demo source: plugin: demo_node_artist # Data source process: title: Name # Use the 'Name' value as title type: plugin: default_value default_value: artist # Node type is 'artist' destination: plugin: entity:node # Save as a node

slide-28
SLIDE 28

*Must Must Importing your config Importing your config

$ drush config-import \

  • -partial \
  • -source=modules/custom/migrate_demo/config/install
slide-29
SLIDE 29

Go! Go!

Or use the UI:

$ drush migrate-import demo_node_artist

slide-30
SLIDE 30

Source data Source data

Human interaction. Where things get messy.

slide-31
SLIDE 31

*Myth Myth “The data is clean and complete” “The data is clean and complete” *Migraine Migraine Believe me. It's not. Believe me. It's not.

slide-32
SLIDE 32

Getting the data Getting the data

How can we access the data? Direct access? Export? API? How do we get updates? How oen? Incremental? With timestamps? How about assets like PDF's and images? What size are we talking about? Number of items, GB's of files

Make some friends at the supplier's side. Make some friends at the supplier's side.

** ** * * * **

slide-33
SLIDE 33

Analyze the provided data Analyze the provided data

Ask the most stupid questions you can think of. What does it all mean? Does everything have a unique, unchanging ID? Do users have unique email addresses? Do all articles have titles? Are records being added and deleted? Yes ⇒ Are unique ID's reused? Does the data contain duplicates? No ⇒ Really? Did you check?

Do not assume people know their own data. Do not assume people know their own data.

* ** * ** **

slide-34
SLIDE 34

Start planning Start planning

Make choices Don't spend 4h automating what takes 8h manually Agree what you will (not) do Have the result tested Functional Content Write a plan for the go-live Content freeze Pick dates Instruct editors

** * ** * ** * *

slide-35
SLIDE 35

*Myth Myth Migrations are Simple Migrations are Simple

(I know. I said migrations are straight-forward.) Prepare to write custom processors.

slide-36
SLIDE 36

(psst, don't forget to start the demo)

slide-37
SLIDE 37

Processors are Awesome Processors are Awesome

Default process plugin: Get “Get the 'Name' property from the current row and use it as title”

process: title: Name Shorthand for: process: title: plugin: get source: Name

slide-38
SLIDE 38

Processors can have Processors can have configuration configuration

process: type: # Entity type plugin: default_value # Plugin ID default_value: album # Fixed value In the plugin: $this->configuration['default_value']; // Returns "album".

slide-39
SLIDE 39

Linking migrations together Linking migrations together

The migration_lookup process plugin “Get the ID of the entity which was created when demo_node_artist imported this ArtistID.”

process: field_artist: # Entity reference field plugin: migration_lookup migration: demo_node_artist # Linked migration ID source: ArtistId # Source ID

slide-40
SLIDE 40

Chaining process plugins Chaining process plugins

process: uid:

  • plugin: author_deduplicate # Custom deduplication processor

source: author_id

  • plugin: migration_lookup # Migration Lookup returns a UID

migration: users # No 'source' property, because chaining!

  • plugin: default_value # Result is passed to the next processor

default_value: 44 # If empty, use UID 44

slide-41
SLIDE 41

A custom processor A custom processor

migrate_demo/src/Plugin/migrate/process/SpotifyInfo.php /** * Retrieves album info through the Spotify Web API. * * @MigrateProcessPlugin( * id = "spotify_info", * ) */ class SpotifyInfo extends ProcessPluginBase { migrate_demo/src/Plugin/migrate/process/SpotifyInfo.php

slide-42
SLIDE 42

/** * {@inheritdoc} */ public function transform($value, MigrateExecutableInterface $migrate_executabl $type = $this->configuration['type']; $query_info = $this->getSpotifyQueryInfo($value, $type); $spotify_result = $this->spotifyQuery($query_info['query'], $type); $property = $this->configuration['property']; $data_path = array_merge($query_info['parents'], explode('][', $property)); return NestedArray::getValue($spotify_result, $data_path); } migrate_demo/src/Plugin/migrate/process/SpotifyInfo.php

slide-43
SLIDE 43

protected function getSpotifyQueryInfo($value, $type) { switch ($type) { case 'album': // Expect $value to be an array: [album title, artist name]. list($title, $artist) = $value; $query = "album:$title artist:$artist"; $parents = ['albums', 'items', 0]; break; } if (empty($query)) { throw new MigrateSkipProcessException('Could not build a query.'); } return ['query' => $query, 'parents' => $parents]; } migrate_demo/src/Plugin/migrate/process/SpotifyInfo.php

slide-44
SLIDE 44

A custom processor: config A custom processor: config

process: field_release_date: plugin: spotify_info source:

  • Title
  • ArtistName

type: album property: release_date field_spotify_url/uri: # Link fields are composed of multiple values plugin: spotify_info source:

  • Title
  • ArtistName

type: album property: external_urls][spotify # Will be split into an array

slide-45
SLIDE 45

*Migraine Migraine A migration never comes alone A migration never comes alone

If everything was perfect, there wouldn't be a migration, right?

slide-46
SLIDE 46

Client goals Client goals

What they say What it means New site New URL's New design An image on every node New navigation Revised categories New workflow Different input filters ...and the existing content will magically fit in.

slide-47
SLIDE 47

Complexity = changes² Complexity = changes²

Reduce the number of changes introduced with the migration. Spotify process plugin = A really bad idea

slide-48
SLIDE 48

*Must Must Start early Start early

Adapt your site to old content and future needs. Migrate early, keep importing. Estimate generously. Double it.

slide-49
SLIDE 49

Tips & tricks Tips & tricks

(If we have time)

Save time: performance Save time: performance

Disable search indexing Run migrations with Drush

* *

slide-50
SLIDE 50

Save time: reduced dataset Save time: reduced dataset

Imports approximately 1 in every 100 items.

settings.local.php $settings['my_migration_reduce_factor'] = 100; mySourcePlugin::query() $reduce_factor = Settings::get('my_migration_reduce_factor'); if ($reduce_factor && is_int($reduce_factor)) { $query->where('MOD(a.id, :reduce_factor) = 0', [':reduce_factor' => $reduce_factor]); }

slide-51
SLIDE 51

Manual edits... now what? Manual edits... now what?

Run a migration on selected fields:

  • verwrite_properties ignores all values except explicitly listed.

destination: plugin: 'entity:node'

  • verwrite_properties:
  • category
slide-52
SLIDE 52

Shortcut: entity_generate Shortcut: entity_generate

No rollbacks, no mappings, no nothing. Great for things that don't have a source ID.

process: tags:

  • plugin: explode

source: keywords # Eg. "Foo,Bar,Baz" delimiter: ',' # Explode comma separated string to array

  • plugin: entity_generate # Generate taxonomy terms that don't exist
slide-53
SLIDE 53

Come for the software, Come for the software, stay for the community stay for the community

Thank you: Thank you:

Audience | Sponsors | LimoenGroen | Drupal Community

slide-54
SLIDE 54

Questions? Questions?