如何将文件实体迁移到媒体实体?


10

我正在使用Migrate模块进行从D7到D8的迁移,并且正在用代码手动编写整个迁移(而不是使用内置的D7迁移模块,因为我想对迁移进行更多的粒度控制。)

我具有以下结构:D7站点有一个image字段,其中图像存储为File实体。在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。在理想的世界中,我想找到一种创建第三次迁移的方法,该方法将创建此中间步骤,并将文件实体迁移到Media Entities,然后将该迁移映射到Articles迁移。但是,我找不到解决此问题的好方法。

计划B只是为图像迁移创建一个流程插件,该插件将手动创建文件实体,将其附加到媒体实体,然后将该迁移传递给Articles(这省去了中间步骤)。但是,这意味着尽管可以回滚媒体实体,但不能进行文件实体。

Answers:


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

您如何处理文件的alt / title属性?
mpp

经过测试,效果很好,但是您可能需要使用“ migration_lookup”插件,因为“ migration”插件已被弃用,并且无法在我的最新版本中使用。以下是对我有用的导入用户图片的方法:插件:migration_lookup迁移:my_file_migration源:图片另外,如果要迁移不包含捆绑软件的实体(如用户图片),则可能需要从以下位置获取补丁:drupal.org/project/migrate_plus/issues / 2787219,否则会出现错误“ Entity_lookup插件需要一个value_key,但没有找到。” 关于迁移。
Mirsoft '18

任何人都可以解释一下如何在其中找到$ entityId吗?
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;
      }
    }
  }
}


0

如果要将Drupal 8中的文件迁移到媒体实体,则可以使用以下模块:https : //www.drupal.org/project/migrate_file_to_media

它有一个提取脚本,可以自动创建媒体参考字段。此外,它使用二进制哈希检测重复的图像。它支持翻译。


1
该模块默认仅解决D8版本之间的迁移。问题更像是关于从D7迁移到D8的问题,因此该模块不易使用(可能需要创建MediaEntityGenerator.php的附加源插件,该插件将从D7中的附件中读取数据)。还有一个根本的区别:migrate_file_to_media模块仅转换附加到某些实体的文件(在步骤1中需要= entity_type和bundle),而公认的解决方案没有此要求,并且首先从(D7)迁移所有文件实体。资源。
Mirsoft '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.