Created
November 20, 2020 00:41
-
-
Save scott1702/85bb26889c036f3637b041cc4a83c3a5 to your computer and use it in GitHub Desktop.
Manually convert youtube links to iframe to prevent calls from to youtube
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use App\View\CustomEmbedShortcodeProvider; | |
use SilverStripe\View\Parsers\ShortcodeParser; | |
ShortcodeParser::get('default') | |
->register('embed', [CustomEmbedShortcodeProvider::class, 'handle_shortcode']); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\View; | |
use Psr\Log\LoggerInterface; | |
use Psr\SimpleCache\CacheInterface; | |
use SilverStripe\Core\Injector\Injector; | |
use SilverStripe\View\Shortcodes\EmbedShortcodeProvider; | |
class CustomEmbedShortcodeProvider extends EmbedShortcodeProvider | |
{ | |
/** | |
* Override handle_shortcode to manually convert youtube links to iframes, this | |
* prevents any potential rate limiting from Youtube. | |
* https://github.com/silverstripe/silverstripe-framework/issues/9073 | |
* | |
* @param $arguments | |
* @param $content | |
* @param $parser | |
* @param $shortcode | |
* @param array $extra | |
* | |
* @return string | |
*/ | |
public static function handle_shortcode($arguments, $content, $parser, $shortcode, $extra = array()) | |
{ | |
$cache = Injector::inst()->get(CacheInterface::class . '.embedcachenamespace'); | |
$cacheKey = 'embed_shortcode_cache_' . preg_replace('/[^a-zA-Z0-9]/', '', implode('-_-', $arguments)); | |
// To prevent being rate limited by youtube, we manually parse youtube links to an iframe | |
if (self::is_youtube_link($arguments)) { | |
preg_match( | |
'%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i', | |
$arguments['url'], | |
$matches | |
); | |
$width = $arguments['width'] ?? 480; | |
$height = $arguments['height'] ?? 270; | |
$title = ''; | |
// Add a title attribute to the iframe if one is defined | |
if (isset($arguments['title'])) { | |
$title = sprintf('title="%s"', $arguments['title']); | |
} | |
return sprintf( | |
'<iframe width="%s" height="%s" src="https://www.youtube.com/embed/%s?feature=oembed&rel=0" %s' . | |
'frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" ' . | |
'allowfullscreen></iframe>', | |
$width, | |
$height, | |
$matches[1], | |
$title | |
); | |
} | |
if ($cache->has($cacheKey)) { | |
return $cache->get($cacheKey); | |
} | |
try { | |
$output = parent::handle_shortcode($arguments, $content, $parser, $shortcode, $extra); | |
$cache->set($cacheKey, $output); | |
return $output; | |
} catch (\Exception $exception) { | |
$msg = "Handle shortcode failed for shortcode: " . $shortcode . " " . $exception; | |
Injector::inst()->get(LoggerInterface::class) | |
->warning($msg); | |
} | |
return ''; | |
} | |
/** | |
* Check if link is from youtube | |
* | |
* @param array $arguments - shortcode arguments | |
* @return boolean | |
*/ | |
public static function is_youtube_link($arguments) | |
{ | |
if (!isset($arguments['url'])) { | |
return false; | |
} | |
$isYoutubeLink = strpos($arguments['url'], 'youtube.com') !== false | |
|| strpos($arguments['url'], 'youtu.be') !== false; | |
return $isYoutubeLink; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Tests\View; | |
use App\View\CustomEmbedShortcodeProvider; | |
use SilverStripe\Dev\SapphireTest; | |
use SilverStripe\View\Parsers\ShortcodeParser; | |
class CustomEmbedShortcodeProviderTest extends SapphireTest | |
{ | |
/** | |
* @return string[][] | |
*/ | |
public function shortCodeHandlerDataProvider() | |
{ | |
return [ | |
[ | |
'[embed url="http://youtu.be/dQw4w9WgXcQ" width="300" height="200"]', | |
'width="300" height="200" src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed&rel=0"' | |
], | |
[ | |
'[embed url="http://www.youtube.com/embed/dQw4w9WgXcQ", width="350", height="270"]', | |
'width="350" height="270" src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed&rel=0"' | |
], | |
[ | |
'[embed url="http://www.youtube.com/watch?v=dQw4w9WgXcQ",height="180",width="250"]', | |
'width="250" height="180" src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed&rel=0"' | |
], | |
[ | |
'[embed url="http://www.youtube.com/?v=dQw4w9WgXcQ"]', | |
'width="480" height="270" src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed&rel=0"' | |
], | |
[ | |
'[embed url="http://www.youtube.com/v/dQw4w9WgXcQ"]', | |
'src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed&rel=0"' | |
], | |
[ | |
'[embed url="http://www.youtube.com/e/dQw4w9WgXcQ"]', | |
'src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed&rel=0"' | |
], | |
[ | |
'[embed url="http://www.youtube.com/user/username#p/u/11/dQw4w9WgXcQ"]', | |
'src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed&rel=0"' | |
], | |
[ | |
'[embed url="http://www.youtube.com/sandalsResorts#p/c/54B8C800269D7C1B/0/dQw4w9WgXcQ"]', | |
'src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed&rel=0"' | |
], | |
[ | |
'[embed url="http://www.youtube.com/watch?feature=player_embedded&v=dQw4w9WgXcQ"]', | |
'src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed&rel=0"' | |
], | |
[ | |
'[embed url="http://www.youtube.com/?feature=player_embedded&v=dQw4w9WgXcQ"]', | |
'src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed&rel=0"' | |
], | |
[ | |
'[embed url="https://vimeo.com/148751763"]', | |
'player.vimeo.com' | |
], | |
[ | |
'[embed url="https://twitter.com/TwitterDev"]', | |
'twitter.com' | |
], | |
]; | |
} | |
/** | |
* @dataProvider shortCodeHandlerDataProvider | |
*/ | |
public function testHandleShortcode($givenContent, $expected) | |
{ | |
$parser = new ShortcodeParser(); | |
$parser->register('embed', [CustomEmbedShortcodeProvider::class, 'handle_shortcode']); | |
$this->assertContains($expected, $parser->parse($givenContent)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment