Skip to content

Instantly share code, notes, and snippets.

@scott1702
Created November 20, 2020 00:41
Show Gist options
  • Save scott1702/85bb26889c036f3637b041cc4a83c3a5 to your computer and use it in GitHub Desktop.
Save scott1702/85bb26889c036f3637b041cc4a83c3a5 to your computer and use it in GitHub Desktop.
Manually convert youtube links to iframe to prevent calls from to youtube
<?php
use App\View\CustomEmbedShortcodeProvider;
use SilverStripe\View\Parsers\ShortcodeParser;
ShortcodeParser::get('default')
->register('embed', [CustomEmbedShortcodeProvider::class, 'handle_shortcode']);
<?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;
}
}
<?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&amp;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&amp;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&amp;rel=0"'
],
[
'[embed url="http://www.youtube.com/?v=dQw4w9WgXcQ"]',
'width="480" height="270" src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed&amp;rel=0"'
],
[
'[embed url="http://www.youtube.com/v/dQw4w9WgXcQ"]',
'src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed&amp;rel=0"'
],
[
'[embed url="http://www.youtube.com/e/dQw4w9WgXcQ"]',
'src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed&amp;rel=0"'
],
[
'[embed url="http://www.youtube.com/user/username#p/u/11/dQw4w9WgXcQ"]',
'src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed&amp;rel=0"'
],
[
'[embed url="http://www.youtube.com/sandalsResorts#p/c/54B8C800269D7C1B/0/dQw4w9WgXcQ"]',
'src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed&amp;rel=0"'
],
[
'[embed url="http://www.youtube.com/watch?feature=player_embedded&v=dQw4w9WgXcQ"]',
'src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed&amp;rel=0"'
],
[
'[embed url="http://www.youtube.com/?feature=player_embedded&v=dQw4w9WgXcQ"]',
'src="https://www.youtube.com/embed/dQw4w9WgXcQ?feature=oembed&amp;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