class MediaWysiwygFilter in Media Migration 8
Processes [[{"type":"media","fid":"1234",...}]] tokens in content.
These style tokens come from media_wysiwyg module. The regex it uses to match them for reference is:
/\[\[.+?"type":"media".+?\]\]/s
# From this
[[{"type":"media","fid":"1234",...}]]
# To this
<drupal-entity
data-embed-button="media"
data-entity-embed-display="view_mode:media.full"
data-entity-type="media"
data-entity-id="1234"></drupal-entity>
# or to this:
<drupal-media
data-entity-type="media"
data-view-mode="full"
data-entity-uuid="12345678-9abc-def0-1234-56789abcdef0"></drupal-media>
Usage:
@endcode process: bar: plugin: media_wysiwyg_filter view_mode_matching: default: full media_migrations:
- upgrade_d7_file_entity_archive
- upgrade_d7_file_entity_image
- upgrade_d7_file_entity_publication
file_migrations:
- upgrade_d7_file
@endcode
Plugin annotation
@MigrateProcessPlugin(
id = "media_wysiwyg_filter"
)
Hierarchy
- class \Drupal\Component\Plugin\PluginBase implements DerivativeInspectionInterface, PluginInspectionInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
- class \Drupal\migrate\ProcessPluginBase implements MigrateProcessInterface
- class \Drupal\media_migration\Plugin\migrate\process\EmbedFilterBase implements ContainerFactoryPluginInterface
- class \Drupal\media_migration\Plugin\migrate\process\MediaWysiwygFilter implements ConfigurableInterface
- class \Drupal\media_migration\Plugin\migrate\process\EmbedFilterBase implements ContainerFactoryPluginInterface
- class \Drupal\migrate\ProcessPluginBase implements MigrateProcessInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
Expanded class hierarchy of MediaWysiwygFilter
1 file declares its use of MediaWysiwygFilter
- MediaWysiwygFilterTest.php in tests/
src/ Unit/ Plugin/ migrate/ process/ MediaWysiwygFilterTest.php
File
- src/
Plugin/ migrate/ process/ MediaWysiwygFilter.php, line 67
Namespace
Drupal\media_migration\Plugin\migrate\processView source
class MediaWysiwygFilter extends EmbedFilterBase implements ConfigurableInterface {
/**
* The migration plugin manager.
*
* @var \Drupal\migrate\Plugin\MigrationPluginManagerInterface
*/
protected $migrationPluginManager;
/**
* Constructs a new MediaWysiwygFilter instance.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
* The migration entity.
* @param \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayManager|null $entity_embed_display_manager
* The entity embed display plugin manager service, if available.
* @param \Drupal\migrate\Plugin\MigrationPluginManagerInterface $migration_plugin_manager
* The migration plugin manager.
* @param \Drupal\media_migration\MediaMigrationUuidOracleInterface $media_uuid_oracle
* The media UUID oracle.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, $entity_embed_display_manager, MigrationPluginManagerInterface $migration_plugin_manager, MediaMigrationUuidOracleInterface $media_uuid_oracle) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $media_uuid_oracle, $entity_embed_display_manager);
$this
->setConfiguration($configuration);
$this->migrationPluginManager = $migration_plugin_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
return new static($configuration, $plugin_id, $plugin_definition, $migration, $container
->get('plugin.manager.entity_embed.display', ContainerInterface::NULL_ON_INVALID_REFERENCE), $container
->get('plugin.manager.migration'), $container
->get('media_migration.media_uuid_oracle'));
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [
'view_mode_matching' => [],
'media_migrations' => [],
'file_migrations' => [],
];
}
/**
* {@inheritdoc}
*/
public function getConfiguration() {
return $this->configuration;
}
/**
* {@inheritdoc}
*/
public function setConfiguration(array $configuration) {
// Merge in defaults.
$this->configuration = NestedArray::mergeDeep($this
->defaultConfiguration(), $configuration);
}
/**
* {@inheritdoc}
*/
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
if (!MediaMigration::embedTokenDestinationFilterPluginIsValid(MediaMigration::getEmbedTokenDestinationFilterPlugin())) {
throw new MigrateException("The embed token's destination filter plugin ID is invalid.");
}
$pattern = '/\\[\\[\\s*(?<tag_info>\\{.+\\})\\s*\\]\\]/sU';
if (defined(JsonDecode::class . '::ASSOCIATIVE')) {
$decoder = new JsonDecode([
JsonDecode::ASSOCIATIVE => TRUE,
]);
}
else {
$decoder = new JsonDecode(TRUE);
}
$entity_type_id = explode(':', $this->migration
->getDestinationConfiguration()['plugin'])[1];
$source_identifier = [];
foreach ($row
->getSourceIdValues() as $source_id_key => $source_id_value) {
$source_identifier[] = "{$source_id_key} {$source_id_value}";
}
$source_identifier = implode(', ', $source_identifier);
$value_is_array = is_array($value);
$text = (string) ($value_is_array ? $value['value'] : $value);
$text = preg_replace_callback($pattern, function ($matches) use ($decoder, $entity_type_id, $source_identifier) {
// Replace line breaks with a single space for valid JSON.
$matches['tag_info'] = preg_replace('/\\s+/', ' ', $matches['tag_info']);
try {
$tag_info = $decoder
->decode($matches['tag_info'], JsonEncoder::FORMAT);
if (!is_array($tag_info) || !array_key_exists('fid', $tag_info)) {
return $matches[0];
}
// Find matching view mode.
if ($this->configuration['view_mode_matching']) {
foreach ($this->configuration['view_mode_matching'] as $key => $match) {
if ($key == $tag_info['view_mode'] ?? NULL) {
$tag_info['view_mode'] = $match;
}
}
}
$embed_metadata = [
'id' => $tag_info['fid'],
'view_mode' => $tag_info['view_mode'] ?? 'default',
];
$source_attributes = !empty($tag_info['attributes']) ? $tag_info['attributes'] : [];
// Add alt and title overrides.
foreach ([
'alt',
'title',
] as $attribute_name) {
if (!empty($source_attributes[$attribute_name])) {
$embed_metadata[$attribute_name] = $source_attributes[$attribute_name];
}
}
// Add alignment.
if (!empty($source_attributes['class']) && is_string($source_attributes['class'])) {
$alignment_map = [
'media-wysiwyg-align-center' => 'center',
'media-wysiwyg-align-left' => 'left',
'media-wysiwyg-align-right' => 'right',
];
$classes_array = array_unique(explode(' ', preg_replace('/\\s{2,}/', ' ', trim($source_attributes['class']))));
foreach ($alignment_map as $original => $replacement) {
if (in_array($original, $classes_array, TRUE)) {
$embed_metadata['data-align'] = $replacement;
break;
}
}
}
return $this
->getEmbedCode($embed_metadata) ?? $matches[0];
} catch (NotEncodableValueException $e) {
// There was an error decoding the JSON.
$this
->messenger()
->addWarning(sprintf('The following media_wysiwyg token in %s %s does not have valid JSON: %s', $entity_type_id, $source_identifier, $matches[0]));
return $matches[0];
} catch (\LogicException $e) {
return $matches[0];
}
}, $text);
// Update fid and token in regex /file/{fid}/download?token={token}.
if ($this->configuration['file_migrations']) {
$pattern = '#\\/file\\/([0-9]*)\\/download\\?token=([a-zA-Z0-9]*)#';
$replacement_template = '/file/%s/download?token=%s';
$text = preg_replace_callback($pattern, function ($matches) use ($replacement_template) {
$oldId = $matches[1];
$newId = $this
->findDestId($oldId, $this->configuration['file_migrations']);
$newToken = '';
try {
$reflector = new \ReflectionClass('Drupal\\file_entity\\Entity\\FileEntity');
if ($reflector
->hasMethod('getDownloadToken') && ($file = File::load($newId))) {
$newToken = $file
->getDownloadToken();
}
} catch (\ReflectionException $e) {
}
return sprintf($replacement_template, $newId, $newToken);
}, $text);
}
if ($value_is_array) {
$value['value'] = $text;
}
else {
$value = $text;
}
return $value;
}
/**
* Find new ID using the migration lookup system.
*
* @param int $source_id
* The original ID.
* @param array $migrations
* The ID of the migrations to look at.
*
* @return int
* The new ID.
*/
protected function findDestId($source_id, array $migrations) {
try {
$lookup_migrations = $this->migrationPluginManager
->createInstances($migrations);
} catch (PluginException $exception) {
return $source_id;
}
foreach ($lookup_migrations as $lookup_migration_id => $lookup_migration) {
$source_id_values[$lookup_migration_id] = [
$source_id,
];
try {
$destination_ids = $lookup_migration
->getIdMap()
->lookupDestinationIds($source_id_values[$lookup_migration_id]);
} catch (MigrateException $exception) {
continue;
}
if (!empty($destination_ids)) {
return reset($destination_ids)[0];
}
}
return $source_id;
}
/**
* Creates the replacement token for the specified embed filter.
*/
protected function getEmbedCode(array $embed_metadata) {
if (empty($embed_metadata['id']) || empty($embed_metadata['view_mode'])) {
return NULL;
}
$destination_filter_plugin_id = MediaMigration::getEmbedTokenDestinationFilterPlugin();
$embed_media_reference_method = MediaMigration::getEmbedMediaReferenceMethod();
$filter_destination_is_entity_embed = $destination_filter_plugin_id === MediaMigration::MEDIA_TOKEN_DESTINATION_FILTER_ENTITY_EMBED;
$reference_method_is_id = $embed_media_reference_method === MediaMigration::EMBED_MEDIA_REFERENCE_METHOD_ID;
$tag = $filter_destination_is_entity_embed ? 'drupal-entity' : 'drupal-media';
// Add the static attributes first.
$attributes = $filter_destination_is_entity_embed ? [
'data-embed-button' => 'media',
] : [];
$attributes['data-entity-type'] = 'media';
// Add the attribute that references the embed media.
$reference_attribute = $reference_method_is_id ? 'data-entity-id' : 'data-entity-uuid';
if ($reference_method_is_id && $this->configuration['media_migrations']) {
$embed_metadata['id'] = $this
->findDestId($embed_metadata['id'], $this->configuration['media_migrations']);
}
$attributes[$reference_attribute] = $reference_method_is_id ? $embed_metadata['id'] : $this->mediaUuidOracle
->getMediaUuid((int) $embed_metadata['id']);
// Add attribute that controls how the embed media is displayed.
$display_mode_property = $destination_filter_plugin_id === MediaMigration::MEDIA_TOKEN_DESTINATION_FILTER_ENTITY_EMBED ? 'data-entity-embed-display' : 'data-view-mode';
$attributes[$display_mode_property] = $this
->getDisplayPluginId($embed_metadata['view_mode'], $destination_filter_plugin_id);
// Alt, title, caption and align should be handled conditionally.
$conditional_attributes = [
'alt',
'title',
'data-caption',
'data-align',
];
foreach ($conditional_attributes as $conditional_attribute) {
if (!empty($embed_metadata[$conditional_attribute])) {
$attributes[$conditional_attribute] = $embed_metadata[$conditional_attribute];
}
}
$attribute = new Attribute($attributes);
return "<{$tag}{$attribute->__toString()}></{$tag}>";
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
EmbedFilterBase:: |
protected | property | The entity embed display plugin manager service, if available. | |
EmbedFilterBase:: |
protected | property | The media UUID oracle. | |
EmbedFilterBase:: |
protected | property | The actual migration plugin instance. | |
EmbedFilterBase:: |
protected | function | Returns the destination display plugin ID. | |
MediaWysiwygFilter:: |
protected | property | The migration plugin manager. | |
MediaWysiwygFilter:: |
public static | function |
Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface:: |
|
MediaWysiwygFilter:: |
public | function |
Gets default configuration for this plugin. Overrides ConfigurableInterface:: |
|
MediaWysiwygFilter:: |
protected | function | Find new ID using the migration lookup system. | |
MediaWysiwygFilter:: |
public | function |
Gets this plugin's configuration. Overrides ConfigurableInterface:: |
|
MediaWysiwygFilter:: |
protected | function | Creates the replacement token for the specified embed filter. | |
MediaWysiwygFilter:: |
public | function |
Sets the configuration for this plugin instance. Overrides ConfigurableInterface:: |
|
MediaWysiwygFilter:: |
public | function |
Performs the associated process. Overrides ProcessPluginBase:: |
|
MediaWysiwygFilter:: |
public | function |
Constructs a new MediaWysiwygFilter instance. Overrides EmbedFilterBase:: |
|
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
PluginBase:: |
protected | property | Configuration information passed into the plugin. | 1 |
PluginBase:: |
protected | property | The plugin implementation definition. | 1 |
PluginBase:: |
protected | property | The plugin_id. | |
PluginBase:: |
constant | A string which is used to separate base plugin IDs from the derivative ID. | ||
PluginBase:: |
public | function |
Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the definition of the plugin implementation. Overrides PluginInspectionInterface:: |
3 |
PluginBase:: |
public | function |
Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface:: |
|
PluginBase:: |
public | function | Determines if the plugin is configurable. | |
ProcessPluginBase:: |
public | function |
Indicates whether the returned value requires multiple handling. Overrides MigrateProcessInterface:: |
3 |
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. |