diff --git a/core/modules/media/src/Plugin/media/Source/OEmbed.php b/core/modules/media/src/Plugin/media/Source/OEmbed.php index 0a21e925f60..fd6bcf11a51 100644 --- a/core/modules/media/src/Plugin/media/Source/OEmbed.php +++ b/core/modules/media/src/Plugin/media/Source/OEmbed.php @@ -2,6 +2,7 @@ namespace Drupal\media\Plugin\media\Source; +use Drupal\Component\Render\PlainTextOutput; use Drupal\Component\Utility\Crypt; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Entity\Display\EntityFormDisplayInterface; @@ -14,6 +15,7 @@ use Drupal\Core\File\FileSystemInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Messenger\MessengerInterface; use Drupal\Core\Url; +use Drupal\Core\Utility\Token; use Drupal\media\IFrameUrlHelper; use Drupal\media\OEmbed\Resource; use Drupal\media\OEmbed\ResourceException; @@ -126,6 +128,13 @@ class OEmbed extends MediaSourceBase implements OEmbedInterface { */ protected $fileSystem; + /** + * The token replacement service. + * + * @var \Drupal\Core\Utility\Token + */ + protected $token; + /** * Constructs a new OEmbed instance. * @@ -157,8 +166,10 @@ class OEmbed extends MediaSourceBase implements OEmbedInterface { * The iFrame URL helper service. * @param \Drupal\Core\File\FileSystemInterface $file_system * The file system. + * @param \Drupal\Core\Utility\Token $token + * The token replacement service. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, ConfigFactoryInterface $config_factory, FieldTypePluginManagerInterface $field_type_manager, LoggerInterface $logger, MessengerInterface $messenger, ClientInterface $http_client, ResourceFetcherInterface $resource_fetcher, UrlResolverInterface $url_resolver, IFrameUrlHelper $iframe_url_helper, FileSystemInterface $file_system) { + public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, ConfigFactoryInterface $config_factory, FieldTypePluginManagerInterface $field_type_manager, LoggerInterface $logger, MessengerInterface $messenger, ClientInterface $http_client, ResourceFetcherInterface $resource_fetcher, UrlResolverInterface $url_resolver, IFrameUrlHelper $iframe_url_helper, FileSystemInterface $file_system, Token $token = NULL) { parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $entity_field_manager, $field_type_manager, $config_factory); $this->logger = $logger; $this->messenger = $messenger; @@ -167,6 +178,11 @@ class OEmbed extends MediaSourceBase implements OEmbedInterface { $this->urlResolver = $url_resolver; $this->iFrameUrlHelper = $iframe_url_helper; $this->fileSystem = $file_system; + if (empty($token)) { + @trigger_error('The token service should be passed to ' . __METHOD__ . '() and is required in drupal:10.0.0. See https://www.drupal.org/node/3240036', E_USER_DEPRECATED); + $token = \Drupal::token(); + } + $this->token = $token; } /** @@ -187,7 +203,8 @@ class OEmbed extends MediaSourceBase implements OEmbedInterface { $container->get('media.oembed.resource_fetcher'), $container->get('media.oembed.url_resolver'), $container->get('media.oembed.iframe_url_helper'), - $container->get('file_system') + $container->get('file_system'), + $container->get('token') ); } @@ -362,7 +379,7 @@ class OEmbed extends MediaSourceBase implements OEmbedInterface { */ public function defaultConfiguration() { return [ - 'thumbnails_directory' => 'public://oembed_thumbnails', + 'thumbnails_directory' => 'public://oembed_thumbnails/[date:custom:Y-m]', 'providers' => [], ] + parent::defaultConfiguration(); } @@ -392,10 +409,13 @@ class OEmbed extends MediaSourceBase implements OEmbedInterface { return NULL; } - // Ensure that we can write to the local directory where thumbnails are - // stored. + // Use the configured directory to store thumbnails. The directory can + // contain basic (i.e., global) tokens. If any of the replaced tokens + // contain HTML, the tags will be removed and XML entities will be decoded. $configuration = $this->getConfiguration(); $directory = $configuration['thumbnails_directory']; + $directory = $this->token->replace($directory); + $directory = PlainTextOutput::renderFromHtml($directory); // The local thumbnail doesn't exist yet, so try to download it. First, // ensure that the destination directory is writable, and if it's not, diff --git a/core/modules/media/tests/src/Kernel/OEmbedSourceTest.php b/core/modules/media/tests/src/Kernel/OEmbedSourceTest.php index 02b481d9e3a..be3b092508f 100644 --- a/core/modules/media/tests/src/Kernel/OEmbedSourceTest.php +++ b/core/modules/media/tests/src/Kernel/OEmbedSourceTest.php @@ -135,19 +135,36 @@ class OEmbedSourceTest extends MediaKernelTestBase { $media_type = $this->createMediaType('oembed:video'); $source = $media_type->getSource(); + // Add some HTML to the global site slogan, and use the site:slogan token in + // the thumbnail path, in order to prove that the final thumbnail path is + // stripped of HTML tags, and XML entities are decoded. + $this->config('system.site') + ->set('slogan', '