Wie migriere ich Dateieinheiten in Medienentitäten?

10

Ich verwende das Migrationsmodul für eine Migration von D7 nach D8 und schreibe die gesamte Migration manuell in Code (anstatt das integrierte D7-Migrationsmodul zu verwenden, da ich eine genauere Kontrolle über die Migration wünschte.)

Ich habe die folgende Struktur: Die D7-Site hat ein Bildfeld, in dem Bilder als Dateientitäten gespeichert werden. Auf der D8-Site ist das Bildfeld eine Entitätsreferenz auf eine Medienentität (und die Medienentität verfügt wiederum über ein Bildfeld).

Ursprünglich hatte ich Folgendes für meine Bildermigration:

id: image_files

source:
  plugin: legacy_images
  constants:
    source_base_path: http://example.com/

destination:
  plugin: 'entity:file'

process:
  fid: fid
  filename: filename
  source_full_path:
    -
      plugin: concat
      delimiter: /
      source:
    -     constants/source_base_path
    -     uri
    -
      plugin: urlencode
  uri:
    plugin: file_copy
    source:
      - '@source_full_path'
      - uri
  filemime: filemime
  status: status

In meiner Artikelknoten-Migrationsdatei hatte ich Folgendes:

'field_article_image/target_id':
plugin: migration
migration: image_files
source: field_article_image 

aber mir wurde klar, dass dies nicht funktionieren würde. Die Ziel-ID, die aus der Migration von image_files stammt, waren tatsächlich Dateientitäts-IDs, keine Medienentitäts-IDs. In der idealen Welt möchte ich einen Weg finden, um eine dritte Migration zu erstellen, die diesen mittleren Schritt erstellt, und Dateieinheiten in Medienentitäten zu migrieren und diese Migration dann der Artikelmigration zuzuordnen. Ich kann jedoch keinen guten Weg finden, dies zu tun.

Plan B besteht einfach darin, ein Prozess-Plugin für die Bildmigration zu erstellen, mit dem Dateieinheiten manuell erstellt, an Medienentitäten angehängt und diese Migration an Artikel übergeben werden (dies entfernt den mittleren Schritt). Dies würde jedoch bedeuten, dass Medienentitäten zwar zurückgesetzt werden können, Dateieinheiten jedoch nicht.

user1015214
quelle

Antworten:

4

Am Ende habe ich mich für eine etwas andere Vorgehensweise entschieden. Ich erstelle einen regulären Dateiimport, lege diese Migration als Quelle für mein Referenzfeld für Medienentitäten fest und wende dann ein zweites Prozess-Plugin 'MediaGenerate' an, um die FID in die neue Medienziel-ID zu übersetzen

<?php

namespace Drupal\my_migration\Plugin\migrate\process;

use Drupal\media_entity\Entity\Media;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\MigrateException;
use Drupal\migrate\Row;
use Drupal\migrate_plus\Plugin\migrate\process\EntityGenerate;

/**
 * Generate a media entity with specified metadata.
 *
 * This plugin is to be used by migrations which have media entity reference
 * fields.
 *
 * Available configuration keys:
 * - destinationField: the name of the file field on the media entity.
 *
 * @code
 * process:
 *   'field_files/target_id':
 *     -
 *       plugin: migration
 *       source: files
 *     -
 *       plugin: media_generate
 *       destinationField: image
 *
 * @endcode
 *
 * @MigrateProcessPlugin(
 *   id = "media_generate"
 * )
 */
class MediaGenerate extends EntityGenerate {

/**
* {@inheritdoc}
*/
public function transform($value, MigrateExecutableInterface $migrateExecutable, Row $row, $destinationProperty) {
if (!isset($this->configuration['destinationField'])) {
  throw new MigrateException('Destination field must be set.');
}
// First load the target_id of the file referenced via the migration.
/* @var /Drupal/file/entity/File $file */
$file = $this->entityManager->getStorage('file')->load($value);

if (empty($file)) {
  throw new MigrateException('Referenced file does not exist');
}

// Creates a media entity if the lookup determines it doesn't exist.
$fileName = $file->label();
if (!($entityId = parent::transform($fileName, $migrateExecutable, $row, $destinationProperty))) {
  return NULL;
}
$entity = Media::load($entityId);

$fileId = $file->id();
$entity->{$this->configuration['destinationField']}->setValue($fileId);
$entity->save();

return $entityId;
}

}
user1015214
quelle
1
Was ist die destinationField-Konfiguration?
dba
Ok, ich habe es selbst herausgefunden, es ist das Feld für das Asset im Medientyp, für das Bild ist dies field_media_image.
dba
Wie gehen Sie mit Datei-Alt / Titel-Attributen um?
MPP
Getestet und es funktioniert gut, aber Sie müssen wahrscheinlich das Plugin "Migration_lookup" verwenden, da das Plugin "Migration" veraltet ist und bei meinen neuesten Versionen noch nicht funktioniert hat. Das Folgende hat für mich funktioniert, um Benutzerbilder zu importieren: Plugin: migration_lookup Migration: my_file_migration Quelle: Bild Wenn Sie Entitäten ohne Bundles (wie Benutzerbilder) migrieren, benötigen Sie wahrscheinlich den Patch von hier: drupal.org/project/migrate_plus/issues / 2787219 , andernfalls wird die Fehlermeldung "Das Entity_lookup-Plugin benötigt einen value_key, keiner gefunden." zur Migration.
Mirsoft
Könnte jemand bitte erklären, wie $ entityId darin gefunden wird?
Dibs
2

