From 7d90a14f3766a0be12af30a53d464979b75ea50d Mon Sep 17 00:00:00 2001 From: Robbie Averill Date: Wed, 20 Jun 2018 11:40:28 +1200 Subject: [PATCH] NEW Shift Embeddable and EmbedResource from asset-admin, lazy load Embed to allow injected dependencies (#8194) --- .upgrade.yml | 2 +- _config/oembed.yml | 6 + src/View/Embed/EmbedResource.php | 147 ++++++++++++++++++ src/View/Embed/Embeddable.php | 53 +++++++ .../Shortcodes/EmbedShortcodeProvider.php | 11 +- tests/php/View/Embed/EmbedResourceTest.php | 65 ++++++++ 6 files changed, 282 insertions(+), 2 deletions(-) create mode 100644 _config/oembed.yml create mode 100644 src/View/Embed/EmbedResource.php create mode 100644 src/View/Embed/Embeddable.php create mode 100644 tests/php/View/Embed/EmbedResourceTest.php diff --git a/.upgrade.yml b/.upgrade.yml index 42584cb49..3b9616a95 100644 --- a/.upgrade.yml +++ b/.upgrade.yml @@ -988,7 +988,7 @@ warnings: 'HTMLEditorField_Toolbar': message: 'replaced With SilverStripe\Admin\ModalController' 'HTMLEditorField_Embed': - message: 'replaced with SilverStripe\AssetAdmin\Model\EmbedResource' + message: 'replaced with SilverStripe\View\Embed\EmbedResource' 'HTMLEditorField_File': message: 'Removed' 'HTMLEditorField_Flash': diff --git a/_config/oembed.yml b/_config/oembed.yml new file mode 100644 index 000000000..75f4bc774 --- /dev/null +++ b/_config/oembed.yml @@ -0,0 +1,6 @@ +--- +Name: coreoembed +--- +SilverStripe\Core\Injector\Injector: + SilverStripe\View\Embed\Embeddable: + class: SilverStripe\View\Embed\EmbedResource diff --git a/src/View/Embed/EmbedResource.php b/src/View/Embed/EmbedResource.php new file mode 100644 index 000000000..3f867465f --- /dev/null +++ b/src/View/Embed/EmbedResource.php @@ -0,0 +1,147 @@ +url = $url; + } + + public function getWidth() + { + return $this->getEmbed()->getWidth() ?: 100; + } + + public function getHeight() + { + return $this->getEmbed()->getHeight() ?: 100; + } + + public function getPreviewURL() + { + // Use thumbnail url + if ($this->getEmbed()->image) { + return $this->getEmbed()->image; + } + + // Use direct image type + if ($this->getType() === 'photo' && !empty($this->getEmbed()->url)) { + return $this->getEmbed()->url; + } + + // Default media + return ModuleResourceLoader::resourceURL( + 'silverstripe/asset-admin:client/dist/images/icon_file.png' + ); + } + + /** + * Get human readable name for this resource + * + * @return string + */ + public function getName() + { + if ($this->getEmbed()->title) { + return $this->getEmbed()->title; + } + + return preg_replace('/\?.*/', '', basename($this->getEmbed()->getUrl())); + } + + public function getType() + { + return $this->getEmbed()->type; + } + + public function validate() + { + return !empty($this->getEmbed()->code); + } + + /** + * @param array $options + * @return $this + */ + public function setOptions(array $options) + { + $this->options = $options; + return $this; + } + + /** + * @return array + */ + public function getOptions() + { + return $this->options; + } + + /** + * @param DispatcherInterface $dispatcher + * @return $this + */ + public function setDispatcher(DispatcherInterface $dispatcher) + { + $this->dispatcher = $dispatcher; + return $this; + } + + /** + * @return DispatcherInterface + */ + public function getDispatcher() + { + return $this->dispatcher; + } + + /** + * Returns a bootstrapped Embed object + * + * @return Adapter + */ + public function getEmbed() + { + if (!$this->embed) { + $this->embed = Embed::create($this->url, $this->getOptions(), $this->getDispatcher()); + } + return $this->embed; + } +} diff --git a/src/View/Embed/Embeddable.php b/src/View/Embed/Embeddable.php new file mode 100644 index 000000000..e274aba6d --- /dev/null +++ b/src/View/Embed/Embeddable.php @@ -0,0 +1,53 @@ +create(Embeddable::class, $serviceURL); + if (!empty($serviceArguments)) { + $embed->setOptions(array_merge($serviceArguments, (array) $embed->getOptions())); + } + // Allow resolver to be mocked $dispatcher = null; if (isset($extra['resolver'])) { @@ -68,10 +76,11 @@ class EmbedShortcodeProvider implements ShortcodeHandler $serviceURL, $extra['resolver']['config'] ); + $embed->setDispatcher($dispatcher); } // Process embed - $embed = Embed::create($serviceURL, $serviceArguments, $dispatcher); + $embed = $embed->getEmbed(); // Convert embed object into HTML if ($embed && $embed instanceof Adapter) { diff --git a/tests/php/View/Embed/EmbedResourceTest.php b/tests/php/View/Embed/EmbedResourceTest.php new file mode 100644 index 000000000..4612f8530 --- /dev/null +++ b/tests/php/View/Embed/EmbedResourceTest.php @@ -0,0 +1,65 @@ +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', + ]), + [] + ); + } +}