class MigratePluginAlterer in Media Migration 8
Service for performing migration plugin alterations.
Hierarchy
- class \Drupal\media_migration\MigratePluginAlterer
Expanded class hierarchy of MigratePluginAlterer
1 file declares its use of MigratePluginAlterer
- MigratePluginAltererTest.php in tests/
src/ Unit/ MigratePluginAltererTest.php
1 string reference to 'MigratePluginAlterer'
1 service uses MigratePluginAlterer
File
- src/
MigratePluginAlterer.php, line 22
Namespace
Drupal\media_migrationView source
class MigratePluginAlterer {
/**
* The plugin.manager.media_wysiwyg service.
*
* @var \Drupal\media_migration\MediaWysiwygPluginManager
*/
protected $pluginManagerMediaWysiwyg;
/**
* The logger.
*
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* Constructs a MigratePluginAlterer object.
*
* @param \Drupal\media_migration\MediaWysiwygPluginManager $plugin_manager_media_wysiwyg
* The Media WYSIWYG plugin manager.
* @param \Psr\Log\LoggerInterface $logger
* The logger.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
*/
public function __construct(MediaWysiwygPluginManager $plugin_manager_media_wysiwyg, LoggerInterface $logger, ModuleHandlerInterface $module_handler) {
$this->pluginManagerMediaWysiwyg = $plugin_manager_media_wysiwyg;
$this->logger = $logger;
$this->moduleHandler = $module_handler;
}
/**
* Alters migrate plugins.
*
* @param array $migrations
* The array of migration plugins.
*
* @throws \Drupal\Component\Plugin\Exception\PluginException
* If a plugin cannot be found.
*/
public function alter(array &$migrations) {
$this
->alterFieldMigrations($migrations);
$this
->addMediaWysiwygProcessor($migrations);
$this
->alterFilterFormatMigration($migrations);
}
/**
* Alters field migrations from file_entity/media in 7 to media in 8.
*
* @param array $migrations
* The array of migration plugins.
*
* @throws \Drupal\Component\Plugin\Exception\PluginException
* If a plugin cannot be found.
*/
protected function alterFieldMigrations(array &$migrations) {
foreach ($migrations as &$migration) {
// If this is not a Drupal 7 migration, we can skip processing it.
if (!in_array('Drupal 7', $migration['migration_tags'] ?? [])) {
continue;
}
$source = NULL;
if (!empty($migration['source']['plugin'])) {
$source = MigrationPluginTool::getSourcePlugin($migration['source']);
if (is_a($migration['class'], FieldMigration::class, TRUE)) {
// Field storage, instance, widget and formatter migrations.
if (is_a($source, Field::class) || is_a($source, FieldInstance::class)) {
static::mapMigrationProcessValueToMedia($migration, 'entity_type');
}
}
// View Modes.
if (is_a($source, ViewMode::class)) {
static::mapMigrationProcessValueToMedia($migration, 'targetEntityType');
}
// D7 field instance migrations should have optional dependency on
// media types — just like it already does for node type, comment type
// and vocabulary type in core.
if ($migration['source']['plugin'] === 'd7_field_instance') {
$migration['migration_dependencies']['optional'][] = 'd7_file_entity_type';
}
}
}
}
/**
* Appends text processors to transform D7 tokens to embeds.
*
* Find field instances with text processing and pass them to a
* MediaWysiwyg plugin that will add processors to the respective
* migrations.
*
* @param array $migrations
* The array of migration plugins.
*
* @see \Drupal\media_migration\Plugin\MediaWysiwyg\Node
*/
protected function addMediaWysiwygProcessor(array &$migrations) : void {
$field_instance_migrations = array_filter($migrations, function (array $definition) {
return $definition['id'] === 'd7_field_instance';
});
if (empty($field_instance_migrations)) {
return;
}
$fields_in_content_entity_migrations_processed = [];
$source_entity_types_without_plugin = [];
foreach ($field_instance_migrations as $field_instance_migration_definition) {
$field_instance_source = MigrationPluginTool::getSourcePlugin($field_instance_migration_definition['source']);
if ($field_instance_source instanceof RequirementsInterface) {
try {
$field_instance_source
->checkRequirements();
} catch (RequirementsException $e) {
continue;
}
}
foreach ($field_instance_source as $row) {
assert($row instanceof Row);
$source_entity_type_id = $row
->getSourceProperty('entity_type');
if (!in_array($source_entity_type_id, $source_entity_types_without_plugin, TRUE) && $row
->getSourceProperty('field_definition')['module'] === 'text' && $row
->getSourceProperty('settings/text_processing') !== 0) {
$field_name = $row
->getSourceProperty('field_name');
if (!empty($fields_in_content_entity_migrations_processed[$source_entity_type_id]) && in_array($field_name, $fields_in_content_entity_migrations_processed[$source_entity_type_id], TRUE)) {
continue;
}
try {
$plugin = $this->pluginManagerMediaWysiwyg
->createInstanceFromSourceEntityType($source_entity_type_id);
$migrations = $plugin
->process($migrations, $row);
} catch (PluginException $e) {
$source_entity_types_without_plugin[] = $source_entity_type_id;
$this->logger
->warning(sprintf("Could not find a MediaWysiwyg plugin for field '%s' used in source entity type '%s'. You probably need to create a new one. Have a look at '%s' for an example.", $row
->getSourceProperty('field_name'), $source_entity_type_id, Paragraphs::class));
}
$fields_in_content_entity_migrations_processed[$source_entity_type_id][] = $field_name;
}
}
}
}
/**
* Maps Drupal 7 media_filter filter plugin to a Drupal 8|9 filter plugin.
*
* If Entity Embed module is installed on the destination site, this method
* maps the media_embed filter plugin (Drupal 7 Media WYSIWYG module) to
* entity_embed filter plugin (from the Entity Embed module).
* If Entity Embed is unavailable, the media_filter filter will be mapped to
* media_embed filter (from core Media Library module).
*
* @param array $migrations
* The array of migration plugins.
*/
protected function alterFilterFormatMigration(array &$migrations) : void {
$destination_filter_plugin_id = MediaMigration::getEmbedTokenDestinationFilterPlugin();
// If entity_embed is not installed, the destination entity type of the
// "d7_embed_button_media" migration is missing.
if (!$this->moduleHandler
->moduleExists('entity_embed')) {
unset($migrations['d7_embed_button_media']);
}
if (isset($migrations['d7_filter_format']) && MediaMigration::embedTokenDestinationFilterPluginIsValid($destination_filter_plugin_id)) {
$migrations['d7_filter_format']['process']['filters']['process']['id']['map']['media_filter'] = $destination_filter_plugin_id;
}
else {
// We don't know the transform type or the filter format migration does
// not exist.
return;
}
if (MediaMigration::MEDIA_TOKEN_DESTINATION_FILTER_ENTITY_EMBED == $destination_filter_plugin_id && isset($migrations['d7_filter_format']) && isset($migrations['d7_embed_button_media'])) {
$migrations['d7_filter_format']['migration_dependencies']['required'][] = 'd7_embed_button_media';
}
// We have to add <drupal-entity> or <drupal-media> to the allowed html
// tag's list.
if (isset($migrations['d7_filter_format'])) {
$filter_plugin_settings_processes = MigrationPluginTool::getAssociativeMigrationProcess($migrations['d7_filter_format']['process']['filters']['process']['settings']);
$filter_plugin_settings_processes[] = [
'plugin' => 'filter_settings_embed_media',
];
$migrations['d7_filter_format']['process']['filters']['process']['settings'] = $filter_plugin_settings_processes;
}
}
/**
* Maps a migration's property from "file" to "media".
*
* @param array $migration
* The migration to alter.
* @param string $property
* The property to change.
*/
public static function mapMigrationProcessValueToMedia(array &$migration, string $property) {
if (!empty($migration['source'][__FUNCTION__])) {
return;
}
try {
$value = static::getSourceValueOfMigrationProcess($migration, $property);
switch ($value) {
case 'file':
$migration['source']["media_migration_{$property}"] = 'media';
$migration['process'][$property] = "media_migration_{$property}";
break;
case NULL:
// The value of the property cannot be determined, it might be a
// dynamic value.
$entity_type_process = MigrationPluginTool::getAssociativeMigrationProcess($migration['process'][$property]);
$entity_type_process[] = [
'plugin' => 'static_map',
'map' => [
'file' => 'media',
],
'bypass' => TRUE,
];
$migration['process'][$property] = $entity_type_process;
break;
}
} catch (\LogicException $e) {
// The process property does not exists, nothing to do.
}
$migration['source'][__FUNCTION__] = TRUE;
}
/**
* Gets the value of a process property if it is not dynamically calculated.
*
* @param array $migration
* The migration plugin's definition array.
* @param string $process_property_key
* The property to check.
*
* @return mixed|null
* The value of the property if it can be determined, or NULL if it seems
* to be dynamic.
*
* @throws \LogicException.
* When the process property does not exists.
*/
public static function getSourceValueOfMigrationProcess(array $migration, string $process_property_key) {
if (!array_key_exists('process', $migration) || !is_array($migration['process']) || !array_key_exists($process_property_key, $migration['process'])) {
throw new \LogicException('No corresponding process found');
}
$property_processes = MigrationPluginTool::getAssociativeMigrationProcess($migration['process'][$process_property_key]);
$the_first_process = reset($property_processes);
$property_value = NULL;
if (!array_key_exists('source', $migration) || count($property_processes) !== 1 || $the_first_process['plugin'] !== 'get' || empty($the_first_process['source'])) {
return NULL;
}
$process_value_source = $the_first_process['source'];
// Parsing string values like "whatever" or "constants/whatever/key".
// If the property is set to an already available value (e.g. a constant),
// we don't need our special mapping applied.
$property_value = NestedArray::getValue($migration['source'], explode(Row::PROPERTY_SEPARATOR, $process_value_source), $key_exists);
// Migrations using the "embedded_data" source plugin actually contain
// rows with source values.
if (!$key_exists && $migration['source']['plugin'] === 'embedded_data') {
$embedded_rows = $migration['source']['data_rows'] ?? [];
$embedded_property_values = array_reduce($embedded_rows, function (array $carry, array $row) use ($process_value_source) {
$embedded_value = NestedArray::getValue($row, explode(Row::PROPERTY_SEPARATOR, $process_value_source));
$carry = array_unique(array_merge($carry, [
$embedded_value,
]));
return $carry;
}, []);
return count($embedded_property_values) === 1 ? $embedded_property_values[0] : NULL;
}
return $key_exists ? $property_value : NULL;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
MigratePluginAlterer:: |
protected | property | The logger. | |
MigratePluginAlterer:: |
protected | property | The module handler. | |
MigratePluginAlterer:: |
protected | property | The plugin.manager.media_wysiwyg service. | |
MigratePluginAlterer:: |
protected | function | Appends text processors to transform D7 tokens to embeds. | |
MigratePluginAlterer:: |
public | function | Alters migrate plugins. | |
MigratePluginAlterer:: |
protected | function | Alters field migrations from file_entity/media in 7 to media in 8. | |
MigratePluginAlterer:: |
protected | function | Maps Drupal 7 media_filter filter plugin to a Drupal 8|9 filter plugin. | |
MigratePluginAlterer:: |
public static | function | Gets the value of a process property if it is not dynamically calculated. | |
MigratePluginAlterer:: |
public static | function | Maps a migration's property from "file" to "media". | |
MigratePluginAlterer:: |
public | function | Constructs a MigratePluginAlterer object. |