Ich habe die akzeptierte Antwort sehr geschätzt, sie hatte jedoch bereits einige veraltete Definitionen und unterstützte das Posten von Alt- und Titelbildeigenschaften nicht. Daher habe ich es ein wenig verbessert, um dies zu unterstützen und reibungslos mit dem neuesten Drupal 8.6.x zu arbeiten. Hier ist der Code von MediaGenerate.php (die entsprechende Yaml-Syntax befindet sich im Dokumentkommentar):

<?php

namespace Drupal\my_migration\Plugin\migrate\process;

use Drupal\media\Entity\Media;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\MigrateException;
use Drupal\migrate\Row;
use Drupal\migrate_plus\Plugin\migrate\process\EntityGenerate;

/**
 * Generate a media entity with specified metadata.
 *
 * This plugin is to be used by migrations which have media entity reference
 * fields.
 *
 * Available configuration keys:
 * - destinationField: the name of the file field on the media entity.
 *
 * @code
 * process:
 *   'field_files/target_id':
 *     -
 *       plugin: migration_lookup
 *       migration: my_file_migration
 *       source: field_image/0/fid
 *     -
 *       plugin: media_generate
 *       destinationField: image
 *       imageAltSource: field_image/0/alt
 *       imageTitleSource: field_image/0/title
 *
 * @endcode
 *
 * If image_alt_source and/or image_title_source configuration parameters
 * are provided, alt and/or title image properties will be fetched from provided
 * source fields (if available) and pushed into media entity
 *
 * @MigrateProcessPlugin(
 *   id = "media_generate"
 * )
 */
class MediaGenerate extends EntityGenerate {

  /**
   * {@inheritdoc}
   */
  public function transform($value, MigrateExecutableInterface $migrateExecutable, Row $row, $destinationProperty) {
    if (!isset($this->configuration['destinationField'])) {
      throw new MigrateException('Destination field must be set.');
    }

    // First load the target_id of the file referenced via the migration.
    /* @var /Drupal/file/entity/File $file */
    $file = $this->entityManager->getStorage('file')->load($value);

    if (empty($file)) {
      throw new MigrateException('Referenced file does not exist');
    }

    // Creates a media entity if the lookup determines it doesn't exist.
    $fileName = $file->label();
    if (!($entityId = parent::transform($fileName, $migrateExecutable, $row, $destinationProperty))) {
      return NULL;
    }

    $entity = Media::load($entityId);

    $fileId = $file->id();

    $destinationFieldValues = $entity->{$this->configuration['destinationField']}->getValue();
    $destinationFieldValues[0]['target_id'] = $fileId;

    $this->insertPropertyIntoDestinationField($destinationFieldValues, $row, 'alt', 'imageAltSource');
    $this->insertPropertyIntoDestinationField($destinationFieldValues, $row, 'title', 'imageTitleSource');

    $entity->{$this->configuration['destinationField']}->setValue($destinationFieldValues);
    $entity->save();

    return $entityId;
  }

  protected function insertPropertyIntoDestinationField(array &$destinationFieldValues, Row $row, $propertyKey, $configurationKey) {
    // Set alt and title into media entity if not empty
    if (isset($this->configuration[$configurationKey])) {
      $propertyValue = $row->getSourceProperty($this->configuration[$configurationKey]);
      if (!empty($propertyValue)) {
        $destinationFieldValues[0][$propertyKey] = $propertyValue;
      }
    }
  }
}
Mirsoft
quelle
2

Da Media ein Entitätstyp ist, sollten Sie eine eigene Migration erstellen. Sie können eine neue Quelle aus der Dateitabelle generieren. Hier ist ein Beispiel

https://gist.github.com/jibran/8e7cd2319e873858dd49a272227a4fd2

Dann migration_lookupkönnen Sie mit die Felder wie folgt abbilden.

field_d8_media_image/0/target_id:
  plugin: migration_lookup
  migration: my_media_image
  source: field_d7_image/0/fid
fabianfiorotto
quelle
0

Wenn Sie Dateien in Drupal 8 auf Medieneinheiten migrieren möchten, können Sie dieses Modul verwenden: https://www.drupal.org/project/migrate_file_to_media

Es verfügt über ein Drush-Skript, das automatisch die Medienreferenzfelder erstellt. Zusätzlich werden doppelte Bilder mithilfe eines binären Hashs erkannt. Und es unterstützt Übersetzungen.

Brainski
quelle
1
Dieses Modul löst standardmäßig nur die Migration zwischen D8-Versionen. Die Frage bezieht sich eher auf die Migration von D7 auf D8, sodass das Modul nicht einfach verwendet werden kann (wahrscheinlich muss ein zusätzliches Quell-Plugin für MediaEntityGenerator.php erstellt werden, das Daten aus angehängten Dateien in D7 liest). Es gibt auch einen grundlegenden Unterschied: Das Modul migrate_file_to_media konvertiert nur Dateien, die an eine bestimmte Entität angehängt sind (= Entitätstyp und Bundle sind in Schritt 1 erforderlich), während die akzeptierte Lösung diese Anforderung nicht erfüllt und zunächst alle Dateientitäten aus dem (D7) migriert. Quelle.
Mirsoft