Bagaimana cara memigrasikan entitas file ke entitas media?

10

Saya menggunakan modul Migrasi untuk migrasi D7 ke D8 dan saya menulis seluruh migrasi secara manual dalam kode (daripada menggunakan modul migrasi D7 bawaan, karena saya ingin lebih banyak kontrol granual pada migrasi.)

Saya memiliki struktur berikut: situs D7 memiliki bidang gambar tempat gambar disimpan sebagai entitas File. Di situs D8, bidang gambar adalah referensi entitas ke entitas Media (dan entitas Media pada gilirannya memiliki bidang Gambar.)

Awalnya, saya memiliki yang berikut untuk migrasi Gambar saya:

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

Di dalam file migrasi simpul artikel saya, saya memiliki yang berikut ini:

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

tetapi saya menyadari bahwa ini tidak akan berhasil. Target_id yang berasal dari migrasi image_files benar-benar ID Entitas File, bukan ID entitas media. Di dunia yang ideal, saya ingin menemukan cara untuk membuat migrasi ketiga, yang akan membuat langkah tengah ini, dan memigrasikan entitas file ke Entitas Media dan kemudian memetakan migrasi tersebut ke migrasi Artikel. Namun, saya tidak bisa menemukan cara yang baik untuk melakukan ini.

Plan B hanya akan membuat plugin proses untuk migrasi gambar, yang secara manual akan membuat entitas file, melampirkannya ke entitas media, dan meneruskan migrasi itu ke Artikel (ini menghilangkan langkah tengah). Ini berarti, meskipun, sementara entitas Media dapat diputar kembali, Entitas File tidak bisa.

pengguna1015214
sumber

Jawaban:

4

Saya akhirnya memilih untuk melakukannya sedikit berbeda - saya membuat impor file biasa, menetapkan migrasi itu sebagai sumber untuk bidang referensi entitas media saya, dan kemudian menerapkan plugin proses kedua 'MediaGenerate' untuk menerjemahkan FID ke media target_id baru

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

}
pengguna1015214
sumber
1
Apa konfigurasi destinationField?
dba
Ok saya menemukan sendiri, itu adalah bidang untuk aset dalam jenis media, untuk gambar ini field_media_image.
dba
Bagaimana Anda menangani atribut alt / judul file?
mpp
Diuji dan berfungsi dengan baik, namun Anda mungkin perlu menggunakan plugin "migrasi_lookup" karena plugin "migrasi" sudah tidak digunakan lagi dan belum berfungsi pada versi terbaru saya. Berikut ini berhasil bagi saya untuk mengimpor gambar pengguna: plugin: migrasi_lookup migrasi: sumber my_file_migrasi: gambar Juga, jika Anda memigrasikan entitas tanpa bundel (seperti gambar pengguna), Anda mungkin perlu tambalan dari sini: drupal.org/project/migrate_plus/issues / 2787219 , jika tidak Anda mendapatkan kesalahan "Plugin entitas_lookup membutuhkan value_key, tidak ada yang terletak." tentang migrasi.
Mirsoft
Adakah yang bisa menjelaskan bagaimana $ entityId ditemukan dalam hal ini?
dibs
2

Saya sangat menghargai jawaban yang diterima, namun sudah memiliki beberapa definisi yang sudah usang dan tidak mendukung posting alt dan properti gambar judul. Jadi, saya meningkatkannya sedikit untuk mendukung itu dan bekerja dengan lancar dengan Drupal 8.6.x. Berikut ini kode MediaGenerate.php (sintaks Yaml yang sesuai ada di dalam komentar 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;
      }
    }
  }
}
Mirsoft
sumber
2

Karena Media adalah tipe entitas, Anda harus membuat migrasi sendiri. Anda dapat menghasilkan sumber baru dari tabel file. Berikut ini sebuah contoh

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

Kemudian dengan migration_lookupAnda dapat memetakan bidang seperti ini.

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

Jika Anda ingin memigrasikan file dalam Drupal 8 ke entitas media, Anda dapat menggunakan modul ini: https://www.drupal.org/project/migrate_file_to_media

Ini memiliki skrip drush, yang secara otomatis membuat bidang referensi media. Selain itu mendeteksi gambar duplikat menggunakan hash biner. Dan itu mendukung terjemahan.

Brainski
sumber
1
Modul itu hanya menyelesaikan migrasi antara versi D8 secara default. Pertanyaannya lebih seperti tentang migrasi dari D7 ke D8, sehingga modul tidak dapat dengan mudah digunakan (plugin sumber tambahan untuk MediaEntityGenerator.php yang akan membaca data dari file terlampir di D7 mungkin perlu dibuat). Ada juga satu perbedaan mendasar: modul migrate_file_to_media hanya mengonversi file yang dilampirkan ke entitas tertentu (= entitas_type dan bundel diperlukan pada langkah1), sedangkan solusi yang diterima tidak memiliki persyaratan ini dan terlebih dahulu memigrasikan semua entitas file dari (D7) sumber.
Mirsoft