web-dev-qa-db-fra.com

Comment migrer des entités de fichier vers des entités multimédias?

J'utilise le module Migrate pour une migration D7 vers D8 et j'écris toute la migration manuellement dans le code (plutôt que d'utiliser le module de migration D7 intégré, car je voulais un contrôle plus granulaire de la migration.)

J'ai la structure suivante: le site D7 a un champ d'image où les images sont stockées en tant qu'entités de fichier. Sur le site D8, le champ image est une référence d'entité à une entité média (et l'entité média à son tour a un champ image).

À l'origine, j'avais les éléments suivants pour ma migration d'images:

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

Dans mon fichier de migration de nœud d'article, j'avais les éléments suivants:

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

mais j'ai réalisé que cela ne fonctionnerait pas. L'ID cible provenant de la migration des fichiers image était en fait des ID d'entité de fichier, et non des ID d'entité multimédia. Dans le monde idéal, j'aimerais trouver un moyen de créer une troisième migration, qui créerait cette étape intermédiaire, et migrerait les entités de fichier vers les entités multimédias, puis mapperait cette migration vers la migration des articles. Cependant, je ne peux pas trouver une bonne façon de procéder.

Le plan B consistera simplement à créer un plug-in de processus pour la migration des images, qui créera manuellement des entités de fichier, les joindra aux entités multimédias et passera cette migration aux articles (cela supprime l'étape intermédiaire). Cela signifierait, cependant, que même si les entités médias peuvent être annulées, les entités fichier ne le peuvent pas.

10
user1015214

J'ai fini par choisir de le faire légèrement différent - je crée une importation de fichier régulière, définit cette migration comme source pour mon champ de référence d'entité multimédia, puis applique un deuxième plugin de processus 'MediaGenerate' pour traduire le FID en nouveau média target_id

<?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;
}

}
4
user1015214

J'ai beaucoup apprécié la réponse acceptée, mais elle contient déjà des définitions obsolètes et ne prend pas en charge l'affichage des propriétés des images alt et title. Ainsi, je l'ai un peu amélioré pour prendre en charge cela et pour travailler en douceur avec la dernière Drupal 8.6.x. Voici le code de MediaGenerate.php (la syntaxe Yaml appropriée est à l'intérieur du commentaire doc):

<?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;
      }
    }
  }
}
2
Mirsoft

Comme Media est un type d'entité, vous devez créer sa propre migration. Vous pouvez générer une nouvelle source à partir de la table de fichiers. Voici un exemple

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

Puis avec migration_lookup vous pouvez mapper les champs comme ceci.

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

Si vous souhaitez migrer des fichiers dans Drupal 8 vers des entités multimédias, vous pouvez utiliser ce module: https://www.drupal.org/project/migrate_file_to_media

Il a un script drush, qui crée automatiquement les champs de référence du média. De plus, il détecte les images en double à l'aide d'un hachage binaire. Et il prend en charge les traductions.

0
Brainski