ファイルエンティティをメディアエンティティに移行するにはどうすればよいですか?


10

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 

しかし、これはうまくいかないことに気づきました。image_filesマイグレーションからのtarget_idは、実際にはメディアエンティティIDではなく、ファイルエンティティIDでした。理想的な世界では、この中間のステップを作成し、ファイルエンティティをメディアエンティティに移行し、その移行を記事の移行にマッピングする3番目の移行を作成する方法を見つけたいと思います。しかし、私はこれを行う良い方法を理解できません。

プランBは、イメージの移行用のプロセスプラグインを作成するだけです。これにより、手動でファイルエンティティが作成され、メディアエンティティにアタッチされ、その移行がArticlesに渡されます(これにより、中央のステップが削除されます)。ただし、メディアエンティティはロールバックできますが、ファイルエンティティはロールバックできませんでした。

回答:


4

少し異なる方法を選択することになりました。通常のファイルインポートを作成し、その移行をメディアエンティティ参照フィールドのソースとして設定してから、2番目のプロセスプラグイン「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
destinationField設定とは何ですか?
dba 2018年

わかりました、私はそれを自分で見つけました、それはメディアタイプのアセットのフィールドです、画像の場合はこれですfield_media_image
dba

ファイルのalt / title属性をどのように処理しますか?
mpp、2018

テスト済みで問題なく動作しますが、「migration」プラグインは非推奨であり、私の最新バージョンではすでに機能していないため、「migration_lookup」プラグインを使用する必要がある可能性があります。プラグイン:migration_lookup移行:my_file_migrationソース:画像また、バンドルのないエンティティ(ユーザー画像など)を移行する場合は、おそらくここからパッチが必要になります:drupal.org/project/migrate_plus/issues / 2787219、それ以外の場合は、「entity_lookupプラグインにはvalue_keyが必要ですが、どれも見つかりません」というエラーが発生します。移行時。
Mirsoft、2018年

これで$ entityIdがどのように見つかるかを誰かに説明してもらえますか?
DIBの

2

私は受け入れられた回答に感謝しましたが、すでにいくつかの非推奨の定義があり、altおよびtitle画像のプロパティの投稿をサポートしていませんでした。したがって、それをサポートし、最新のDrupal 8.6.xでスムーズに動作するように少し拡張しました。MediaGenerate.phpのコードは次のとおりです(適切なYaml構文はドキュメントコメント内にあります)。

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

メディア参照フィールドを自動的に作成するDrushスクリプトがあります。さらに、バイナリハッシュを使用して重複画像を検出します。そして、それは翻訳をサポートします。


1
そのモジュールは、デフォルトではD8バージョン間の移行のみを解決します。問題は、D7からD8への移行に似ているため、モジュールを簡単に使用できません(D7の添付ファイルからデータを読み取るMediaEntityGenerator.phpへの追加のソースプラグインを作成する必要がある可能性があります)。基本的な違いも1つあります。migrate_file_to_mediaモジュールは特定のエンティティに添付されたファイルのみを変換します(= entity_typeとバンドルはステップ1で必要です)。承認されたソリューションにはこの要件はなく、最初にすべてのファイルエンティティを(D7)から移行します。ソース。
Mirsoft、2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.