파일 엔터티를 미디어 엔터티로 어떻게 마이그레이션합니까?


10

D7에서 D8 로의 마이그레이션에 Migrate 모듈을 사용하고 있으며 마이그레이션에 대한보다 세부적인 제어를 원했기 때문에 내장 된 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였습니다. 이상적인 세계에서는이 중간 단계를 생성하고 파일 엔터티를 미디어 엔터티로 마이그레이션 한 다음 마이그레이션을 기사 마이그레이션에 매핑하는 세 번째 마이그레이션을 만드는 방법을 찾고 싶습니다. 그러나 나는 이것을하는 좋은 방법을 알 수 없습니다.

계획 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
destinationField 구성은 무엇입니까?
dba

좋아, 나는 그것을 스스로 알아 냈습니다. 미디어 유형의 자산 필드입니다 field_media_image. 이미지는 입니다.
dba

파일 대체 / 제목 속성을 어떻게 처리합니까?
mpp

테스트되었으며 제대로 작동하지만 "migration"플러그인은 더 이상 사용되지 않으며 이미 최신 버전에서 작동하지 않기 때문에 "migration_lookup"플러그인을 사용해야 할 것입니다. 다음은 사용자 사진을 가져 오기 위해 작동했습니다. 플러그인 : migration_lookup 마이그레이션 : my_file_migration 소스 : picture 또한 번들이없는 엔티티 (예 : 사용자 사진)를 마이그레이션하는 경우 여기에서 패치가 필요할 것입니다. drupal.org/project/migrate_plus/issues / 2787219 , 그렇지 않으면 "entity_lookup 플러그인에는 value_key가 필요합니다. 없음"오류가 표시됩니다. 마이그레이션시.
Mirsoft

누구든지 $ entityId가 어떻게 발견되는지 설명해 주시겠습니까?

2

허용 된 답변을 많이 주셔서 감사하지만 이미 사용되지 않는 정의가 있었고 대체 및 제목 이미지 속성 게시를 지원하지 않았습니다. 따라서 최신 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에 대한 추가 소스 플러그인을 만들어야 함). 또한 근본적인 차이점이 하나 있습니다. migrate_file_to_media 모듈은 특정 엔티티에 첨부 된 파일 만 변환하고 (= 1 단계에서 = entity_type 및 번들이 필요함) 승인 된 솔루션에는이 요구 사항이 없으며 먼저 (D7)에서 모든 파일 엔티티를 마이그레이션합니다. 출처.
Mirsoft
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.