Skip to content

Instantly share code, notes, and snippets.

@jibran
Created March 24, 2017 00:39
Show Gist options
  • Save jibran/8e7cd2319e873858dd49a272227a4fd2 to your computer and use it in GitHub Desktop.
Save jibran/8e7cd2319e873858dd49a272227a4fd2 to your computer and use it in GitHub Desktop.
Migrating Drupal 7 File Entities to Drupal 8 Media Entities
<?php
// modules/custom/my_custom_module/src/Plugin/migrate/source/FileEntity.php
namespace Drupal\my_custom_module\Plugin\migrate\source;
use Drupal\Core\Database\Query\Condition;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity;
/**
* Drupal 7 file_entity source from database.
*
* @MigrateSource(
* id = "file_entity",
* source_provider = "file"
* )
*/
class FileEntity extends FieldableEntity {
/**
* {@inheritdoc}
*/
public function query() {
$query = $this->select('file_managed', 'f')
->fields('f')
->orderBy('f.fid');
if (isset($this->configuration['type'])) {
$query->condition('f.type', $this->configuration['type']);
}
// Filter by scheme(s), if configured.
if (isset($this->configuration['scheme'])) {
$schemes = array();
// Accept either a single scheme, or a list.
foreach ((array) $this->configuration['scheme'] as $scheme) {
$schemes[] = rtrim($scheme) . '://';
}
$schemes = array_map([$this->getDatabase(), 'escapeLike'], $schemes);
// The uri LIKE 'public://%' OR uri LIKE 'private://%'.
$conditions = new Condition('OR');
foreach ($schemes as $scheme) {
$conditions->condition('uri', $scheme . '%', 'LIKE');
}
$query->condition($conditions);
}
return $query;
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
// Get Field API field values.
foreach (array_keys($this->getFields('file', $row->getSourceProperty('type'))) as $field) {
$fid = $row->getSourceProperty('fid');
$row->setSourceProperty($field, $this->getFieldValues('file', $field, $fid));
}
return parent::prepareRow($row);
}
/**
* {@inheritdoc}
*/
public function fields() {
return array(
'fid' => $this->t('File ID'),
'uid' => $this->t('The {users}.uid who added the file. If set to 0, this file was added by an anonymous user.'),
'filename' => $this->t('File name'),
'uri' => $this->t('The URI to access the file'),
'filemime' => $this->t('File MIME Type'),
'status' => $this->t('The published status of a file.'),
'timestamp' => $this->t('The time that the file was added.'),
'type' => $this->t('The type of this file.'),
);
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['fid']['type'] = 'integer';
return $ids;
}
}
# modules/custom/my_custom_module/migrations/my_files.yml
id: my_files
label: Files
migration_tags:
- Custom
source:
plugin: d7_file
constants:
source_base_path: 'sites/default/files/'
old_files_path: 'sites/default/files/migration-files'
process:
filename: filename
source_full_path:
-
plugin: concat
delimiter: /
source:
- constants/old_files_path
- filepath
-
plugin: urlencode
uri:
-
plugin: skip_youtube_files
source:
- '@source_full_path'
- uri
-
plugin: file_copy
filemime: filemime
# filesize is dynamically computed when file entities are saved, so there is
# no point in migrating it.
# filesize: filesize
status: status
# Drupal 7 didn't keep track of the file's creation or update time -- all it
# had was the vague "timestamp" column. So we'll use it for both.
created: timestamp
changed: timestamp
fid: fid
uid:
-
plugin: skip_on_empty
method: process
source: uid
-
plugin: migration
migration: my_users
destination:
plugin: entity:file
migration_dependencies:
required:
- my_users
# modules/custom/my_custom_module/migrations/my_media_audio.yml
id: my_media_audio
label: Media Audio
migration_tags:
- Custom
source:
plugin: file_entity
type: audio
constants:
bundle: 'audio'
process:
mid: fid
bundle: 'constants/bundle'
langcode:
plugin: default_value
source: language
default_value: "und"
name: filename
uid:
-
plugin: skip_on_empty
method: process
source: uid
-
plugin: migration
migration: my_users
status: status
# Drupal 7 didn't keep track of the file's creation or update time -- all it
# had was the vague "timestamp" column. So we'll use it for both.
created: timestamp
changed: timestamp
# File field see media_entity.bundle.audio.yml.
field_media_audio/target_id: fid
# Title field.
field_title: field_title
# Transcript field.
field_transcript: field_transcript
destination:
plugin: entity:media
migration_dependencies:
required:
- my_files
- my_users
To migrate media images, I moved the dedicated field entity fields for alt and title to the image field.
modules/custom/my_custom_module/migrations/my_media_audio.yml
id: my_media_image
label: Files
migration_tags:
- Custom
source:
plugin: file_entity
type: image
constants:
bundle: 'image'
process:
mid: fid
bundle: 'constants/bundle'
langcode:
plugin: default_value
source: language
default_value: "und"
name: filename
uid:
-
plugin: skip_on_empty
method: process
source: uid
-
plugin: migration
migration: my_users
status: status
# Drupal 7 didn't keep track of the file's creation or update time -- all it
# had was the vague "timestamp" column. So we'll use it for both.
created: timestamp
changed: timestamp
# Image field see media_entity.bundle.image.yml.
field_media_image/target_id: fid
field_media_image/alt: field_file_image_alt_text/0/value
field_media_image/title: field_file_image_title_text/0/value
# Description field.
field_description: field_image_description
# Caption field.
field_caption: field_caption
destination:
plugin: entity:media
migration_dependencies:
required:
- my_files
- my_users
# modules/custom/my_custom_module/migrations/my_media_local_video.yml
id: my_media_local_video
label: Files
migration_tags:
- Custom
source:
plugin: file_entity
type: video
# See output of SELECT DISTINCT(SUBSTRING_INDEX(uri, ':', 1)) FROM file_managed WHERE type = 'video';
scheme:
- "public"
constants:
bundle: 'local_video'
process:
mid: fid
bundle: 'constants/bundle'
langcode:
plugin: default_value
source: language
default_value: "und"
name: filename
uid:
-
plugin: skip_on_empty
method: process
source: uid
-
plugin: migration
migration: my_users
status: status
# Drupal 7 didn't keep track of the file's creation or update time -- all it
# had was the vague "timestamp" column. So we'll use it for both.
created: timestamp
changed: timestamp
# File field see media_entity.bundle.local_video.yml.
field_media_video/target_id: fid
# Title field.
field_title: field_video_title
# Transcript field.
field_transcript: field_transcript
destination:
plugin: entity:media
migration_dependencies:
required:
- my_files
- my_users
# modules/custom/my_custom_module/migrations/my_media_video.yml
id: my_media_video
label: Files
migration_tags:
- Custom
source:
plugin: file_entity
type: video
# See output of SELECT DISTINCT(SUBSTRING_INDEX(uri, ':', 1)) FROM file_managed WHERE type = 'video';
scheme:
- "youtube"
constants:
bundle: 'video'
process:
mid: fid
bundle: 'constants/bundle'
langcode:
plugin: default_value
source: language
default_value: "und"
name: filename
uid:
-
plugin: skip_on_empty
method: process
source: uid
-
plugin: migration
migration: my_users
status: status
# Drupal 7 didn't keep track of the file's creation or update time -- all it
# had was the vague "timestamp" column. So we'll use it for both.
created: timestamp
changed: timestamp
# Embed field see media_entity.bundle.video.yml.
field_media_video_embed_field:
plugin: youtube
source: uri
# Title field.
field_title: field_video_title
# Transcript field.
field_transcript: field_transcript
destination:
plugin: entity:media
migration_dependencies:
required:
- my_files
- my_users
<?php
// modules/custom/my_custom_module/src/Plugin/migrate/process/SkipYoutubeVideos.php
namespace Drupal\my_custom_module\Plugin\migrate\process;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\MigrateSkipRowException;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
/**
* Skip youtube videos.
*
* @MigrateProcessPlugin(
* id = "skip_youtube_files"
* )
*/
class SkipYoutubeVideos extends ProcessPluginBase {
/**
* {@inheritdoc}
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
if (parse_url(end($value), PHP_URL_SCHEME) == 'youtube') {
throw new MigrateSkipRowException();
}
return $value;
}
}
<?php
// modules/custom/my_custom_module/src/Plugin/migrate/process/Youtube.php
namespace Drupal\my_module\Plugin\migrate\process;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
/**
* Custom process plugin to convert youtube scheme uri to video url.
*
* @MigrateProcessPlugin(
* id = "youtube"
* )
*/
class Youtube extends ProcessPluginBase {
const SCHEME = 'youtube://';
const BASE_URL = 'http://youtube.com/watch?';
/**
* {@inheritdoc}
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
// Convert youtube scheme uri to video url.
if (strpos($value, static::SCHEME) !== FALSE) {
$value = static::BASE_URL . implode('=', explode('/', str_replace(static::SCHEME, '', $value), 2));
}
else {
$value = NULL;
}
return $value;
}
}
@namita-sharma
Copy link

namita-sharma commented Dec 9, 2019

Sorry for my ignorance, I have few questions:

  1. Is this module works for moving Drupal 7 file entities to drupal 8 media entities?
  2. Do I have to copy over the drupal 7 files in drupal 8 or migration will pick up the location by itself?
  3. What commands needs to be run fater the module has been installed
    I tried drush migrate-import my_files but that didn't work

I am really new at migration, any help will be appreciated. Thanks

@captaindav
Copy link

captaindav commented May 24, 2020

Doesn't the Media Migration module (https://www.drupal.org/project/media_migration) make possible the automatic generation of this migration using the command drush migrate:upgrade?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment