diff --git a/_config/oembed.yml b/_config/oembed.yml index 75f4bc774..31a1b742b 100644 --- a/_config/oembed.yml +++ b/_config/oembed.yml @@ -3,4 +3,7 @@ Name: coreoembed --- SilverStripe\Core\Injector\Injector: SilverStripe\View\Embed\Embeddable: - class: SilverStripe\View\Embed\EmbedResource + class: SilverStripe\View\Embed\EmbedContainer + Embed\Embed: + constructor: + - '%$Embed\Http\Crawler' diff --git a/composer.json b/composer.json index 286c2d720..08806cc7a 100644 --- a/composer.json +++ b/composer.json @@ -25,8 +25,8 @@ "bramus/monolog-colored-line-formatter": "^2", "composer/installers": "^1 || ^2", "composer/semver": "^1 || ^3", - "embed/embed": "^3", "guzzlehttp/psr7": "^2", + "embed/embed": "^4", "league/csv": "^8 || ^9", "m1/env": "^2.1", "monolog/monolog": "^1.16", diff --git a/src/View/Embed/EmbedContainer.php b/src/View/Embed/EmbedContainer.php new file mode 100644 index 000000000..5374842ff --- /dev/null +++ b/src/View/Embed/EmbedContainer.php @@ -0,0 +1,138 @@ + '%$' . Embed::class, + ]; + + public Embed $embed; + + private ?Extractor $extractor = null; + + private string $url; + + private array $options = []; + + public function __construct(string $url) + { + $this->url = $url; + } + + /** + * @return int + */ + public function getWidth() + { + $code = $this->getExtractor()->code; + return $code ? ($code->width ?: 100) : 100; + } + + /** + * @return int + */ + public function getHeight() + { + $code = $this->getExtractor()->code; + return $code ? ($code->height ?: 100) : 100; + } + + /** + * @return string + */ + public function getPreviewURL() + { + $extractor = $this->getExtractor(); + + // Use thumbnail url + if ($extractor->image) { + return (string) $extractor->image; + } + + // Default media + return ModuleResourceLoader::resourceURL( + 'silverstripe/asset-admin:client/dist/images/icon_file.png' + ); + } + + /** + * @return string + */ + public function getName() + { + $extractor = $this->getExtractor(); + if ($extractor->title) { + return $extractor->title; + } + if ($extractor->url instanceof UriInterface) { + return basename($extractor->url->getPath()); + } + return ''; + } + + /** + * @return string + */ + public function getType() + { + $html = $this->getExtractor()->code->html ?? ''; + if (strpos($html, 'getExtractor()->code->html ?? ''); + } + + public function getOptions(): array + { + return $this->options; + } + + public function setOptions(array $options): self + { + $this->options = $options; + return $this; + } + + /** + * Calling this method will trigger the HTTP call(s) to the remote url + */ + public function getExtractor(): Extractor + { + if (!$this->extractor) { + $this->extractor = $this->embed->get($this->url); + } + return $this->extractor; + } +} diff --git a/src/View/Embed/EmbedResource.php b/src/View/Embed/EmbedResource.php index fdfbdc50e..216498691 100644 --- a/src/View/Embed/EmbedResource.php +++ b/src/View/Embed/EmbedResource.php @@ -6,11 +6,16 @@ use Embed\Adapters\Adapter; use Embed\Embed; use Embed\Http\DispatcherInterface; use SilverStripe\Core\Manifest\ModuleResourceLoader; +use SilverStripe\Dev\Deprecation; /** + * This is a deprecated class that was compatible with embed/embed v3 + * This has been replaced with EmbedContainer which is embed/embed v4 compatible + * * Encapsulation of an embed tag, linking to an external media source. * * @see Embed + * @deprecated 4.11..5.0 Use EmbedContainer instead */ class EmbedResource implements Embeddable { @@ -41,6 +46,7 @@ class EmbedResource implements Embeddable */ public function __construct($url) { + Deprecation::notice('4.11', 'Use EmbedContainer instead'); $this->url = $url; } diff --git a/src/View/Embed/Embeddable.php b/src/View/Embed/Embeddable.php index e274aba6d..085153400 100644 --- a/src/View/Embed/Embeddable.php +++ b/src/View/Embed/Embeddable.php @@ -5,7 +5,7 @@ namespace SilverStripe\View\Embed; /** * Abstract interface for an embeddable resource * - * @see EmbedResource + * @see EmbedContainer */ interface Embeddable { diff --git a/src/View/Shortcodes/EmbedShortcodeProvider.php b/src/View/Shortcodes/EmbedShortcodeProvider.php index ab0eb976b..98d4cca26 100644 --- a/src/View/Shortcodes/EmbedShortcodeProvider.php +++ b/src/View/Shortcodes/EmbedShortcodeProvider.php @@ -2,23 +2,22 @@ namespace SilverStripe\View\Shortcodes; -use Embed\Http\DispatcherInterface; +use Embed\Http\NetworkException; +use Embed\Http\RequestException; use Psr\SimpleCache\CacheInterface; use Psr\SimpleCache\InvalidArgumentException; use SilverStripe\Core\Convert; -use SilverStripe\Core\Extensible; use SilverStripe\Core\Injector\Injector; use SilverStripe\ORM\ArrayList; use SilverStripe\ORM\FieldType\DBField; use SilverStripe\View\ArrayData; use SilverStripe\View\Embed\Embeddable; -use SilverStripe\View\Embed\EmbedResource; use SilverStripe\View\HTML; use SilverStripe\View\Parsers\ShortcodeHandler; -use Embed\Adapters\Adapter; -use Embed\Exceptions\InvalidUrlException; use SilverStripe\View\Parsers\ShortcodeParser; use SilverStripe\Control\Director; +use SilverStripe\Dev\Deprecation; +use SilverStripe\View\Embed\EmbedContainer; /** * Provider for the [embed] shortcode tag used by the embedding service @@ -84,32 +83,23 @@ class EmbedShortcodeProvider implements ShortcodeHandler $serviceArguments['min_image_height'] = $arguments['height']; } - /** @var EmbedResource $embed */ - $embed = Injector::inst()->create(Embeddable::class, $serviceURL); + /** @var EmbedContainer $embeddable */ + $embeddable = Injector::inst()->create(Embeddable::class, $serviceURL); + + // Only EmbedContainer is currently supported + if (!($embeddable instanceof EmbedContainer)) { + throw new \RuntimeException('Emeddable must extend EmbedContainer'); + } + if (!empty($serviceArguments)) { - $embed->setOptions(array_merge($serviceArguments, (array) $embed->getOptions())); - } - - // Allow resolver to be mocked - $dispatcher = null; - if (isset($extra['resolver'])) { - $dispatcher = Injector::inst()->create( - $extra['resolver']['class'], - $serviceURL, - $extra['resolver']['config'] - ); - } elseif (Injector::inst()->has(DispatcherInterface::class)) { - $dispatcher = Injector::inst()->get(DispatcherInterface::class); - } - - if ($dispatcher) { - $embed->setDispatcher($dispatcher); + $embeddable->setOptions(array_merge($serviceArguments, (array) $embeddable->getOptions())); } // Process embed try { - $embed = $embed->getEmbed(); - } catch (InvalidUrlException $e) { + // this will trigger a request/response which will then be cached within $embeddable + $embeddable->getExtractor(); + } catch (NetworkException | RequestException $e) { $message = (Director::isDev()) ? $e->getMessage() : _t(__CLASS__ . '.INVALID_URL', 'There was a problem loading the media.'); @@ -127,30 +117,54 @@ class EmbedShortcodeProvider implements ShortcodeHandler } // Convert embed object into HTML - if ($embed && $embed instanceof Adapter) { - $result = static::embedForTemplate($embed, $arguments); - } + $html = static::embeddableToHtml($embeddable, $arguments); // Fallback to link to service - if (!$result) { + if (!$html) { $result = static::linkEmbed($arguments, $serviceURL, $serviceURL); } // Cache result - if ($result) { + if ($html) { try { - $cache->set($key, $result); + $cache->set($key, $html); } catch (InvalidArgumentException $e) { } } - return $result; + return $html; + } + + public static function embeddableToHtml(Embeddable $embeddable, array $arguments): string + { + // Only EmbedContainer is supported + if (!($embeddable instanceof EmbedContainer)) { + return ''; + } + $extractor = $embeddable->getExtractor(); + $type = $embeddable->getType(); + if ($type === 'video' || $type === 'rich') { + // Attempt to inherit width (but leave height auto) + if (empty($arguments['width']) && $embeddable->getWidth()) { + $arguments['width'] = $embeddable->getWidth(); + } + return static::videoEmbed($arguments, $extractor->code->html); + } + if ($type === 'photo') { + return static::photoEmbed($arguments, (string) $extractor->url); + } + if ($type === 'link') { + return static::linkEmbed($arguments, (string) $extractor->url, $extractor->title); + } + return ''; } /** * @param Adapter $embed * @param array $arguments Additional shortcode params * @return string + * @deprecated 4.11..5.0 Use embeddableToHtml instead */ public static function embedForTemplate($embed, $arguments) { + Deprecation::notice('4.11', 'Use embeddableToHtml() instead'); switch ($embed->getType()) { case 'video': case 'rich': diff --git a/tests/php/View/Embed/EmbedContainerTest.php b/tests/php/View/Embed/EmbedContainerTest.php new file mode 100644 index 000000000..09199e71d --- /dev/null +++ b/tests/php/View/Embed/EmbedContainerTest.php @@ -0,0 +1,134 @@ +getEmbedContainer(); + $this->assertSame(480, $container->getWidth()); + $this->assertSame(270, $container->getHeight()); + $container = $this->getFallbackEmbedContainer(); + $this->assertSame(100, $container->getWidth()); + $this->assertSame(100, $container->getHeight()); + } + + public function testGetPreviewURL() + { + $container = $this->getEmbedContainer(); + $this->assertSame('https://www.youtube.com/watch?v=iRXJXaLV0n4', $container->getPreviewURL()); + $container = $this->getFallbackEmbedContainer(); + if (class_exists(AssetAdmin::class)) { + $this->assertStringContainsString('client/dist/images/icon_file.png', $container->getPreviewURL()); + } + } + + public function testGetName() + { + $container = $this->getEmbedContainer(); + $this->assertSame('Try to stay SERIOUS -The most popular CAT videos', $container->getName()); + } + + public function testGetType() + { + $container = $this->getEmbedContainer(); + $this->assertSame('rich', $container->getType()); + $container = $this->getEmbedContainer( + << + + Your browser does not support the video tag. + + EOT + ); + $this->assertSame('video', $container->getType()); + $container = $this->getEmbedContainer( + << + + Your browser does not support the audio element. + + EOT + ); + $this->assertSame('audio', $container->getType()); + $container = $this->getEmbedContainer( + <<bird + EOT + ); + $this->assertSame('photo', $container->getType()); + $container = $this->getEmbedContainer('

Lorem ipsum

'); + $this->assertSame('link', $container->getType()); + } + + public function testValidate() + { + $container = $this->getEmbedContainer(); + $this->assertTrue($container->validate()); + $container = $this->getFallbackEmbedContainer(); + $this->assertFalse($container->validate()); + } + + public function testOptions() + { + $options = ['foo' => 'bar']; + $container = $this->getEmbedContainer(); + $this->assertSame([], $container->getOptions()); + $container->setOptions($options); + $this->assertSame($options, $container->getOptions()); + } + + public function testGetExtractor() + { + $container = $this->getEmbedContainer(); + $extractor = $container->getExtractor(); + $this->assertTrue($extractor instanceof Extractor); + $this->assertSame('Try to stay SERIOUS -The most popular CAT videos', $extractor->title); + } + + private function getFallbackEmbedContainer() + { + return $this->createEmbedContainer('', '', '', ''); + } + + private function getEmbedContainer(string $htmlOverride = '') + { + $html = $htmlOverride ?: implode('', [ + '' + ]); + $url = 'https://www.youtube.com/watch?v=iRXJXaLV0n4'; + return $this->createEmbedContainer( + $url, + $url, + implode('', [ + '' + ]), + json_encode([ + 'author_url' => 'https://www.youtube.com/channel/UCR2KG2dK1tAkwZZjm7rAiSg', + 'thumbnail_width' => 480, + 'title' => 'Try to stay SERIOUS -The most popular CAT videos', + 'width' => 480, + 'provider_name' => 'YouTube', + 'author_name' => 'Tiger Funnies', + 'height' => 270, + 'version' => '1.0', + 'type' => 'video', + // phpcs:ignore + 'html' => $html, + 'provider_url' => 'https://www.youtube.com/', + 'thumbnail_height' => 360, + 'thumbnail_url' => 'https://i.ytimg.com/vi/iRXJXaLV0n4/hqdefault.jpg', + ]) + ); + } +} diff --git a/tests/php/View/Embed/EmbedResourceTest.php b/tests/php/View/Embed/EmbedResourceTest.php deleted file mode 100644 index 4612f8530..000000000 --- a/tests/php/View/Embed/EmbedResourceTest.php +++ /dev/null @@ -1,65 +0,0 @@ -createMock(DispatcherInterface::class); - $dispatcherMock->expects($this->atLeastOnce())->method('dispatch')->willReturn($this->mockResponse()); - - /** @var EmbedResource $embed */ - $embed = Injector::inst()->create(EmbedResource::class, 'https://www.youtube.com/watch?v=iRXJXaLV0n4'); - $this->assertEmpty($embed->getOptions()); - $this->assertEmpty($embed->getDispatcher()); - - $embed->setOptions(['foo' => 'bar']); - $embed->setDispatcher($dispatcherMock); - - $adapter = $embed->getEmbed(); - $this->assertInstanceOf(Adapter::class, $adapter); - $this->assertSame('Try to stay SERIOUS -The most popular CAT videos', $adapter->getTitle()); - } - - /** - * Generate a mock Response object suitable for Embed - * - * @return Response - */ - private function mockResponse() - { - $url = Url::create('https://www.youtube.com/watch?v=iRXJXaLV0n4'); - return new Response( - $url, - $url, - 200, - 'application/json', - json_encode([ - 'author_url' => 'https://www.youtube.com/channel/UCR2KG2dK1tAkwZZjm7rAiSg', - 'thumbnail_width' => 480, - 'title' => 'Try to stay SERIOUS -The most popular CAT videos', - 'width' => 480, - 'provider_name' => 'YouTube', - 'author_name' => 'Tiger Funnies', - 'height' => 270, - 'version' => '1.0', - 'type' => 'video', - // phpcs:ignore - 'html' => '', - 'provider_url' => 'https://www.youtube.com/', - 'thumbnail_height' => 360, - 'thumbnail_url' => 'https://i.ytimg.com/vi/iRXJXaLV0n4/hqdefault.jpg', - ]), - [] - ); - } -} diff --git a/tests/php/View/Embed/EmbedUnitTest.php b/tests/php/View/Embed/EmbedUnitTest.php new file mode 100644 index 000000000..c58169f66 --- /dev/null +++ b/tests/php/View/Embed/EmbedUnitTest.php @@ -0,0 +1,68 @@ +firstRequest; + } + + public function setFirstRequest(bool $b): void + { + $this->firstRequest = $b; + } + + protected function createEmbedContainer( + string $urlA, + string $urlB, + string $firstResponse, + string $secondResponse + ): EmbedContainer { + $this->registerCrawlerService($urlA, $urlB, $firstResponse, $secondResponse); + $embedContainer = EmbedContainer::create($urlA); + return $embedContainer; + } + + private function registerCrawlerService( + string $urlA, + string $urlB, + string $firstResponse, + string $secondResponse + ): void { + $mockUriA = new MockUri($urlA); + $mockUriB = new MockUri($urlB); + $crawlerMock = $this->createMock(Crawler::class); + $crawlerMock->method('getResponseUri')->willReturn($mockUriA); + $crawlerMock->method('createUri')->willReturn($mockUriB); + $crawlerMock->method('sendRequest')->willReturn(new MockResponse($this, $firstResponse, $secondResponse)); + $crawlerMock->method('createRequest')->willReturn(new MockRequest($this, $mockUriA)); + Injector::inst()->registerService($crawlerMock, Crawler::class); + // replace the existing registered Embed singleton with a new singleton that is + // created using $crawlerMock as the the __constructor argument - see oembed.yml + $embed = Injector::inst()->create(Embed::class, $crawlerMock); + Injector::inst()->registerService($embed, Embed::class); + } + + /** + * This is to prevent the following warning: + * No tests found in class "SilverStripe\View\Tests\Embed\EmbedUnitTest". + */ + public function testPass() + { + $this->assertTrue(true); + } +} diff --git a/tests/php/View/Embed/MockRequest.php b/tests/php/View/Embed/MockRequest.php new file mode 100644 index 000000000..c92af5773 --- /dev/null +++ b/tests/php/View/Embed/MockRequest.php @@ -0,0 +1,97 @@ +unitTest = $unitTest; + $this->mockUri = $mockUri; + } + + public function getRequestTarget() + { + } + + public function getMethod() + { + } + + public function getUri() + { + $this->unitTest->setFirstRequest(false); + return $this->mockUri; + } + + public function getProtocolVersion() + { + } + + public function getHeaders() + { + } + + public function getHeader($name) + { + } + + public function getHeaderLine($name) + { + } + + public function getBody() + { + } + + public function hasHeader($name) + { + } + + public function withHeader($name, $value) + { + return $this; + } + + public function withAddedHeader($name, $value) + { + return $this; + } + + public function withoutHeader($name) + { + return $this; + } + + public function withBody(StreamInterface $body) + { + return $this; + } + + public function withProtocolVersion($version) + { + return $this; + } + + public function withRequestTarget($requestTarget) + { + return $this; + } + + public function withMethod($method) + { + return $this; + } + + public function withUri(UriInterface $uri, $preserveHost = false) + { + return $this; + } +} diff --git a/tests/php/View/Embed/MockResponse.php b/tests/php/View/Embed/MockResponse.php new file mode 100644 index 000000000..2c71e179b --- /dev/null +++ b/tests/php/View/Embed/MockResponse.php @@ -0,0 +1,90 @@ +unitTest = $unitTest; + $this->firstResponse = $firstResponse; + $this->secondResponse = $secondResponse; + } + + public function getStatusCode() + { + return 200; + } + + public function getBody() + { + // first request is to the video HTML to get to find the oembed link + // second request is to the oembed endpoint to fetch JSON + if ($this->unitTest->getFirstRequest()) { + return $this->firstResponse; + } else { + return $this->secondResponse; + } + } + + public function getReasonPhrase() + { + } + + public function getProtocolVersion() + { + } + + public function getHeaders() + { + } + + public function getHeader($name) + { + } + + public function getHeaderLine($name) + { + } + + public function hasHeader($name) + { + } + + public function withHeader($name, $value) + { + return $this; + } + + public function withAddedHeader($name, $value) + { + return $this; + } + + public function withBody(StreamInterface $body) + { + return $this; + } + + public function withoutHeader($name) + { + return $this; + } + + public function withProtocolVersion($version) + { + return $this; + } + + public function withStatus($code, $reasonPhrase = '') + { + return $this; + } +} diff --git a/tests/php/View/Embed/MockUri.php b/tests/php/View/Embed/MockUri.php new file mode 100644 index 000000000..a0577367a --- /dev/null +++ b/tests/php/View/Embed/MockUri.php @@ -0,0 +1,105 @@ +scheme = $p['scheme'] ?? ''; + $this->host = $p['host'] ?? ''; + $this->path = $p['path'] ?? ''; + $this->query = $p['query'] ?? ''; + } + + public function getScheme() + { + return $this->scheme; + } + + public function getHost() + { + return $this->host; + } + + public function getPath() + { + return $this->path; + } + + public function getQuery() + { + return $this->query; + } + + public function getPort() + { + } + + public function getAuthority() + { + } + + public function getUserInfo() + { + } + + public function getFragment() + { + } + + public function withPath($path) + { + return $this; + } + + public function withScheme($scheme) + { + return $this; + } + + public function withUserInfo($user, $password = null) + { + return $this; + } + + public function withHost($host) + { + return $this; + } + + public function withPort($port) + { + return $this; + } + + public function withQuery($query) + { + return $this; + } + + public function withFragment($fragment) + { + return $this; + } + + public function __toString() + { + $query = $this->getQuery(); + return sprintf( + '%s://%s%s%s', + $this->getScheme(), + $this->getHost(), + '/' . ltrim($this->getPath(), '/'), + $query ? "?$query" : '' + ); + } +} diff --git a/tests/php/View/Shortcodes/EmbedShortcodeProviderTest.php b/tests/php/View/Shortcodes/EmbedShortcodeProviderTest.php index d6e877a75..1cbc3e027 100644 --- a/tests/php/View/Shortcodes/EmbedShortcodeProviderTest.php +++ b/tests/php/View/Shortcodes/EmbedShortcodeProviderTest.php @@ -6,119 +6,154 @@ use Psr\SimpleCache\CacheInterface; use SilverStripe\View\Parsers\ShortcodeParser; use SilverStripe\View\Shortcodes\EmbedShortcodeProvider; use SilverStripe\Dev\SapphireTest; +use SilverStripe\View\Tests\Embed\EmbedUnitTest; -/** - * Class EmbedShortcodeProviderTest - * - * Because Embed/Embed does not have a mockup, the tests have to run against a live environment. - * I've tried to fix it by serializing the data to a file, but to no avail. - * Any improvements on not having to call external resources are welcome. - */ -class EmbedShortcodeProviderTest extends SapphireTest +class EmbedShortcodeProviderTest extends EmbedUnitTest { - - /** - * @var string test youtube. The SilverStripe Platform promotion by UncleCheese - */ - protected static $test_youtube = 'https://www.youtube.com/watch?v=dM15HfUYwF0'; - - /** - * @var string test Soundcloud. One of my favorite bands, Delain, Suckerpunch. - */ - protected static $test_soundcloud = 'http://soundcloud.com/napalmrecords/delain-suckerpunch'; - public function assertEqualIgnoringWhitespace($a, $b, $message = '') { $this->assertEquals(preg_replace('/\s+/', '', $a), preg_replace('/\s+/', '', $b), $message); } + private function getShortcodeHtml( + string $urlA, + string $urlB, + string $firstResponse, + string $secondResponse, + array $arguments + ): string { + $firstResponse = str_replace("\n", '', $firstResponse); + $secondResponse = str_replace("\n", '', $secondResponse); + $embedContainer = $this->createEmbedContainer($urlA, $urlB, $firstResponse, $secondResponse); + return EmbedShortcodeProvider::handle_shortcode($arguments, '', null, '', ['Embeddable' => $embedContainer]); + } + public function testYoutube() { - /** @var string $result */ - $result = $this->mockRequest( + $url = 'https://www.youtube.com/watch?v=dM15HfUYwF0'; + $html = $this->getShortcodeHtml( + $url, + $url, + << + EOT, + << static::$test_youtube, + 'url' => $url, 'caption' => 'A nice video', 'width' => 777, 'height' => 437, ], - [ - 'version' => '1.0', - 'provider_url' => 'https://www.youtube.com/', - 'title' => 'SilverStripe Platform 2 min introduction', - 'html' => '', - 'provider_name' => 'YouTube', - 'thumbnail_width' => 480, - 'type' => 'video', - 'thumbnail_url' => 'https://i.ytimg.com/vi/dM15HfUYwF0/hqdefault.jpg', - 'thumbnail_height' => 360, - 'width' => 480, - 'author_url' => 'https://www.youtube.com/user/SilverStripe', - 'author_name' => 'SilverStripe', - 'height' => 270, - ] ); $this->assertEqualIgnoringWhitespace( - << -

A nice video

-EOS - , - $result + <<

A nice video

+ EOT, + $html ); } public function testSoundcloud() { - /** @var string $result */ - $result = $this->mockRequest( - ['url' => static::$test_soundcloud], + $url = 'https://soundcloud.com/napalmrecords/delain-suckerpunch'; + $html = $this->getShortcodeHtml( + $url, + $url, + << + EOT, + <<","author_name":"Napalm Records","author_url":"https://soundcloud.com/napalmrecords"} + EOT, [ - 'version' => 1, - 'type' => 'rich', - 'provider_name' => 'SoundCloud', - 'provider_url' => 'http://soundcloud.com', - 'height' => 400, - 'width' => '100%', - 'title' => 'DELAIN - Suckerpunch by Napalm Records', - 'description' => 'Taken from the EP "Lunar Prelude": http://shop.napalmrecords.com/delain', - 'thumbnail_url' => 'http://i1.sndcdn.com/artworks-000143578557-af0v6l-t500x500.jpg', - 'html' => '', - 'author_name' => 'Napalm Records', - 'author_url' => 'http://soundcloud.com/napalmrecords', - ] + 'url' => $url + ], ); $this->assertEqualIgnoringWhitespace( - << -EOS - , - $result + << + EOT, + $html ); } - /** - * Mock an oembed request - * - * @param array $arguments Input arguments - * @param array $response JSON response body - * @return string - */ - protected function mockRequest($arguments, $response) + public function testVimeo() { - return EmbedShortcodeProvider::handle_shortcode( - $arguments, - '', - null, - 'embed', + $url = 'https://vimeo.com/680885625'; + $html = $this->getShortcodeHtml( + $url, + $url, + << + EOT, + <<<\/iframe>","width":640,"height":360,"duration":60,"description":"Mount Rainier was the first national park I ever visited so it was definitely exciting to be back with refined skills and better equipment. Here is a quick cap of the trip with more segments on the way.\n\nSong: And What Now of the Birds for Ben by David Jennings - March 3, 2021.","thumbnail_url":"https:\/\/i.vimeocdn.com\/video\/1380153025-d3b1840ae521cd936bdaaafaef280b9c0634e729c6b09bca7767792b553a5220-d_640","thumbnail_width":640,"thumbnail_height":360,"thumbnail_url_with_play_button":"https:\/\/i.vimeocdn.com\/filter\/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F1380153025-d3b1840ae521cd936bdaaafaef280b9c0634e729c6b09bca7767792b553a5220-d_640&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png","upload_date":"2022-02-23 08:54:15","video_id":680885625,"uri":"\/videos\/680885625"} + EOT, [ - 'resolver' => [ - 'class' => MockResolver::class, - 'config' => [ - 'expectedContent' => json_encode($response), - ], - ], - ] + 'url' => $url + ], + ); + $this->assertEqualIgnoringWhitespace( + << + EOT, + $html + ); + } + + public function testFlickr() + { + $urlA = 'https://www.flickr.com/photos/philocycler/32119532132/in/photolist-QWhZSL-DFFK9V-JcDYRD-S5ksMB-KPznfz-dT81te-2aqUUb1-Gur1ok-cgfEL1-dUu2Cv-8iqmZ9-z5ktAq-z5mCCE-9FmXnE-UH4Y1d-VZsXJn-22zGNHz-e1mzTR-22uVLSo-VJJWsE-VJJJQG-8in8np-agL5ae-9KKkAe-29if7Rt'; + $urlB = 'https://live.staticflickr.com/759/32119532132_50c3f7933f_b.jpg'; + $html = $this->getShortcodeHtml( + $urlA, + $urlB, + << + EOT, + <<\"bird\"<\/a>

Birdy

+ EOT, + $html + ); + } + + public function testAudio() + { + // not implemented in Silerstripe so will fallback to a link to $urlA + $urlA = 'https://www.someaudioplace.com/12345'; + $urlB = 'https://www.someaudioplace.com/listen/12345'; + $html = $this->getShortcodeHtml( + $urlA, + $urlB, + << + EOT, + <<"} + EOT, + [ + 'url' => $urlB, + ], + ); + $this->assertEqualIgnoringWhitespace( + << + EOT, + $html ); } diff --git a/tests/php/View/Shortcodes/MockResolver.php b/tests/php/View/Shortcodes/MockResolver.php deleted file mode 100644 index 53d2e5b5a..000000000 --- a/tests/php/View/Shortcodes/MockResolver.php +++ /dev/null @@ -1,63 +0,0 @@ -url = $url; - if (empty($config['expectedContent'])) { - throw new InvalidArgumentException("Mock resolvers need expectedContent"); - } - $this->expectedContent = $config['expectedContent']; - } - - /** - * Dispatch an url. - * - * @param Url $url - * - * @return Response - */ - public function dispatch(Url $url) - { - return new Response( - $url, - $url, - 200, - 'application/json', - $this->expectedContent, - [], - [] - ); - } - - /** - * Resolve multiple image urls at once. - * - * @param Url[] $urls - * - * @return ImageResponse[] - */ - public function dispatchImages(array $urls) - { - return []; - } -}