Skip to content

Commit

Permalink
Merge pull request #1049 from bedita/feat/oembed-vimeo-domain-level-p…
Browse files Browse the repository at this point in the history
…rivacy

Improve oembed feature
  • Loading branch information
didoda authored Oct 6, 2023
2 parents 7b56e50 + e3428e9 commit bd08f0c
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 32 deletions.
49 changes: 37 additions & 12 deletions config/oembed.php
Original file line number Diff line number Diff line change
@@ -1,25 +1,50 @@
<?php

use Cake\Routing\Router;

return [
/**
* Simplified oEmbed configuration.
* This method is not meant to give a precise provider match but it simply gives
* the most probable oembed provider for an URL.
*
* - providers: list of hostnames with associated providers oEmbed endpoints
* - providers: list providers with oEmbed endpoints and hostnames to match.
* With optional 'options' you can specify options for the oembed request as headers, ...
*/
'OEmbed' => [
'providers' => [

'soundcloud.com' => 'https://soundcloud.com/oembed',

'*.spotify.com' => 'https://embed.spotify.com/oembed/',

'vimeo.com' => 'https://vimeo.com/api/oembed.json',
'*.vimeo.com' => 'https://vimeo.com/api/oembed.json',

'youtube.com' => 'https://www.youtube.com/oembed',
'www.youtube.com' => 'https://www.youtube.com/oembed',
'youtu.be' => 'https://www.youtube.com/oembed',
'soundcloud' => [
'name' => 'SoundCloud',
'match' => ['soundcloud.com'],
'url' => 'https://soundcloud.com/oembed',
],
'spotify' => [
'name' => 'Spotify',
'match' => ['*.spotify.com'],
'url' => 'https://embed.spotify.com/oembed',
],
'vimeo' => [
'name' => 'Vimeo',
'match' => [
'vimeo.com',
'*.vimeo.com',
],
'url' => 'https://vimeo.com/api/oembed.json',
'options' => [
'headers' => [
'Referer' => env('VIMEO_REFERER_HEADER', Router::url('/', true)),
],
],
],
'youtube' => [
'name' => 'YouTube',
'match' => [
'youtube.com',
'www.youtube.com',
'youtu.be',
],
'url' => 'https://www.youtube.com/oembed',
],
],
],
];
42 changes: 24 additions & 18 deletions src/Utility/OEmbed.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,18 @@ public function readMetadata($url): array
{
$parsed = parse_url($url);
$host = Hash::get($parsed, 'host', '');
$oemBedurl = $this->findProvider($host);
if (empty($oemBedurl)) {
$provider = $this->findProvider($host);
$oEmbedUrl = Hash::get($provider, 'url');
if (empty($oEmbedUrl)) {
return ['provider_url' => $url];
}

$oemBedurl = sprintf('%s?url=%s&format=json', $oemBedurl, $url);
$oEmbedUrl = sprintf('%s?url=%s&format=json', $oEmbedUrl, rawurlencode($url));

// custom UID if not found via oEmbed => query or path
$providerUID = Hash::get($parsed, 'query', Hash::get($parsed, 'path'));

$meta = $this->fetchJson($oemBedurl);
$meta = $this->fetchJson($oEmbedUrl, (array)Hash::get($provider, 'options'));
if (empty($meta)) {
return ['provider_url' => $url];
}
Expand All @@ -62,13 +63,14 @@ public function readMetadata($url): array
/**
* Fetch oEmbed JSON response from oEmbed provider URL
*
* @param string $oemBedurl oEmbed URL
* @param string $oEmbedUrl oEmbed URL
* @param array $options The options to apply to the request
* @return array JSON decoded response or empty array on failure
* @codeCoverageIgnore
*/
protected function fetchJson(string $oemBedurl): array
protected function fetchJson(string $oEmbedUrl, array $options = []): array
{
$o = (new Client())->get($oemBedurl, [], ['type' => 'json']);
$o = (new Client())->get($oEmbedUrl, [], ['type' => 'json'] + $options);

return $o->getJson() ?? [];
}
Expand All @@ -77,23 +79,27 @@ protected function fetchJson(string $oemBedurl): array
* Find oEmbed provider URL for a given hostname
*
* @param string $host Host name
* @return string|null OEmbed provider or null if no match
* @return array OEmbed provider configuration or null if no match
*/
protected function findProvider(string $host): ?string
protected function findProvider(string $host): array
{
Configure::load('oembed');
// exact match

$providers = (array)Configure::read('OEmbed.providers');
if (!empty($providers[$host])) {
return $providers[$host];
}
// wildcard match
foreach ($providers as $h => $url) {
if (fnmatch($h, $host)) {
return $url;
$providerConf = array_filter($providers, function ($conf) use ($host) {
foreach ((array)Hash::get($conf, 'match') as $pattern) {
if (fnmatch($pattern, $host)) {
return true;
}
}

return false;
});

if (empty($providerConf)) {
return [];
}

return null;
return current($providerConf);
}
}
6 changes: 5 additions & 1 deletion templates/Element/Form/media.twig
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@
<div v-show="isOpen" class="tab-container">
{# Display embedded video if available #}
{% if object.attributes.provider_extra.html %}
{% set height = object.attributes.provider_extra.height|default(1) %}
{% set width = object.attributes.provider_extra.width|default(1) %}
<div class="embedded-container"
style="padding-bottom: {{ 100 * object.attributes.provider_extra.height / object.attributes.provider_extra.width }}%;">
{% if height matches '/^\\d+$/' and width matches '/^\\d+$/' %}
style="padding-bottom: {{ 100 * height / width|default(1) }}%;"
{% endif %}>
{{ object.attributes.provider_extra.html|raw }}
</div>
{% else %}
Expand Down
2 changes: 1 addition & 1 deletion tests/TestCase/Utility/OEmbedTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public function testReadMetadata(array $expected, string $url, array $oembedResp
$oembed = new class () extends OEmbed
{
public $json = [];
protected function fetchJson(string $oembedUrl): array
protected function fetchJson(string $oembedUrl, array $options = []): array
{
return $this->json;
}
Expand Down

0 comments on commit bd08f0c

Please sign in to comment.