diff --git a/core/modules/media/media.module b/core/modules/media/media.module index 91bcebd305..d0d357ccf1 100644 --- a/core/modules/media/media.module +++ b/core/modules/media/media.module @@ -96,7 +96,7 @@ function media_theme_suggestions_media(array $variables) { $suggestions[] = 'media__' . $media->bundle(); $suggestions[] = 'media__' . $media->bundle() . '__' . $sanitized_view_mode; - if ($media->getSource() instanceof OEmbed) { + if ($media->getSource() instanceof OEmbedInterface) { $provider_id = $media->getSource()->getMetadata($media, 'provider_id'); $suggestions[] = 'media__oembed'; $suggestions[] = 'media__oembed__' . strtolower($provider_id); @@ -111,12 +111,11 @@ function media_theme_suggestions_media(array $variables) { function media_field_widget_string_textfield_form_alter(array &$element, FormStateInterface $form_state, array $context) { /** @var \Drupal\media\MediaInterface|OEmbedInterface $media */ $media = $context['items']->getEntity(); - /** @var \Drupal\media\Plugin\media\Source\OEmbedInterface $source */ - $source = $media->getSource(); - if (empty($element['value']) || !($media instanceof MediaInterface) || !($source instanceof OEmbedInterface)) { + if (empty($element['value']) || !($media instanceof MediaInterface) || !($media->getSource() instanceof OEmbedInterface)) { return; } - + /** @var \Drupal\media\Plugin\media\Source\OEmbedInterface $source */ + $source = $media->getSource(); $field_definition = $context['items']->getFieldDefinition(); // Only change the value field description on the source field. if ($source->getSourceFieldDefinition($media->bundle->entity)->getName() != $field_definition->getName()) { @@ -124,18 +123,10 @@ function media_field_widget_string_textfield_form_alter(array &$element, FormSta } $message = t('You can link to media from the following services: @providers', ['@providers' => implode(', ', $source->getAllowedProviders())]); - if (!empty($element['value']['#description'])) { - $element['value']['#description'] = [ - '#theme' => 'item_list', - '#items' => [$element['value']['#description'], $message], - ]; - } - else { - $element['value']['#description'] = [ - '#theme' => 'item_list', - '#items' => [$message], - ]; - } + $element['value']['#description'] = [ + '#theme' => 'item_list', + '#items' => !empty($element['value']['#description']) ? [$element['value']['#description'], $message] : [$message], + ]; } /** diff --git a/core/modules/media/media.services.yml b/core/modules/media/media.services.yml index a94a2fedca..57643b1a4f 100644 --- a/core/modules/media/media.services.yml +++ b/core/modules/media/media.services.yml @@ -7,9 +7,12 @@ services: arguments: ['@entity_type.manager'] tags: - { name: access_check, applies_to: _access_media_revision } - media.oembed.provider_discovery: - class: Drupal\media\OEmbed\ProviderDiscovery + media.oembed.oembed_manager: + class: Drupal\media\OEmbed\OEmbedManager + arguments: ['@media.oembed.provider_collector', '@media.oembed.resource_fetcher', '@http_client', '@module_handler', '@cache.default'] + media.oembed.provider_collector: + class: Drupal\media\OEmbed\ProviderCollector arguments: ['@http_client', 'https://oembed.com/providers.json', '@datetime.time', '@cache.default'] media.oembed.resource_fetcher: class: Drupal\media\OEmbed\ResourceFetcher - arguments: ['@media.oembed.provider_discovery', '@http_client', '@module_handler', '@cache.default'] + arguments: ['@http_client', '@cache.default'] diff --git a/core/modules/media/src/OEmbed/Endpoint.php b/core/modules/media/src/OEmbed/Endpoint.php index 4b9dc768f8..3866a936c1 100644 --- a/core/modules/media/src/OEmbed/Endpoint.php +++ b/core/modules/media/src/OEmbed/Endpoint.php @@ -82,7 +82,8 @@ public function __construct($url, Provider $provider, array $schemes = [], array */ public function getUrl() { $format = 'json'; - if (!empty($this->formats) && is_array($this->formats)) { + if (!empty($this->formats)) { + // If the endpoint specifies multiple formats we use the fist one. $format = reset($this->getFormats()); } return str_replace('{format}', $format, $this->url); @@ -122,7 +123,7 @@ public function getFormats() { * Returns whether the provider supports oEmbed discovery. * * @return bool - * TRUE or FALSE. + * Returns TRUE if the provides discovery, otherwise FALSE. */ public function supportsDiscovery() { return $this->supportsDiscovery; diff --git a/core/modules/media/src/OEmbed/ResourceFetcher.php b/core/modules/media/src/OEmbed/OEmbedManager.php similarity index 67% copy from core/modules/media/src/OEmbed/ResourceFetcher.php copy to core/modules/media/src/OEmbed/OEmbedManager.php index c119ce0948..7f0bcccbf9 100644 --- a/core/modules/media/src/OEmbed/ResourceFetcher.php +++ b/core/modules/media/src/OEmbed/OEmbedManager.php @@ -2,7 +2,6 @@ namespace Drupal\media\OEmbed; -use Drupal\Component\Serialization\Json; use Drupal\Component\Utility\Html; use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Cache\CacheBackendInterface; @@ -13,25 +12,32 @@ use GuzzleHttp\Exception\RequestException; /** - * Fetches and caches oEmbed resources. + * Class OEmbedManager. */ -class ResourceFetcher implements ResourceFetcherInterface { +class OEmbedManager implements OEmbedManagerInterface { use UseCacheBackendTrait; /** - * The OEmbed provider discovery service. + * The HTTP client. * - * @var \Drupal\media\OEmbed\ProviderDiscoveryInterface + * @var \GuzzleHttp\Client */ - protected $providerDiscovery; + protected $httpClient; /** - * The HTTP client. + * The OEmbed provider collector service. * - * @var \GuzzleHttp\Client + * @var \Drupal\media\OEmbed\ProviderCollectorInterface */ - protected $httpClient; + protected $providerCollector; + + /** + * The OEmbed resource fetcher service. + * + * @var \Drupal\media\OEmbed\ResourceFetcherInterface + */ + protected $resourceFetcher; /** * The module handler service. @@ -51,10 +57,12 @@ class ResourceFetcher implements ResourceFetcherInterface { protected $urlCache; /** - * Constructs OEmbed class. + * Constructs OEmbedManager class. * - * @param \Drupal\media\OEmbed\ProviderDiscoveryInterface $provider_discovery - * The OEmbed provider discovery service. + * @param \Drupal\media\OEmbed\ProviderCollectorInterface $provider_collector + * The OEmbed provider collector service. + * @param \Drupal\media\OEmbed\ResourceFetcherInterface $resource_fetcher + * The OEmbed resource fetcher service. * @param \GuzzleHttp\Client $http_client * The HTTP client. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler @@ -62,65 +70,15 @@ class ResourceFetcher implements ResourceFetcherInterface { * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * (optional) The cache backend. */ - public function __construct(ProviderDiscoveryInterface $provider_discovery, Client $http_client, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend = NULL) { - $this->providerDiscovery = $provider_discovery; + public function __construct(ProviderCollectorInterface $provider_collector, ResourceFetcherInterface $resource_fetcher, Client $http_client, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend = NULL) { + $this->providerCollector = $provider_collector; + $this->resourceFetcher = $resource_fetcher; $this->httpClient = $http_client; $this->moduleHandler = $module_handler; $this->cacheBackend = $cache_backend; $this->useCaches = isset($cache_backend); } - /** - * {@inheritdoc} - */ - public function getResourceUrl($url, $max_width = NULL, $max_height = NULL) { - $cache_id = 'media:oembed_resource_url:' . hash('sha256', $url); - - if ($this->urlCache === NULL) { - $this->urlCache = []; - if ($cached = $this->cacheGet($cache_id)) { - $this->urlCache[$url] = $cached->data; - } - } - - if ($url instanceof Url) { - $url = $url->toString(); - } - - if (isset($this->urlCache[$url])) { - return $this->urlCache[$url]; - } - - $provider = $this->providerDiscovery->getProviderByUrl($url); - if ($provider) { - $resource_url = $provider->buildResourceUrl($url); - } - else { - $resource_url = $this->discoverResourceUrl($url); - } - - if (empty($resource_url)) { - throw new ResourceException('Could not determine the oEmbed resource URL.', $url); - } - - $parsed_url = UrlHelper::parse($resource_url); - if ($max_width) { - $parsed_url['query']['max_width'] = $max_width; - } - if ($max_height) { - $parsed_url['query']['max_height'] = $max_height; - } - // Let other modules alter the query string, because some oEmbed providers - // are providing extra parameters. For example, Instagram also supports the - // 'omitscript' parameter. - $this->moduleHandler->alter('oembed_resource_url', $parsed_url); - $resource_url = $parsed_url['path'] . '?' . UrlHelper::buildQuery($parsed_url['query']); - - $this->urlCache[$url] = $resource_url; - $this->cacheSet($cache_id, $resource_url); - return $resource_url; - } - /** * Runs oEmbed discovery and returns the endpoint URL if successful. * @@ -165,43 +123,80 @@ protected function findUrl(\DOMXPath $xpath, $format) { /** * {@inheritdoc} */ - public function fetchResource($url) { + public function getProviderByUrl($url) { if ($url instanceof Url) { $url = $url->toString(); } - $cache_id = 'media:oembed:' . hash('sha256', $url); + // Check the URL against every scheme of every endpoint of every provider + // until we find a match. + foreach ($this->providerCollector->getAll() as $provider_name => $provider_info) { + if (empty($provider_info->getEndpoints())) { + continue; + } + foreach ($provider_info->getEndpoints() as $endpoint) { + if (empty($endpoint->getSchemes())) { + continue; + } + if ($endpoint->matchUrl($url)) { + return $provider_info; + } + } + } - $cached = $this->cacheGet($cache_id); - if ($cached) { - return $cached->data; + if ($resource_url = $this->discoverResourceUrl($url)) { + $resource = $this->resourceFetcher->fetchResource($resource_url); + return $this->providerCollector->get($resource['provider_name']); } + throw new ResourceException('No matching provider found.', $url); + } - try { - $response = $this->httpClient->get($url); + /** + * {@inheritdoc} + */ + public function getResourceUrl($url, $max_width = NULL, $max_height = NULL) { + $cache_id = 'media:oembed_resource_url:' . hash('sha256', $url); + + if ($this->urlCache === NULL) { + $this->urlCache = []; + if ($cached = $this->cacheGet($cache_id)) { + $this->urlCache[$url] = $cached->data; + } } - catch (RequestException $e) { - throw new ResourceException('Could not retrieve the oEmbed resource.', $url, [], $e); + + if ($url instanceof Url) { + $url = $url->toString(); } - $format = $response->getHeader('Content-Type'); - $content = (string) $response->getBody(); + if (isset($this->urlCache[$url])) { + return $this->urlCache[$url]; + } - // If the response is XML, magically convert it to JSON. - if (strpos($format[0], 'text/xml') !== FALSE) { - // Load XML into SimpleXMLElement. - $content = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA); - // Convert the SimpleXMLElement to JSON. - $content = Json::encode($content); + $provider = $this->getProviderByUrl($url); + if ($provider) { + $resource_url = $provider->buildResourceUrl($url); } - // If the response wasn't XML or JSON, we are in bat country. - elseif (strpos($format[0], 'application/json') === FALSE && strpos($format[0], 'text/javascript') === FALSE) { - throw new ResourceException('The fetched resource did not have a valid Content-Type header.', $url); + + if (empty($resource_url)) { + throw new ResourceException('Could not determine the oEmbed resource URL.', $url); } - $resource = Json::decode($content); - $this->cacheSet($cache_id, $resource); - return $resource; + $parsed_url = UrlHelper::parse($resource_url); + if ($max_width) { + $parsed_url['query']['max_width'] = $max_width; + } + if ($max_height) { + $parsed_url['query']['max_height'] = $max_height; + } + // Let other modules alter the query string, because some oEmbed providers + // are providing extra parameters. For example, Instagram also supports the + // 'omitscript' parameter. + $this->moduleHandler->alter('oembed_resource_url', $parsed_url); + $resource_url = $parsed_url['path'] . '?' . UrlHelper::buildQuery($parsed_url['query']); + + $this->urlCache[$url] = $resource_url; + $this->cacheSet($cache_id, $resource_url); + return $resource_url; } } diff --git a/core/modules/media/src/OEmbed/ResourceFetcherInterface.php b/core/modules/media/src/OEmbed/OEmbedManagerInterface.php similarity index 62% copy from core/modules/media/src/OEmbed/ResourceFetcherInterface.php copy to core/modules/media/src/OEmbed/OEmbedManagerInterface.php index 16c908ae79..5681af9f7c 100644 --- a/core/modules/media/src/OEmbed/ResourceFetcherInterface.php +++ b/core/modules/media/src/OEmbed/OEmbedManagerInterface.php @@ -3,9 +3,24 @@ namespace Drupal\media\OEmbed; /** - * Interface for oEmbed service. + * Interface for OEmbedManager service. */ -interface ResourceFetcherInterface { +interface OEmbedManagerInterface { + + /** + * Tries to get provider info from the provider list. + * + * @param string $url + * The URL of a media object to match against the oEmbed providers. + * + * @return \Drupal\media\OEmbed\Provider + * Returns a single provider if found, otherwise FALSE. + * + * @see \Drupal\media\ProviderCollectorInterface::get() + * + * @throws \Drupal\media\OEmbed\ResourceException + */ + public function getProviderByUrl($url); /** * Tries to match the URL against the database of oEmbed providers. @@ -26,18 +41,4 @@ */ public function getResourceUrl($url, $max_width = NULL, $max_height = NULL); - /** - * Fetches information about the oEmbed resource. - * - * @param string $endpoint_url - * Resource-specific URL of the oEmbed endpoint. - * - * @return array - * Resource information as returned from the oEmbed endpoint, or FALSE if - * the resource could not be fetched. - * - * @throws \Drupal\media\OEmbed\ResourceException - */ - public function fetchResource($endpoint_url); - } diff --git a/core/modules/media/src/OEmbed/Provider.php b/core/modules/media/src/OEmbed/Provider.php index 7317eb3984..2ca3e8acae 100644 --- a/core/modules/media/src/OEmbed/Provider.php +++ b/core/modules/media/src/OEmbed/Provider.php @@ -48,10 +48,8 @@ public function __construct($name, $url, array $endpoints) { } foreach ($endpoints as $endpoint) { - $formats = !empty($endpoint['formats']) ? $endpoint['formats'] : []; - $schemes = !empty($endpoint['schemes']) ? $endpoint['schemes'] : []; - $discovery = !empty($endpoint['discovery']) ? $endpoint['discovery'] : []; - $this->endpoints[] = new Endpoint($endpoint['url'], $this, $schemes, $formats, $discovery); + $endpoint += ['formats' => [], 'schemes' => [], 'discovery' => FALSE]; + $this->endpoints[] = new Endpoint($endpoint['url'], $this, $endpoint['schemes'], $endpoint['formats'], $endpoint['discovery']); } $this->name = $name; @@ -91,6 +89,9 @@ public function getEndpoints() { /** * Builds the endpoint URL and returns it. * + * The oEmbed API could provide multiple endpoints, but never does this. + * So the resource URL will be built from the first available endpoint. + * * @param string $url * The canonical media URL. * diff --git a/core/modules/media/src/OEmbed/ProviderDiscovery.php b/core/modules/media/src/OEmbed/ProviderCollector.php similarity index 77% rename from core/modules/media/src/OEmbed/ProviderDiscovery.php rename to core/modules/media/src/OEmbed/ProviderCollector.php index 5dafe41cec..335c512eae 100644 --- a/core/modules/media/src/OEmbed/ProviderDiscovery.php +++ b/core/modules/media/src/OEmbed/ProviderCollector.php @@ -4,6 +4,7 @@ use Drupal\Component\Datetime\TimeInterface; use Drupal\Component\Serialization\Json; +use Drupal\Component\Utility\Html; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Url; use GuzzleHttp\Client; @@ -12,7 +13,7 @@ /** * Retrieves and caches information about oEmbed providers. */ -class ProviderDiscovery implements ProviderDiscoveryInterface { +class ProviderCollector implements ProviderCollectorInterface { /** * Cache provider list for a week. @@ -108,38 +109,10 @@ public function getAll() { public function get($provider_name) { $providers = $this->getAll(); - if (isset($providers[$provider_name])) { - return $providers[$provider_name]; - } - else { + if (!isset($providers[$provider_name])) { throw new \InvalidArgumentException("Unknown provider '$provider_name'"); } - } - - /** - * {@inheritdoc} - */ - public function getProviderByUrl($url) { - if ($url instanceof Url) { - $url = $url->toString(); - } - - // Check the URL against every scheme of every endpoint of every provider - // until we find a match. - foreach ($this->getAll() as $provider_name => $provider_info) { - if (empty($provider_info->getEndpoints())) { - continue; - } - foreach ($provider_info->getEndpoints() as $endpoint) { - if (empty($endpoint->getSchemes())) { - continue; - } - if ($endpoint->matchUrl($url)) { - return $provider_info; - } - } - } - return FALSE; + return $providers[$provider_name]; } } diff --git a/core/modules/media/src/OEmbed/ProviderDiscoveryInterface.php b/core/modules/media/src/OEmbed/ProviderCollectorInterface.php similarity index 62% rename from core/modules/media/src/OEmbed/ProviderDiscoveryInterface.php rename to core/modules/media/src/OEmbed/ProviderCollectorInterface.php index 10cbe52e3e..387a87fd2b 100644 --- a/core/modules/media/src/OEmbed/ProviderDiscoveryInterface.php +++ b/core/modules/media/src/OEmbed/ProviderCollectorInterface.php @@ -3,9 +3,9 @@ namespace Drupal\media\OEmbed; /** - * Interface for OEmbedProviderDiscovery service. + * Interface for OEmbedProviderCollector service. */ -interface ProviderDiscoveryInterface { +interface ProviderCollectorInterface { /** * Gets oEmbed providers information. @@ -17,7 +17,7 @@ * @return \Drupal\media\OEmbed\Provider[] * Information about oEmbed providers. * - * @see \Drupal\media\ProviderDiscoveryInterface::get() + * @see \Drupal\media\ProviderCollectorInterface::get() * * @throws \Drupal\media\OEmbed\ProviderException */ @@ -37,17 +37,4 @@ public function getAll(); */ public function get($provider_name); - /** - * Tries to get provider info from the provider list. - * - * @param string $url - * The URL of a media object to match against the oEmbed providers. - * - * @return \Drupal\media\OEmbed\Provider|bool - * Returns a single provider if found, otherwise FALSE. - * - * @see \Drupal\media\ProviderDiscoveryInterface::get() - */ - public function getProviderByUrl($url); - } diff --git a/core/modules/media/src/OEmbed/ProviderException.php b/core/modules/media/src/OEmbed/ProviderException.php index e6284a9101..1b72b7f34d 100644 --- a/core/modules/media/src/OEmbed/ProviderException.php +++ b/core/modules/media/src/OEmbed/ProviderException.php @@ -14,7 +14,7 @@ class ProviderException extends \Exception { * * @var \Drupal\media\OEmbed\Provider * - * @see \Drupal\media\OEmbed\ProviderDiscoveryInterface::get() + * @see \Drupal\media\OEmbed\ProviderCollectorInterface::get() */ protected $provider; diff --git a/core/modules/media/src/OEmbed/ResourceFetcher.php b/core/modules/media/src/OEmbed/ResourceFetcher.php index c119ce0948..a1e84920e6 100644 --- a/core/modules/media/src/OEmbed/ResourceFetcher.php +++ b/core/modules/media/src/OEmbed/ResourceFetcher.php @@ -3,11 +3,8 @@ namespace Drupal\media\OEmbed; use Drupal\Component\Serialization\Json; -use Drupal\Component\Utility\Html; -use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Cache\UseCacheBackendTrait; -use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Url; use GuzzleHttp\Client; use GuzzleHttp\Exception\RequestException; @@ -19,13 +16,6 @@ class ResourceFetcher implements ResourceFetcherInterface { use UseCacheBackendTrait; - /** - * The OEmbed provider discovery service. - * - * @var \Drupal\media\OEmbed\ProviderDiscoveryInterface - */ - protected $providerDiscovery; - /** * The HTTP client. * @@ -34,134 +24,19 @@ class ResourceFetcher implements ResourceFetcherInterface { protected $httpClient; /** - * The module handler service. - * - * @var \Drupal\Core\Extension\ModuleHandlerInterface - */ - protected $moduleHandler; - - /** - * Static cache of discovered oEmbed resources. - * - * A discovered oEmbed resource is the oEmbed URL for a specific media object. - * This oEmbed URL is fetched from the canonical URL of the media object. + * Constructs ResourceFetcher class. * - * @var array - */ - protected $urlCache; - - /** - * Constructs OEmbed class. - * - * @param \Drupal\media\OEmbed\ProviderDiscoveryInterface $provider_discovery - * The OEmbed provider discovery service. * @param \GuzzleHttp\Client $http_client * The HTTP client. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler - * The module handler service. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * (optional) The cache backend. */ - public function __construct(ProviderDiscoveryInterface $provider_discovery, Client $http_client, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend = NULL) { - $this->providerDiscovery = $provider_discovery; + public function __construct(Client $http_client, CacheBackendInterface $cache_backend = NULL) { $this->httpClient = $http_client; - $this->moduleHandler = $module_handler; $this->cacheBackend = $cache_backend; $this->useCaches = isset($cache_backend); } - /** - * {@inheritdoc} - */ - public function getResourceUrl($url, $max_width = NULL, $max_height = NULL) { - $cache_id = 'media:oembed_resource_url:' . hash('sha256', $url); - - if ($this->urlCache === NULL) { - $this->urlCache = []; - if ($cached = $this->cacheGet($cache_id)) { - $this->urlCache[$url] = $cached->data; - } - } - - if ($url instanceof Url) { - $url = $url->toString(); - } - - if (isset($this->urlCache[$url])) { - return $this->urlCache[$url]; - } - - $provider = $this->providerDiscovery->getProviderByUrl($url); - if ($provider) { - $resource_url = $provider->buildResourceUrl($url); - } - else { - $resource_url = $this->discoverResourceUrl($url); - } - - if (empty($resource_url)) { - throw new ResourceException('Could not determine the oEmbed resource URL.', $url); - } - - $parsed_url = UrlHelper::parse($resource_url); - if ($max_width) { - $parsed_url['query']['max_width'] = $max_width; - } - if ($max_height) { - $parsed_url['query']['max_height'] = $max_height; - } - // Let other modules alter the query string, because some oEmbed providers - // are providing extra parameters. For example, Instagram also supports the - // 'omitscript' parameter. - $this->moduleHandler->alter('oembed_resource_url', $parsed_url); - $resource_url = $parsed_url['path'] . '?' . UrlHelper::buildQuery($parsed_url['query']); - - $this->urlCache[$url] = $resource_url; - $this->cacheSet($cache_id, $resource_url); - return $resource_url; - } - - /** - * Runs oEmbed discovery and returns the endpoint URL if successful. - * - * @param string $url - * The resource's URL. - * - * @return string|bool - * URL of the oEmbed endpoint, or FALSE if the discovery was not successful. - * - * @throws \Drupal\media\OEmbed\ResourceException - */ - protected function discoverResourceUrl($url) { - try { - $response = $this->httpClient->get($url); - } - catch (RequestException $e) { - throw new ResourceException('Could not fetch oEmbed resource.', $url, [], $e); - } - - $document = Html::load((string) $response->getBody()); - $xpath = new \DOMXpath($document); - - return $this->findUrl($xpath, 'json') ?: $this->findUrl($xpath, 'xml'); - } - - /** - * Tries to find the oEmbed URL in a DOM. - * - * @param \DOMXPath $xpath - * Page HTML as DOMXPath. - * @param string $format - * Format of oEmbed resource. Possible values are 'json' and 'xml'. - * - * @return bool|string - * A URL to an oEmbed resource or FALSE if not found. - */ - protected function findUrl(\DOMXPath $xpath, $format) { - $result = $xpath->query("//link[@type='application/$format+oembed']"); - return $result->length ? $result->item(0)->getAttribute('href') : FALSE; - } - /** * {@inheritdoc} */ diff --git a/core/modules/media/src/OEmbed/ResourceFetcherInterface.php b/core/modules/media/src/OEmbed/ResourceFetcherInterface.php index 16c908ae79..baf19b55da 100644 --- a/core/modules/media/src/OEmbed/ResourceFetcherInterface.php +++ b/core/modules/media/src/OEmbed/ResourceFetcherInterface.php @@ -3,29 +3,10 @@ namespace Drupal\media\OEmbed; /** - * Interface for oEmbed service. + * Interface for resource fetcher service. */ interface ResourceFetcherInterface { - /** - * Tries to match the URL against the database of oEmbed providers. - * - * @param string $url - * The URL to be tested. - * @param int|null $max_width - * Max width for the oEmbed resource. - * @param int|null $max_height - * Max height for the oEmbed resource. - * - * @return bool - * If a match was found, will return TRUE, otherwise FALSE. - * - * @see \Drupal\media\ResourceFetcherInterface::getProviders() - * - * @throws \Drupal\media\OEmbed\ResourceException - */ - public function getResourceUrl($url, $max_width = NULL, $max_height = NULL); - /** * Fetches information about the oEmbed resource. * diff --git a/core/modules/media/src/Plugin/Field/FieldFormatter/OEmbedFormatter.php b/core/modules/media/src/Plugin/Field/FieldFormatter/OEmbedFormatter.php index 6921ec2ed6..1d58eefbc0 100644 --- a/core/modules/media/src/Plugin/Field/FieldFormatter/OEmbedFormatter.php +++ b/core/modules/media/src/Plugin/Field/FieldFormatter/OEmbedFormatter.php @@ -6,9 +6,11 @@ use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FormatterBase; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Logger\LoggerChannelFactoryInterface; use Drupal\Core\Messenger\MessengerInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Url; +use Drupal\media\OEmbed\OEmbedManagerInterface; use Drupal\media\OEmbed\ResourceException; use Drupal\media\OEmbed\ResourceFetcherInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -36,11 +38,18 @@ class OEmbedFormatter extends FormatterBase implements ContainerFactoryPluginInt protected $resourceFetcher; /** - * The messenger service. + * The oEmbed manager. * - * @var \Drupal\Core\Messenger\MessengerInterface $messenger + * @var \Drupal\media\OEmbed\OEmbedManagerInterface */ - protected $messenger; + protected $oEmbedManager; + + /** + * The logger service. + * + * @var \Drupal\Core\Logger\LoggerChannelInterface $logger + */ + protected $logger; /** * Constructs a OEmbedFormatter instance. @@ -60,14 +69,17 @@ class OEmbedFormatter extends FormatterBase implements ContainerFactoryPluginInt * @param array $third_party_settings * Any third party settings settings. * @param \Drupal\media\OEmbed\ResourceFetcherInterface $resource_fetcher - * The oEmbed service. - * @param \Drupal\Core\Messenger\MessengerInterface $messenger - * The messenger service. + * The resource fetcher service. + * @param \Drupal\media\OEmbed\OEmbedManagerInterface $oembed_manager + * The oEmbed manager service. + * @param \Drupal\Core\Logger\LoggerChannelFactory $logger_factory + * The logger service. */ - public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, ResourceFetcherInterface $resource_fetcher, MessengerInterface $messenger) { + public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, ResourceFetcherInterface $resource_fetcher, OEmbedManagerInterface $oembed_manager, LoggerChannelFactoryInterface $logger_factory) { parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings); $this->resourceFetcher = $resource_fetcher; - $this->messenger = $messenger; + $this->oEmbedManager = $oembed_manager; + $this->logger = $logger_factory->get('media'); } /** @@ -83,7 +95,8 @@ public static function create(ContainerInterface $container, array $configuratio $configuration['view_mode'], $configuration['third_party_settings'], $container->get('media.oembed.resource_fetcher'), - $container->get('messenger') + $container->get('media.oembed.oembed_manager'), + $container->get('logger.factory') ); } @@ -111,10 +124,10 @@ public function viewElements(FieldItemListInterface $items, $langcode) { } try { - $resource = $this->resourceFetcher->fetchResource($this->resourceFetcher->getResourceUrl($item->{$main_property}, $this->getSetting('max_width'), $this->getSetting('max_height'))); + $resource = $this->resourceFetcher->fetchResource($this->oEmbedManager->getResourceUrl($item->{$main_property}, $this->getSetting('max_width'), $this->getSetting('max_height'))); } catch (ResourceException $exception) { - $this->messenger->addError($this->t("Could not retrieve the remote URL.")); + $this->logger->error("Could not retrieve the remote URL."); continue; } @@ -145,7 +158,7 @@ public function viewElements(FieldItemListInterface $items, $langcode) { break; default: - $this->messenger->addError($this->t("Unknown oEmbed resource type @type", ['@type' => $resource['type']])); + $this->logger->error("Unknown oEmbed resource type @type", ['@type' => $resource['type']]); } } diff --git a/core/modules/media/src/Plugin/Validation/Constraint/OEmbedProviderConstraintValidator.php b/core/modules/media/src/Plugin/Validation/Constraint/OEmbedProviderConstraintValidator.php index 021baf00c7..3b2ec7b520 100644 --- a/core/modules/media/src/Plugin/Validation/Constraint/OEmbedProviderConstraintValidator.php +++ b/core/modules/media/src/Plugin/Validation/Constraint/OEmbedProviderConstraintValidator.php @@ -2,11 +2,10 @@ namespace Drupal\media\Plugin\Validation\Constraint; -use Drupal\Component\Render\FormattableMarkup; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Logger\LoggerChannelFactoryInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; -use Drupal\media\OEmbed\ProviderDiscoveryInterface; +use Drupal\media\OEmbed\OEmbedManagerInterface; use Drupal\media\OEmbed\ProviderException; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Validator\Constraint; @@ -20,11 +19,11 @@ class OEmbedProviderConstraintValidator extends ConstraintValidator implements C use StringTranslationTrait; /** - * The oEmbed provider discovery service. + * The oEmbed manager service. * - * @var \Drupal\media\OEmbed\ProviderDiscoveryInterface + * @var \Drupal\media\OEmbed\OEmbedManagerInterface */ - protected $providerDiscovery; + protected $oEmbedManager; /** * The logger service. @@ -36,13 +35,13 @@ class OEmbedProviderConstraintValidator extends ConstraintValidator implements C /** * Constructs a new OEmbedProviderConstraintValidator. * - * @param \Drupal\media\OEmbed\ProviderDiscoveryInterface $provider_discovery - * The oEmbed provider discovery service. + * @param \Drupal\media\OEmbed\OEmbedManagerInterface $oembed_manager + * The oEmbed manager service. * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger_factory * The logger service. */ - public function __construct(ProviderDiscoveryInterface $provider_discovery, LoggerChannelFactoryInterface $logger_factory) { - $this->providerDiscovery = $provider_discovery; + public function __construct(OEmbedManagerInterface $oembed_manager, LoggerChannelFactoryInterface $logger_factory) { + $this->oEmbedManager = $oembed_manager; $this->logger = $logger_factory->get('media'); } @@ -51,7 +50,7 @@ public function __construct(ProviderDiscoveryInterface $provider_discovery, Logg */ public static function create(ContainerInterface $container) { return new static( - $container->get('media.oembed.provider_discovery'), + $container->get('media.oembed.oembed_manager'), $container->get('logger.factory') ); } @@ -65,7 +64,7 @@ public function validate($value, Constraint $constraint) { $url = $media->getSource()->getSourceFieldValue($media); try { - $provider = $this->providerDiscovery->getProviderByUrl($url); + $provider = $this->oEmbedManager->getProviderByUrl($url); } catch (ProviderException $e) { $this->context->addViolation($this->t('An error occurred while trying to retrieve the oEmbed provider database.')); diff --git a/core/modules/media/src/Plugin/Validation/Constraint/OEmbedResourceConstraintValidator.php b/core/modules/media/src/Plugin/Validation/Constraint/OEmbedResourceConstraintValidator.php index 2b3d477f81..08cfc220da 100644 --- a/core/modules/media/src/Plugin/Validation/Constraint/OEmbedResourceConstraintValidator.php +++ b/core/modules/media/src/Plugin/Validation/Constraint/OEmbedResourceConstraintValidator.php @@ -3,6 +3,7 @@ namespace Drupal\media\Plugin\Validation\Constraint; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; +use Drupal\media\OEmbed\OEmbedManagerInterface; use Drupal\media\OEmbed\ResourceException; use Drupal\media\OEmbed\ResourceFetcherInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -17,25 +18,25 @@ class OEmbedResourceConstraintValidator extends ConstraintValidator implements C /** * The oEmbed resource fetcher service. * - * @var \Drupal\media\OEmbed\ResourceFetcherInterface + * @var \Drupal\media\OEmbed\OEmbedManagerInterface */ - protected $resourceFetcher; + protected $oEmbedManager; /** * Constructs a new OEmbedResourceConstraintValidator instance. * - * @param \Drupal\media\OEmbed\ResourceFetcherInterface $resource_fetcher - * The oEmbed resource fetcher service. + * @param \Drupal\media\OEmbed\OEmbedManagerInterface $oembed_manager + * The oEmbed manager service. */ - public function __construct(ResourceFetcherInterface $resource_fetcher) { - $this->resourceFetcher = $resource_fetcher; + public function __construct(OEmbedManagerInterface $oembed_manager) { + $this->oEmbedManager = $oembed_manager; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { - return new static($container->get('media.oembed.resource_fetcher')); + return new static($container->get('media.oembed.oembed_manager')); } /** @@ -47,7 +48,7 @@ public function validate($value, Constraint $constraint) { $url = $media->getSource()->getSourceFieldValue($media); try { - $this->resourceFetcher->getResourceUrl($url); + $this->oEmbedManager->getResourceUrl($url); } catch (ResourceException $e) { $this->context->addViolation($constraint->message); diff --git a/core/modules/media/src/Plugin/media/Source/OEmbed.php b/core/modules/media/src/Plugin/media/Source/OEmbed.php index 0a63287c5a..b7cf7cf932 100644 --- a/core/modules/media/src/Plugin/media/Source/OEmbed.php +++ b/core/modules/media/src/Plugin/media/Source/OEmbed.php @@ -12,12 +12,13 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Logger\LoggerChannelInterface; use Drupal\Core\Messenger\MessengerInterface; +use Drupal\media\OEmbed\OEmbedManagerInterface; use Drupal\media\OEmbed\ResourceException; use Drupal\media\MediaSourceBase; use Drupal\media\MediaInterface; use Drupal\media\MediaTypeInterface; use Drupal\media\OEmbed\ResourceFetcherInterface; -use Drupal\media\OEmbed\ProviderDiscoveryInterface; +use Drupal\media\OEmbed\ProviderCollectorInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -63,11 +64,11 @@ class OEmbed extends MediaSourceBase implements OEmbedInterface { protected $resourceFetcher; /** - * The OEmbed provider discovery service. + * The OEmbed manager service. * - * @var \Drupal\media\OEmbed\ProviderDiscoveryInterface + * @var \Drupal\media\OEmbed\OEmbedManagerInterface */ - protected $providerDiscovery; + protected $oEmbedManager; /** * Constructs a new OEmbed instance. @@ -94,16 +95,16 @@ class OEmbed extends MediaSourceBase implements OEmbedInterface { * The transliteration service. * @param \Drupal\media\OEmbed\ResourceFetcherInterface $resource_fetcher * The oEmbed resource fetcher service. - * @param \Drupal\media\OEmbed\ProviderDiscoveryInterface $provider_discovery - * The oEmbed provider discovery service. + * @param \Drupal\media\OEmbed\OEmbedManagerInterface $oembed_manager + * The oEmbed manager 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, LoggerChannelInterface $logger, MessengerInterface $messenger, TransliterationInterface $transliteration, ResourceFetcherInterface $resource_fetcher, ProviderDiscoveryInterface $provider_discovery) { + public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, ConfigFactoryInterface $config_factory, FieldTypePluginManagerInterface $field_type_manager, LoggerChannelInterface $logger, MessengerInterface $messenger, TransliterationInterface $transliteration, ResourceFetcherInterface $resource_fetcher, OEmbedManagerInterface $oembed_manager) { parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $entity_field_manager, $field_type_manager, $config_factory); $this->logger = $logger; $this->messenger = $messenger; $this->transliteration = $transliteration; $this->resourceFetcher = $resource_fetcher; - $this->providerDiscovery = $provider_discovery; + $this->oEmbedManager = $oembed_manager; } /** @@ -122,7 +123,7 @@ public static function create(ContainerInterface $container, array $configuratio $container->get('messenger'), $container->get('transliteration'), $container->get('media.oembed.resource_fetcher'), - $container->get('media.oembed.provider_discovery') + $container->get('media.oembed.oembed_manager') ); } @@ -158,7 +159,7 @@ public function getMetadata(MediaInterface $media, $name) { $media_url = $this->getSourceFieldValue($media); try { - $resource_url = $this->resourceFetcher->getResourceUrl($media_url); + $resource_url = $this->oEmbedManager->getResourceUrl($media_url); $resource = $this->resourceFetcher->fetchResource($resource_url); } catch (ResourceException $e) { diff --git a/core/modules/media/tests/src/Functional/OEmbedProviderDiscoveryTest.php b/core/modules/media/tests/src/Functional/OEmbedProviderCollectorTest.php similarity index 86% rename from core/modules/media/tests/src/Functional/OEmbedProviderDiscoveryTest.php rename to core/modules/media/tests/src/Functional/OEmbedProviderCollectorTest.php index 862b92f021..70bb38beda 100644 --- a/core/modules/media/tests/src/Functional/OEmbedProviderDiscoveryTest.php +++ b/core/modules/media/tests/src/Functional/OEmbedProviderCollectorTest.php @@ -2,24 +2,23 @@ namespace Drupal\Tests\media\Functional; -use Drupal\media\OEmbed\ProviderDiscovery; +use Drupal\media\OEmbed\ProviderCollector; /** - * Tests the oEmbed provider discovery. + * Tests the oEmbed provider collector. * - * @covers \Drupal\media\ProviderDiscovery + * @covers \Drupal\media\ProviderCollector * * @group media */ -class OEmbedProviderDiscoveryTest extends MediaFunctionalTestBase { +class OEmbedProviderCollectorTest extends MediaFunctionalTestBase { /** - * Test provider discovery. + * Test provider collection. * * @dataProvider dataProviderEmptyProviderList */ public function testEmptyProviderList($content, $providerUrl, $exceptionClass, $exceptionMessage) { - $cacheBackend = $this->container->get('cache.default'); $time = $this->container->get('datetime.time'); @@ -39,8 +38,8 @@ public function testEmptyProviderList($content, $providerUrl, $exceptionClass, $ $this->setExpectedException($exceptionClass, $exceptionMessage); - $providerDiscovery = new ProviderDiscovery($client, $providerUrl, $time, $cacheBackend); - $providerDiscovery->getAll(); + $providerCollector = new ProviderCollector($client, $providerUrl, $time, $cacheBackend); + $providerCollector->getAll(); } /** @@ -79,8 +78,8 @@ public function testNonExistingProviderDatabase($providerUrl, $exceptionClass, $ $this->setExpectedException($exceptionClass, $exceptionMessage); - $providerDiscovery = new ProviderDiscovery($client, $providerUrl, $time, $cacheBackend); - $providerDiscovery->getAll(); + $providerCollector = new ProviderCollector($client, $providerUrl, $time, $cacheBackend); + $providerCollector->getAll(); } /** diff --git a/core/modules/media/tests/src/Functional/OEmbedTest.php b/core/modules/media/tests/src/Functional/OEmbedTest.php index 16620ea021..45b167b40d 100644 --- a/core/modules/media/tests/src/Functional/OEmbedTest.php +++ b/core/modules/media/tests/src/Functional/OEmbedTest.php @@ -2,6 +2,7 @@ namespace Drupal\Tests\media\Functional; +use Drupal\media\OEmbed\OEmbedManager; use Drupal\media\OEmbed\ResourceFetcher; /** @@ -20,9 +21,10 @@ public function testUrlDiscovery() { $cacheBackend = $this->container->get('cache.default'); $module_handler = $this->container->get('module_handler'); $client = $this->container->get('http_client'); - $oEmbedProviderDiscovery = $this->container->get('media.oembed.provider_discovery'); + $providerCollector = $this->container->get('media.oembed.provider_collector'); + $resourceFetcher = $this->container->get('media.oembed.resource_fetcher'); - $oEmbed = new ResourceFetcher($oEmbedProviderDiscovery, $client, $module_handler, $cacheBackend); + $oEmbed = new OEmbedManager($providerCollector, $resourceFetcher, $client, $module_handler, $cacheBackend); // Received by discovery. $this->assertSame('https://vimeo.com/api/oembed.json?url=https%3A//vimeo.com/7073899', $oEmbed->getResourceUrl('https://vimeo.com/7073899')); @@ -31,7 +33,7 @@ public function testUrlDiscovery() { // URL building with format replacement. $this->assertSame('http://www.collegehumor.com/oembed.json?url=http%3A//www.collegehumor.com/video/40002870/lets-not-get-a-drink-sometime', $oEmbed->getResourceUrl('http://www.collegehumor.com/video/40002870/lets-not-get-a-drink-sometime')); // URL building with height and width. - $this->assertSame('https://www.flickr.com/services/oembed?url=https%3A//www.flickr.com/photos/amazeelabs/30530130354&format=json&max_width=320&max_height=480', $oEmbed->getResourceUrl('https://www.flickr.com/photos/amazeelabs/30530130354/in/album-72157675936437840', 320, 480)); + $this->assertSame('http://www.flickr.com/services/oembed/?url=https%3A//www.flickr.com/photos/amazeelabs/30530130354/in/album-72157675936437840&max_width=320&max_height=480', $oEmbed->getResourceUrl('https://www.flickr.com/photos/amazeelabs/30530130354/in/album-72157675936437840', 320, 480)); } /** @@ -39,11 +41,11 @@ public function testUrlDiscovery() { */ public function testFetchResource() { $cacheBackend = $this->container->get('cache.default'); - $module_handler = $this->container->get('module_handler'); $client = $this->container->get('http_client'); - $oEmbedProviderDiscovery = $this->container->get('media.oembed.provider_discovery'); + $oEmbedProviderDiscovery = $this->container->get('media.oembed.provider_collector'); + $providerCollector = $this->container->get('media.oembed.provider_collector'); - $oEmbed = new ResourceFetcher($oEmbedProviderDiscovery, $client, $module_handler, $cacheBackend); + $oEmbed = new ResourceFetcher($client, $cacheBackend); // Fetch JSON resource. $resource = $oEmbed->fetchResource('https://vimeo.com/api/oembed.json?url=https%3A%2F%2Fvimeo.com%2F7073899');