Як перенести файлові об'єкти в медіа-об’єкти?


10

Я використовую модуль Migrate для міграції від D7 до D8 і записую всю міграцію вручну в коді (замість того, щоб використовувати вбудований модуль міграції D7, оскільки я хотів більш детально контролювати міграцію.)

Я маю таку структуру: на сайті D7 є поле зображення, де зображення зберігаються як Файлові сутності. На сайті D8 поле зображення є посиланням на сутність медіа-об'єкта (а медіа-об'єкт у свою чергу має поле Зображення.)

Спочатку у мене були міграції зображень:

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

Всередині файлу міграції вузла статті у мене було таке:

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

але я зрозумів, що це не вийде. Цільовий_id, що походить від міграції image_files, насправді був ідентифікатором файлової сутності, а не ідентифікатором медіа-суті. В ідеальному світі я хотів би знайти спосіб створення третьої міграції, яка створила б цей середній крок, і переміщення сутностей файлів у медіа-об'єкти, а потім відобразити цю міграцію до міграції статей. Однак я не можу розібратися, як це зробити.

План B буде просто створити плагін процесу для міграції зображень, який вручну створюватиме файлові об'єкти, приєднувати їх до медіа-об'єктів та передавати цю міграцію в статті (це видаляє середній крок). Це означає, що, хоча медіа-об'єкти можна повернути назад, файлові об'єкти не могли.

Відповіді:


4

Я вирішив зробити це дещо інакше - я створив звичайний імпорт файлу, встановив цю міграцію як джерело для мого довідкового поля медіа-об'єкта, а потім застосував другий плагін процесу 'MediaGenerate' для перекладу FID на новий медіа 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
Що таке конфігурація призначенняField?
дба

Гаразд я зрозумів це сам, це поле для активу в медіа-типі, для іміджу це field_media_image.
дба

Як обробляти атрибути alt / title файлу?
mpp

Випробувано, і він працює чудово, проте, ймовірно, вам доведеться використовувати плагін "migra_lookup", оскільки плагін "migration" застарілий і не працював на моїх останніх версіях. Слідом за мною імпортували фотографії користувачів: плагін: migra_lookup міграція: my_file_migration джерело: малюнок Також, якщо ви переміщуєте об'єкти без пакетів (наприклад, фотографії користувачів), вам, мабуть, потрібен патч звідси: drupal.org/project/migrate_plus/isissue / 2787219 , в іншому випадку ви отримаєте помилку "Плагін entit_lookup вимагає значення_ ключа, жодного не розміщено." про міграцію.
Мірсофт

Чи може хто-небудь пояснити, будь ласка, як у цьому знайдено $ entitId?
dibs

2

Я дуже оцінив прийняту відповідь, однак вона вже мала деякі застарілі визначення та не підтримувала розміщення властивостей зображення alt та title. Таким чином, я трохи покращив це, щоб підтримати це та безперебійно працювати з останніми Drupal 8.6.x. Ось код MediaGenerate.php (відповідний синтаксис Yaml знаходиться в коментарі 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

Оскільки медіа - це тип сутності, ви повинні створити власну міграцію. Можна створити нове джерело з таблиці файлів. Ось приклад

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

Тоді за допомогою migration_lookupвас можна зіставити подібні поля.

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

0

Якщо ви хочете перемістити файли в Drupal 8 на медіа-об'єкти, ви можете використовувати цей модуль: https://www.drupal.org/project/migrate_file_to_media

Він має друкований сценарій, який автоматично створює медіапосилання. Крім того, він виявляє повторювані зображення, використовуючи двійковий хеш. І він підтримує переклади.


1
Цей модуль за замовчуванням вирішує міграцію між версіями D8. Питання більше нагадує про міграцію з D7 на D8, так що цей модуль не може бути легко використаний (можливо, потрібно буде створити додатковий модуль джерела до MediaEntityGenerator.php, який би читав дані з приєднаних файлів у D7). Існує також одна принципова відмінність: модуль migrate_file_to_media перетворює лише файли, приєднані до певного об'єкта (= крок_типу і пакет потрібні на етапі1), тоді як прийняте рішення не має цієї вимоги, і воно спочатку мігрує всі файлові сутності з (D7) джерело.
Мірсофт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.