diff -u b/core/modules/media/src/OEmbed.php b/core/modules/media/src/OEmbed.php --- b/core/modules/media/src/OEmbed.php +++ b/core/modules/media/src/OEmbed.php @@ -92,8 +92,8 @@ /** * {@inheritdoc} */ - public function getResourceUrl($url) { - $cacheKey = 'media:oembed:url:' . sha1($url); + public function getResourceUrl($url, $max_width = NULL, $max_height = NULL) { + $cacheKey = 'media:oembed:url:' . sha1($url . $max_width . $max_height); if (!empty($this->discovered[$url])) { return $this->discovered[$url]; } @@ -102,27 +102,45 @@ return $this->discovered[$url]; } else { - if ($this->discovered[$url] = $this->urlDiscovery($url)) { - $this->cacheSet($cacheKey, $this->discovered[$url]); - return $this->discovered[$url]; - } if ($provider_info = $this->getProvider($url)) { - // todo: Take formats into account - // todo: We could specify width and height if (!empty($provider_info['endpoints'])) { foreach ($provider_info['endpoints'] as $endpoint) { if (!empty($endpoint['url'])) { $options = [ 'url' => $url, ]; - $query_parameter = UrlHelper::buildQuery($options); - $this->discovered[$url] = $endpoint['url'] . '?' . $query_parameter; - $this->cacheSet($cacheKey, $this->discovered[$url]); - return $this->discovered[$url]; + $endpoint_url = $endpoint['url']; + if (strpos($endpoint_url, '{format}') !== FALSE) { + $format = (!empty($endpoint['formats']) && is_array($endpoint['formats'])) ? reset($endpoint['formats']) : $format = 'json'; + $endpoint_url = str_replace('{format}', $format, $endpoint_url); + } + $this->discovered[$url] = $endpoint_url . '?' . UrlHelper::buildQuery($options); } } } } + else { + $this->discovered[$url] = $this->urlDiscovery($url); + } + + if (!empty($this->discovered[$url])) { + $parsed_url = UrlHelper::parse($this->discovered[$url]); + if (!empty($max_width)) { + $parsed_url['query']['maxwidth'] = $max_width; + } + if (!empty($max_height)) { + $parsed_url['query']['maxheight'] = $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. + \Drupal::moduleHandler()->alter('oembed_resource_query', $parsed_url['query']); + $this->discovered[$url] = $parsed_url['path'] . '?' . UrlHelper::buildQuery($parsed_url['query']); + + $this->cacheSet($cacheKey, $this->discovered[$url]); + return $this->discovered[$url]; + } + } throw new OEmbedResourceException(); } @@ -131,7 +149,6 @@ * {@inheritdoc} */ public function isAllowedProvider($url, array $allowed_providers = []) { - if ($resource_url = $this->getResourceUrl($url)) { $data = $this->fetchResource($resource_url); if (empty($allowed_providers) || (!empty($data['provider_name']) && in_array(bin2hex($data['provider_name']), $allowed_providers))) { @@ -174,25 +191,23 @@ $format = $response->getHeader('Content-Type'); $content = (string) $response->getBody(); - $data = ''; - if (strpos($format[0], 'application/json') !== FALSE) { - $data = Json::decode($content); - } - elseif (strpos($format[0], 'text/xml') !== FALSE) { - $data = Json::decode(Json::encode($content)); - } - - if ($data && is_array($data)) { - $this->cacheSet($cacheKey, $data); - $this->resources[$endpoint_url] = $data; - return $data; - } - else { + if (strpos($format[0], 'application/json') === FALSE && strpos($format[0], 'text/xml') === FALSE) { $this->logger->error('Remote resource returned incorrect response content. Data: @response', [ - '@response' => Json::encode($data), + '@response' => $content, ]); throw new OEmbedResourceException('An error occurred while trying to retrieve the remote URL content.'); } + + if (strpos($format[0], 'text/xml') !== FALSE) { + // Load XML into SimpleXMLElement. + $content = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA); + // Converting SimpleXMLElement to JSON. + $content = Json::encode($content); + } + + $this->resources[$endpoint_url] = Json::decode($content); + $this->cacheSet($cacheKey, $data); + return $this->resources[$endpoint_url]; } } diff -u b/core/modules/media/src/OEmbedInterface.php b/core/modules/media/src/OEmbedInterface.php --- b/core/modules/media/src/OEmbedInterface.php +++ b/core/modules/media/src/OEmbedInterface.php @@ -12,13 +12,17 @@ * * @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\OEmbedInterface::getProviders() */ - public function getResourceUrl($url); + public function getResourceUrl($url, $max_width = NULL, $max_height = NULL); /** * Determines whether a given URL is an oEmbed resource. diff -u b/core/modules/media/src/Plugin/Field/FieldFormatter/OEmbedFormatter.php b/core/modules/media/src/Plugin/Field/FieldFormatter/OEmbedFormatter.php --- b/core/modules/media/src/Plugin/Field/FieldFormatter/OEmbedFormatter.php +++ b/core/modules/media/src/Plugin/Field/FieldFormatter/OEmbedFormatter.php @@ -5,6 +5,7 @@ use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FormatterBase; +use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\media\Exception\OEmbedResourceException; use Drupal\media\OEmbedInterface; @@ -76,6 +77,16 @@ /** * {@inheritdoc} */ + public static function defaultSettings() { + return [ + 'maxwidth' => NULL, + 'maxheight' => NULL, + ] + parent::defaultSettings(); + } + + /** + * {@inheritdoc} + */ public function viewElements(FieldItemListInterface $items, $langcode) { $element = []; @@ -83,7 +94,7 @@ $main_property = $item->getFieldDefinition()->getFieldStorageDefinition()->getMainPropertyName(); if (!empty($item->{$main_property})) { try { - $resource = $this->oEmbed->fetchResource($this->oEmbed->getResourceUrl($item->{$main_property})); + $resource = $this->oEmbed->fetchResource($this->oEmbed->getResourceUrl($item->{$main_property}, $this->getSetting('maxwidth'), $this->getSetting('maxheight'))); $element[$delta] = [ '#theme' => 'media_oembed', '#post' => (string) $resource['html'], @@ -100,2 +111,52 @@ + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + return parent::settingsForm($form, $form_state) + [ + 'maxwidth' => [ + '#type' => 'number', + '#title' => $this->t('Max width'), + '#default_value' => $this->getSetting('maxwidth'), + '#size' => 5, + '#maxlength' => 5, + '#field_suffix' => $this->t('pixels'), + '#min' => 0, + ], + 'maxheight' => [ + '#type' => 'number', + '#title' => $this->t('Max height'), + '#default_value' => $this->getSetting('maxheight'), + '#size' => 5, + '#maxlength' => 5, + '#field_suffix' => $this->t('pixels'), + '#min' => 0, + ], + ]; + } + + /** + * {@inheritdoc} + */ + public function settingsSummary() { + $summary = parent::settingsSummary(); + if ($this->getSetting('maxwidth') && $this->getSetting('maxheight')) { + $summary[] = $this->t('Max size: %maxwidth x %maxheight pixels', [ + '%maxwidth' => $this->getSetting('maxwidth'), + '%maxheight' => $this->getSetting('maxheight'), + ]); + } + elseif ($this->getSetting('maxwidth')) { + $summary[] = $this->t('Max width: %maxwidth pixels', [ + '%maxwidth' => $this->getSetting('maxwidth'), + ]); + } + elseif ($this->getSetting('maxheight')) { + $summary[] = $this->t('Max height: %maxheight pixels', [ + '%maxheight' => $this->getSetting('maxheight'), + ]); + } + return $summary; + } + } diff -u b/core/modules/media/tests/src/Functional/OEmbedTest.php b/core/modules/media/tests/src/Functional/OEmbedTest.php --- b/core/modules/media/tests/src/Functional/OEmbedTest.php +++ b/core/modules/media/tests/src/Functional/OEmbedTest.php @@ -17,7 +17,6 @@ * Test isProvidedUrl method. */ public function testIsProvidedUrl() { - $providers = [ '596f7554756265' => [ @@ -81,7 +80,6 @@ * Test urlDiscovery method. */ public function testUrlDiscovery() { - $cacheBackend = $this->container->get('cache.default'); $logger = $this->container->get('logger.factory'); $client = $this->container->get('http_client_factory'); @@ -90,16 +88,19 @@ $oEmbed = new OEmbed($oEmbedProviderDiscovery, $client, $cacheBackend, $logger); // Received by discovery. - $this->assertSame('https://vimeo.com/api/oembed.json?url=https%3A%2F%2Fvimeo.com%2F7073899', $oEmbed->getResourceUrl('https://vimeo.com/7073899')); + $this->assertSame('https://vimeo.com/api/oembed.json?url=https%3A//vimeo.com/7073899', $oEmbed->getResourceUrl('https://vimeo.com/7073899')); // Received by URL building. - $this->assertSame('https://publish.twitter.com/oembed?url=https://twitter.com/drupaldevdays/status/935643039741202432', $oEmbed->getResourceUrl('https://twitter.com/drupaldevdays/status/935643039741202432')); + $this->assertSame('https://publish.twitter.com/oembed?url=https%3A//twitter.com/drupaldevdays/status/935643039741202432', $oEmbed->getResourceUrl('https://twitter.com/drupaldevdays/status/935643039741202432')); + // 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&maxwidth=320&maxheight=480', $oEmbed->getResourceUrl('https://www.flickr.com/photos/amazeelabs/30530130354/in/album-72157675936437840', 320, 480)); } /** * Test fetchResource method. */ public function testFetchResource() { - $cacheBackend = $this->container->get('cache.default'); $logger = $this->container->get('logger.factory'); $client = $this->container->get('http_client_factory'); @@ -107,11 +108,17 @@ $oEmbed = new OEmbed($oEmbedProviderDiscovery, $client, $cacheBackend, $logger); + // Fetch JSON resource. $resource = $oEmbed->fetchResource('https://vimeo.com/api/oembed.json?url=https%3A%2F%2Fvimeo.com%2F7073899'); - $this->assertSame('video', $resource['type']); $this->assertSame('Vimeo', $resource['provider_name']); $this->assertSame('Drupal Rap Video - Schipulcon09', $resource['title']); + + // Fetch XML resource. + $resource = $oEmbed->fetchResource('http://www.collegehumor.com/oembed.xml?url=http%3A//www.collegehumor.com/video/40002870/lets-not-get-a-drink-sometime'); + $this->assertSame('video', $resource['type']); + $this->assertSame('CollegeHumor', $resource['provider_name']); + $this->assertSame('Let\'s Not Get a Drink Sometime', $resource['title']); } }