Migration Datei-Felder zu Media-Entities

Ralf Richtsteiger

Senior Frontend Architect
München, Deutschland

Aufgabe / Vorüberlegungen

  • Bestehende Dateifelder in Media-Entities migrieren
  • Einsatz Entity Browser, Multi-File-Upload, usw.
  • media_entity  oder  media ?
  • media mit Drupal 8.4.0 stable
  • 1 Migration reicht ;-)

Migrations-Prozess

  1. Migration bestehender Dateien nach Media-Entities
  2. Migration von Inhalten

Migration bestehender Dateien nach Media-Entities

  1. Media-Modul installieren 
    drush en media -y
  2. Patch von www.drupal.org/node/2835825 downloaden
    enthält Migrations-Template für die Migration
  3. Core patchen 
    patch -p1 < 2835825-21.patch
  4. Mapping der Dateitypen testen und ggf. anpassen
    (siehe ./core/modules/media/migration_templates/file_media.yml)
  5. Module zum Durchführen von Migrationen installieren und aktivieren:
    drush dl migrate_tools && drush en -y migrate migrate_tools

Migration bestehender Dateien nach Media-Entities

  1. Migrations-Status testen drush ms
  2. Migration starten drush mi file_media
  3. Migrations-Status kontrollieren drush ms

Migration von Inhalten

Es kommt ein eigenes PHP-Script zum Einsatz, welches mittels drush ausgeführt wird

Annahme: ein bestehendes Feld field_download_file soll migriert werden

Vorgehen zur erfolgreichen Migration:

  • neues Feld field_download_media anlegen
  • Konfiguration des Migrationsscriptes anpassen
  • Vorgehen bei Inhaltstypen wie auch Paragraph nahezu identisch

Angepasste Konfiguration:

$file_fields = [
  'node' => [
    'field_publication_download' => 'field_publication_media',
  ],
  'paragraph' => [],
];

$image_fields = [
  'node' => [],
  'paragraph' => [
    'field_section_bg_image' => 'field_section_bg_media',
  ]
];

Migration durchführen

  • cp migrate-file-fields.php /drupal-root-path/sites/default
  • cd /drupal-root-path/sites/default
  • drush scr migrate-file-fields.php

Migration erfolgreich?

-----
migrate entries from
  »field_publication_download_target_id« to
  »field_publication_media_target_id«
  
6 entries migrated
-----

-----
migrate entries from
  »field_section_bg_image_target_id« to
  »field_section_bg_media_target_id«
  
28 entries migrated
-----

migrate-file-fields.php

<?php

function get_entries($options) {
  if (db_table_exists('media__field_media_' . $options['media_type']) &&
    db_table_exists($options['table_from']) &&
    db_table_exists($options['table_to'])
  ) {
    $query = <<<EOT
select
  r.bundle,
  r.deleted,
  r.entity_id,
  r.revision_id,
  r.langcode,
  r.delta,
  r.{$options[field_from]},
  m.entity_id as {$options[field_to]}
from
  {$options[table_from]} r
left join
  media__field_media_{$options[media_type]} m
    on
      m.field_media_{$options[media_type]}_target_id = r.{$options[field_from]}
EOT;

    $result = db_query($query);
    return $result->fetchAll(PDO::FETCH_ASSOC);
}
  else {
    return [];
  }
}

function do_field_migration($map = [], $type = 'file') {
  $config = [];
  foreach ($map as $bundle => $fields) {
    foreach ($fields as $old => $new) {
      $config[] = [
        'field_from' => $old . '_target_id',
        'field_to' => $new . '_target_id',
        'media_type' => $type,
        'table_from' => $bundle . '__' . $old,
        'table_to' => $bundle . '__' . $new,
        'revision_to' => $bundle . '_revision__' . $new,
      ];
    }
  }
  
  $clear_cache = false;
  
  foreach ($config as $options) {
    $results = get_entries($options);
    $count = count($results);
    
    print "\n-----\nmigrate entries from\n  »{$options[field_from]}« to\n  »{$options[field_to]}«\n";
    foreach ($results as $result) {
      // File-Fields could have documents and images too. Avoid SQL errors by skipping
      // not existing media items. Do a new migration with changed media type instead.
      if (empty($result[$options['field_to']])) {
        $count--;
        continue;
      }
      $keys = [
        'entity_id' => $result['entity_id'],
        'revision_id' => $result['revision_id'],
        'langcode' => $result['langcode']
      ];
      $fields = array_filter($result, function ($k) use ($options) {
        return $k != $options['field_from'];
      }, ARRAY_FILTER_USE_KEY);
      db_merge($options['table_to'])
        ->key($keys)
        ->fields($fields)
        ->execute();
      db_merge($options['revision_to'])
        ->key($keys)
        ->fields($fields)
        ->execute();
    }
    print "\n" . $count . " entries migrated\n-----\n";
    $clear_cache = $clear_cache || $count;
  }
  
  if ($clear_cache) {
    drupal_flush_all_caches();
  }
}

$files = [
  'node' => [
    'field_publication_download' => 'field_publication_media',
  ],
  'paragraph' => []
];

$images = [
  'node' => [],
  'paragraph' => [
    'field_section_bg_image' => 'field_section_bg_media',
  ]
];

do_field_migration($files);
do_field_migration($images, 'image');

Download Script
(Verwendung ohne Gewähr)

Vielen Dank

Ralf Richtsteiger