Come migrare le entità file in entità multimediali?


10

Sto usando il modulo Migrate per una migrazione da D7 a D8 e sto scrivendo manualmente l'intera migrazione nel codice (piuttosto che usare il modulo di migrazione D7 incorporato, poiché volevo un controllo più granulare sulla migrazione).

Ho la seguente struttura: il sito D7 ha un campo immagine in cui le immagini sono memorizzate come entità File. Sul sito D8, il campo immagine è un riferimento di entità a un'entità multimediale (e l'entità multimediale a sua volta ha un campo immagine).

Inizialmente, avevo la seguente migrazione per le mie immagini:

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

All'interno del mio file di migrazione del nodo articolo, avevo il seguente:

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

ma mi sono reso conto che questo non avrebbe funzionato. Il target_id proveniente dalla migrazione dei file immagine era in realtà un ID entità file, non un ID entità multimediale. Nel mondo ideale, mi piacerebbe trovare un modo per creare una terza migrazione, che crei questo passaggio intermedio e migra le entità dei file in Entità multimediali e quindi associ tale migrazione alla migrazione degli articoli. Tuttavia, non riesco a capire un buon modo per farlo.

Il piano B consisterà semplicemente nella creazione di un plug-in di processo per la migrazione delle immagini, che creerà manualmente le entità dei file, li collegherà alle entità multimediali e passerà la migrazione agli articoli (questo rimuove il passaggio intermedio). Ciò significherebbe, tuttavia, che mentre le entità multimediali possono essere ripristinate, le entità file non possono.

Risposte:


4

Ho finito per scegliere di farlo in modo leggermente diverso: creo una normale importazione di file, imposto tale migrazione come fonte per il campo di riferimento della mia entità multimediale e quindi ho applicato un secondo plug-in di processo 'MediaGenerate' per tradurre il FID nel nuovo media 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;
}

}

1
Qual è la configurazione di destinationField?
dba,

Ok, l'ho capito da solo, è il campo dell'asset nel tipo di media, per l'immagine questo è field_media_image.
dba,

Come gestite gli attributi alt / title dei file?
mpp,

Testato e funziona bene, tuttavia sarà probabilmente necessario utilizzare il plug-in "migration_lookup" perché il plug-in "migrazione" è obsoleto e non ha funzionato sulle mie ultime versioni. Seguito ha funzionato per me per importare le immagini dell'utente: plugin: migration_lookup migrazione: my_file_migration source: picture Inoltre, se migra entità senza bundle (come le immagini dell'utente), probabilmente avrai bisogno della patch da qui: drupal.org/project/migrate_plus/issues / 2787219 , altrimenti viene visualizzato un errore "Il plug-in entity_lookup richiede un valore_key, nessuno trovato." sulla migrazione.
Mirsoft,

Qualcuno potrebbe spiegare come $ entityId si trova in questo?
dibs,

2

Ho apprezzato molto la risposta accettata, tuttavia aveva già alcune definizioni deprecate e non supportava la pubblicazione delle proprietà dell'immagine alt e del titolo. Pertanto, l'ho migliorato un po 'per supportarlo e per funzionare senza problemi con l'ultimo Drupal 8.6.x. Ecco il codice di MediaGenerate.php (la sintassi Yaml appropriata è all'interno del commento 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;
      }
    }
  }
}

2

Poiché Media è un tipo di entità, è necessario creare la propria migrazione. È possibile generare una nuova fonte dalla tabella dei file. Ecco un esempio

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

Quindi con migration_lookupte puoi mappare i campi in questo modo.

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

0

Se vuoi migrare i file in Drupal 8 su entità multimediali puoi usare questo modulo: https://www.drupal.org/project/migrate_file_to_media

Ha uno script drush, che crea automaticamente i campi di riferimento multimediali. Inoltre rileva immagini duplicate utilizzando un hash binario. E supporta le traduzioni.


1
Quel modulo risolve solo la migrazione tra le versioni D8 per impostazione predefinita. La domanda è più simile alla migrazione da D7 a D8, quindi quel modulo non può essere facilmente usato (sarebbe probabilmente necessario creare un plug-in di origine aggiuntivo per MediaEntityGenerator.php che leggesse i dati dai file allegati in D7). C'è anche una differenza fondamentale: il modulo migrate_file_to_media converte solo i file allegati a una determinata entità (= entity_type e bundle sono richiesti nel passaggio 1), mentre la soluzione accettata non ha questo requisito e migra innanzitutto tutte le entità file dalla (D7) fonte.
Mirsoft,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.