¿Cómo migro entidades de archivo a entidades de medios?

10

Estoy usando el módulo Migrate para una migración de D7 a D8 y estoy escribiendo toda la migración manualmente en código (en lugar de usar el módulo de migración D7 integrado, ya que quería un control más granular de la migración).

Tengo la siguiente estructura: el sitio D7 tiene un campo de imagen donde las imágenes se almacenan como entidades de archivo. En el sitio D8, el campo de imagen es una referencia de entidad a una entidad de Medios (y la entidad de Medios a su vez tiene un campo de Imagen).

Originalmente, tenía lo siguiente para mi migración de Imágenes:

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

Dentro de mi archivo de migración de nodo de artículo, tenía lo siguiente:

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

pero me di cuenta de que esto no funcionaría. El target_id proveniente de la migración de image_files era realmente ID de entidad de archivo, no ID de entidad de medios. En el mundo ideal, me gustaría encontrar una manera de crear una tercera migración, que crearía este paso intermedio, y migraría las entidades de archivo a Entidades de Medios y luego asignaría esa migración a la migración de Artículos. Sin embargo, no puedo encontrar una buena manera de hacer esto.

El Plan B será simplemente crear un complemento de proceso para la migración de imágenes, que creará manualmente entidades de archivos, las adjuntará a entidades de medios y pasará esa migración a Artículos (esto elimina el paso intermedio). Sin embargo, esto significaría que, si bien las entidades de medios se pueden revertir, las entidades de archivo no.

usuario1015214
fuente

Respuestas:

4

Terminé eligiendo hacerlo ligeramente diferente: creo una importación de archivo regular, configuré esa migración como la fuente del campo de referencia de mi entidad de medios y luego apliqué un segundo complemento de proceso 'MediaGenerate' para traducir el FID al nuevo medio 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;
}

}
usuario1015214
fuente
1
¿Cuál es la configuración de destinationField?
dba
Ok, lo descubrí por mí mismo, es el campo para el activo en el tipo de medio, por imagen, esto es field_media_image.
dba
¿Cómo manejas los atributos alt / title del archivo?
mpp
Probado y funciona bien, sin embargo, es probable que necesite usar el complemento "Migration_lookup" porque el complemento "Migración" está en desuso y ya no funciona en mis últimas versiones. Lo siguiente funcionó para mí para importar imágenes de usuario: plugin: Migration_lookup Migración: my_file_migration Fuente: imagen Además, si migra entidades sin paquetes (como imágenes de usuario), probablemente necesitará el parche desde aquí: drupal.org/project/migrate_plus/issues / 2787219 , de lo contrario, aparece un error "El complemento entity_lookup requiere una clave_valor, ninguna ubicada". sobre migración
Mirsoft
¿Alguien podría explicar cómo se encuentra $ entityId en esto?
dibs
2

Aprecié mucho la respuesta aceptada, sin embargo, ya tenía algunas definiciones obsoletas y no admitía publicar propiedades de imagen de título y alt. Por lo tanto, lo mejoré un poco para admitir eso y trabajar sin problemas con la última versión de Drupal 8.6.x. Aquí está el código de MediaGenerate.php (la sintaxis apropiada de Yaml está dentro del comentario del documento):

<?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
fuente
2

Como los medios son un tipo de entidad, debe crear su propia migración. Puede generar una nueva fuente desde la tabla de archivos. Aquí hay un ejemplo

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

Luego con migration_lookupusted puede mapear los campos de esta manera.

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

Si desea migrar archivos en Drupal 8 a entidades de medios, puede usar este módulo: https://www.drupal.org/project/migrate_file_to_media

Tiene un script drush, que crea automáticamente los campos de referencia de medios. Además, detecta imágenes duplicadas utilizando un hash binario. Y es compatible con las traducciones.

Brainski
fuente
1
Ese módulo solo resuelve la migración entre versiones D8 de forma predeterminada. La pregunta se parece más a la migración de D7 a D8, por lo que ese módulo no se puede usar fácilmente (probablemente sea necesario crear un complemento fuente adicional para MediaEntityGenerator.php que leería datos de archivos adjuntos en D7). También hay una diferencia fundamental: el módulo migrate_file_to_media solo convierte los archivos adjuntos a cierta entidad (= se requieren el tipo de entidad y el paquete en el paso 1), mientras que la solución aceptada no tiene este requisito y primero migra todas las entidades de archivo desde (D7) fuente.
Mirsoft