I had the same exact problem. Tried https://www.drupal.org/project/media_migration but just couldn't seem to get it to work. So, I went old school. I figured that I could write a migration source plugin that would take this:
[[{"type":"media","view_mode":"media_large","fid":"532","field_deltas":{"1":
{}},"link_text":null,"fields":{},"attributes":{"alt":"Image of a hand","height":"238","width":"278","style":"margin: 10px; width: 278px; height: 238px;
float: right;","class":"media-image media-element file-media-large","data-delta":"1"}}]]
And convert it to a ckeditor compatible D9 image link.
In my migration module, I created two functions:
<?php
/**
* Get the inline image link info for this fid
*
* Requires: fid
*
* Returns an array with the FileName, UUID and RealPath for the fid image
*
* Array containing uuid, filename and realpath to file
*
* Array
* (
* [uuid] => 2a8c2c69-7cc9-43cd-9d79-3ee22e59c0a7
* [filename] => node label - hidden.jpg
* [path] => /var/www/html/websites/drupal9/master1and1/private/master1and1/node label - hidden.jpg
* )
*
*/
function sbn_migrations_get_image_link_info($fid) {
$link_info = [];
$database = \Drupal\Core\Database\Database::getConnection('default', 'default');
$query = $database->select('file_managed', 'fm');
$query->condition('fm.fid', $fid, '='); // Find this fid
$query->fields('fm', ['uri']);
$query->fields('fm', ['uuid']);
$query->fields('fm', ['filename']);
$result = $query->execute();
foreach ($result as $record) {
$link_info['uuid'] = $record->uuid;
$link_info['filename'] = $record->filename;
$uri = $record->uri;
$link_info['path'] = \Drupal::service('file_system')->realpath($uri);
$link_info['path'] = str_replace(' ', '%20', $link_info['path']);
}
return $link_info;
}
/**
* Insert the correctly formatted D9 link into text body
*
* Requires: body text field
*
* Returns updated body text field with correct links (if necessary)
*
*
*/
function sbn_migrations_insert_link_into_body($body) {
$body;
$array = [];
$pattern = '/\[\[[^\]]+\"fid\"\:\"([0-9]+)\"\,[^\]]+\]\]/i';
preg_match_all($pattern, $body, $array); // search for the d7 code
// dpm($array); // Test
if (empty($array)) return $body; // if no code is found, return the $body
// If code is found, we continue on.
foreach ($array[1] as $key => $fid) {
$link_info = sbn_migrations_get_image_link_info($fid); // get the link information for this $fid
// Only continue processing if something is returned
if (!empty($link_info) && !is_null($link_info)) {
// Create the link
$link = '<img alt="'.$link_info['filename'].'" data-entity-type="file" data-entity-uuid="'.$link_info['uuid'].'" src="'.$link_info['path'].'" />';
$pattern01 = '/(\[\[)[^\]]+\"fid\"\:\"('.$fid.')\"\,[^\]]+(\]\])/i'; // this is the pattern for replacing links in the body text
$replacement = $link; // this will be the the new $link replacing the old code.
$body = preg_replace($pattern01, $replacement, $body); // this is the new body text
\Drupal::messenger()->addStatus('(info) insert link into body processing fid value '.$fid.' | '.$link_info['filename']);
}
}
return $body;
}
?>
Then, in the prepareRow() section of my source plugin, I added this:
<?php
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
// Check the $body_value for inline image links
$body_value = $row->getSourceProperty('body_value');
$body_value = sbn_migrations_insert_link_into_body($body_value); // Check body for image links
$row->setSourceProperty('body_value', $body_value);
return parent::prepareRow($row);
}
?>
Essentially, I am scanning the body text of my source input and replacing the D7 ckeditor image links with D9 formatted links. I use php regex functions preg_replace() and preg_match_all() to find the old code and replace it with new.
This works because the files referenced in the D7 links are migrated by the Drupal d7_file migration and they are in the correct public/private locations. I use \Drupal::service('file_system')->realpath($uri)
, create the new D9 (standard html) link, and I'm in business.
Just sharing an alternate method for getting this done.