View source
<?php
namespace Drupal\media_migration\Plugin\migrate\process;
use Drupal\Component\Plugin\ConfigurableInterface;
use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Template\Attribute;
use Drupal\file\Entity\File;
use Drupal\media_migration\MediaMigration;
use Drupal\media_migration\MediaMigrationUuidOracleInterface;
use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\Plugin\MigrationPluginManagerInterface;
use Drupal\migrate\Row;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Serializer\Encoder\JsonDecode;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Exception\NotEncodableValueException;
class MediaWysiwygFilter extends EmbedFilterBase implements ConfigurableInterface {
protected $migrationPluginManager;
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;
}
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'));
}
public function defaultConfiguration() {
return [
'view_mode_matching' => [],
'media_migrations' => [],
'file_migrations' => [],
];
}
public function getConfiguration() {
return $this->configuration;
}
public function setConfiguration(array $configuration) {
$this->configuration = NestedArray::mergeDeep($this
->defaultConfiguration(), $configuration);
}
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) {
$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];
}
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'] : [];
foreach ([
'alt',
'title',
] as $attribute_name) {
if (!empty($source_attributes[$attribute_name])) {
$embed_metadata[$attribute_name] = $source_attributes[$attribute_name];
}
}
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) {
$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);
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;
}
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;
}
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';
$attributes = $filter_destination_is_entity_embed ? [
'data-embed-button' => 'media',
] : [];
$attributes['data-entity-type'] = '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']);
$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);
$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}>";
}
}