[FEATURE] Render additionalAttributes and data-* attr in media renderer 88/53488/11
authorMarkus Hoelzle <typo3@markus-hoelzle.de>
Fri, 14 Jul 2017 20:19:52 +0000 (22:19 +0200)
committerGeorg Ringer <georg.ringer@gmail.com>
Mon, 28 Aug 2017 19:01:53 +0000 (21:01 +0200)
Render additionalAttributes and data-* attributes in VideoTag,
YouTube, Vimeo and AudioRenderer if set in the Fluid MediaViewHelper.

Releases: master
Resolves: #81741
Change-Id: Ieef9eae905a33e09e225d3a563c3f31988a65a57
Reviewed-on: https://review.typo3.org/53488
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Joerg Boesche <typo3@joergboesche.de>
Tested-by: Joerg Boesche <typo3@joergboesche.de>
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Reviewed-by: Sascha Rademacher <sascha.rademacher+typo3@gmail.com>
Tested-by: Sascha Rademacher <sascha.rademacher+typo3@gmail.com>
Reviewed-by: Henning Liebe <h.liebe@neusta.de>
Tested-by: Henning Liebe <h.liebe@neusta.de>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
typo3/sysext/core/Classes/Resource/Rendering/AudioTagRenderer.php
typo3/sysext/core/Classes/Resource/Rendering/VideoTagRenderer.php
typo3/sysext/core/Classes/Resource/Rendering/VimeoRenderer.php
typo3/sysext/core/Classes/Resource/Rendering/YouTubeRenderer.php
typo3/sysext/core/Documentation/Changelog/master/Feature-81741-AudioVideoYouTubeVimeoAdditionalAttributes.rst [new file with mode: 0644]
typo3/sysext/core/Tests/Unit/Resource/Rendering/AudioTagRendererTest.php
typo3/sysext/core/Tests/Unit/Resource/Rendering/VideoTagRendererTest.php
typo3/sysext/core/Tests/Unit/Resource/Rendering/VimeoRendererTest.php
typo3/sysext/core/Tests/Unit/Resource/Rendering/YouTubeRendererTest.php

index 0d5ba40..44cfd18 100644 (file)
@@ -16,6 +16,7 @@ namespace TYPO3\CMS\Core\Resource\Rendering;
 
 use TYPO3\CMS\Core\Resource\FileInterface;
 use TYPO3\CMS\Core\Resource\FileReference;
 
 use TYPO3\CMS\Core\Resource\FileInterface;
 use TYPO3\CMS\Core\Resource\FileReference;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * Class AudioTagRenderer
 
 /**
  * Class AudioTagRenderer
@@ -76,6 +77,15 @@ class AudioTagRenderer implements FileRendererInterface
         }
 
         $additionalAttributes = [];
         }
 
         $additionalAttributes = [];
+        if (is_array($options['additionalAttributes'])) {
+            $additionalAttributes[] = GeneralUtility::implodeAttributes($options['additionalAttributes'], true, true);
+        }
+        if (is_array($options['data'])) {
+            array_walk($options['data'], function (&$value, $key) {
+                $value = 'data-' . htmlspecialchars($key) . '="' . htmlspecialchars($value) . '"';
+            });
+            $additionalAttributes[] = implode(' ', $options['data']);
+        }
         if (!isset($options['controls']) || !empty($options['controls'])) {
             $additionalAttributes[] = 'controls';
         }
         if (!isset($options['controls']) || !empty($options['controls'])) {
             $additionalAttributes[] = 'controls';
         }
index 3786d7d..d779493 100644 (file)
@@ -16,6 +16,7 @@ namespace TYPO3\CMS\Core\Resource\Rendering;
 
 use TYPO3\CMS\Core\Resource\FileInterface;
 use TYPO3\CMS\Core\Resource\FileReference;
 
 use TYPO3\CMS\Core\Resource\FileInterface;
 use TYPO3\CMS\Core\Resource\FileReference;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * Class VideoTagRenderer
 
 /**
  * Class VideoTagRenderer
@@ -76,6 +77,15 @@ class VideoTagRenderer implements FileRendererInterface
         }
 
         $attributes = [];
         }
 
         $attributes = [];
+        if (is_array($options['additionalAttributes'])) {
+            $attributes[] = GeneralUtility::implodeAttributes($options['additionalAttributes'], true, true);
+        }
+        if (is_array($options['data'])) {
+            array_walk($options['data'], function (&$value, $key) {
+                $value = 'data-' . htmlspecialchars($key) . '="' . htmlspecialchars($value) . '"';
+            });
+            $attributes[] = implode(' ', $options['data']);
+        }
         if ((int)$width > 0) {
             $attributes[] = 'width="' . (int)$width . '"';
         }
         if ((int)$width > 0) {
             $attributes[] = 'width="' . (int)$width . '"';
         }
index 0bafd20..8dd6aed 100644 (file)
@@ -19,6 +19,7 @@ use TYPO3\CMS\Core\Resource\FileInterface;
 use TYPO3\CMS\Core\Resource\FileReference;
 use TYPO3\CMS\Core\Resource\OnlineMedia\Helpers\OnlineMediaHelperInterface;
 use TYPO3\CMS\Core\Resource\OnlineMedia\Helpers\OnlineMediaHelperRegistry;
 use TYPO3\CMS\Core\Resource\FileReference;
 use TYPO3\CMS\Core\Resource\OnlineMedia\Helpers\OnlineMediaHelperInterface;
 use TYPO3\CMS\Core\Resource\OnlineMedia\Helpers\OnlineMediaHelperRegistry;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * Vimeo renderer class
 
 /**
  * Vimeo renderer class
@@ -118,6 +119,15 @@ class VimeoRenderer implements FileRendererInterface
         $src = sprintf('https://player.vimeo.com/video/%s?%s', $videoId, implode('&amp;', $urlParams));
 
         $attributes = ['allowfullscreen'];
         $src = sprintf('https://player.vimeo.com/video/%s?%s', $videoId, implode('&amp;', $urlParams));
 
         $attributes = ['allowfullscreen'];
+        if (is_array($options['additionalAttributes'])) {
+            $attributes[] = GeneralUtility::implodeAttributes($options['additionalAttributes'], true, true);
+        }
+        if (is_array($options['data'])) {
+            array_walk($options['data'], function (&$value, $key) {
+                $value = 'data-' . htmlspecialchars($key) . '="' . htmlspecialchars($value) . '"';
+            });
+            $attributes[] = implode(' ', $options['data']);
+        }
         if ((int)$width > 0) {
             $attributes[] = 'width="' . (int)$width . '"';
         }
         if ((int)$width > 0) {
             $attributes[] = 'width="' . (int)$width . '"';
         }
index d4d2c40..1b3593c 100644 (file)
@@ -133,6 +133,15 @@ class YouTubeRenderer implements FileRendererInterface
         );
 
         $attributes = ['allowfullscreen'];
         );
 
         $attributes = ['allowfullscreen'];
+        if (is_array($options['additionalAttributes'])) {
+            $attributes[] = GeneralUtility::implodeAttributes($options['additionalAttributes'], true, true);
+        }
+        if (is_array($options['data'])) {
+            array_walk($options['data'], function (&$value, $key) {
+                $value = 'data-' . htmlspecialchars($key) . '="' . htmlspecialchars($value) . '"';
+            });
+            $attributes[] = implode(' ', $options['data']);
+        }
         if ((int)$width > 0) {
             $attributes[] = 'width="' . (int)$width . '"';
         }
         if ((int)$width > 0) {
             $attributes[] = 'width="' . (int)$width . '"';
         }
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-81741-AudioVideoYouTubeVimeoAdditionalAttributes.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-81741-AudioVideoYouTubeVimeoAdditionalAttributes.rst
new file mode 100644 (file)
index 0000000..30b36c1
--- /dev/null
@@ -0,0 +1,29 @@
+.. include:: ../../Includes.txt
+
+===============================================================================================
+Feature: #81741 - Render additional and data-* attributes in media renderer for MediaViewHelper
+===============================================================================================
+
+See :issue:`81741`
+
+Description
+===========
+
+Render additionalAttributes and data-* attributes in Audio-, VideoTag, YouTube, Vimeo and
+if set in the Fluid MediaViewHelper.
+
+Basic Usage
+===========
+
+.. code-block:: html
+
+   <f:media additionalAttributes="{parameter:'argument'}" data="{src:'test'}"/>
+
+Example Output
+==============
+
+.. code-block:: html
+
+   <video controls data-src="test" parameter="argument">[...]</video>
+
+.. index:: Fluid, Frontend
index 88849d7..78df84b 100644 (file)
@@ -91,6 +91,22 @@ class AudioTagRendererTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
                 '//:path/myAudioFile',
                 ['controls' => 1, 'controlsList' => 'nodownload'],
                 '<audio controls controlsList="nodownload"><source src="//:path/myAudioFile" type="audio/mpeg"></audio>',
                 '//:path/myAudioFile',
                 ['controls' => 1, 'controlsList' => 'nodownload'],
                 '<audio controls controlsList="nodownload"><source src="//:path/myAudioFile" type="audio/mpeg"></audio>',
+            ],
+            [
+                '//:path/myAudioFile',
+                ['additionalAttributes' => ['muted' => 'muted', 'foo' => 'bar']],
+                '<audio muted="muted" foo="bar" controls><source src="//:path/myAudioFile" type="audio/mpeg"></audio>',
+            ],
+            [
+                '//:path/myAudioFile',
+                ['data' => ['js-required' => 'yes', 'custom-id' => 'audio-123']],
+                '<audio data-js-required="yes" data-custom-id="audio-123" controls><source src="//:path/myAudioFile" type="audio/mpeg"></audio>',
+            ]
+            ,
+            [
+                '//:path/myAudioFile',
+                ['data' => ['js-required' => 'yes', 'custom-id' => 'audio-123'], 'additionalAttributes' => ['muted' => 'muted', 'foo' => 'bar']],
+                '<audio muted="muted" foo="bar" data-js-required="yes" data-custom-id="audio-123" controls><source src="//:path/myAudioFile" type="audio/mpeg"></audio>',
             ]
         ];
     }
             ]
         ];
     }
index dac48ca..306a383 100644 (file)
@@ -94,6 +94,16 @@ class VideoTagRendererTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCas
                 '//:path/myVideoFile',
                 ['controls' => 1, 'controlsList' => 'nodownload'],
                 '<video width="300" height="200" controls controlsList="nodownload"><source src="//:path/myVideoFile" type="video/mp4"></video>',
                 '//:path/myVideoFile',
                 ['controls' => 1, 'controlsList' => 'nodownload'],
                 '<video width="300" height="200" controls controlsList="nodownload"><source src="//:path/myVideoFile" type="video/mp4"></video>',
+            ],
+            [
+                '//:path/myVideoFile',
+                ['additionalAttributes' => ['muted' => 'muted', 'foo' => 'bar']],
+                '<video muted="muted" foo="bar" width="300" height="200" controls><source src="//:path/myVideoFile" type="video/mp4"></video>',
+            ],
+            [
+                '//:path/myVideoFile',
+                ['data' => ['js-required' => 'yes', 'custom-id' => 'video-123']],
+                '<video data-js-required="yes" data-custom-id="video-123" width="300" height="200" controls><source src="//:path/myVideoFile" type="video/mp4"></video>',
             ]
         ];
     }
             ]
         ];
     }
index 894da57..923a676 100644 (file)
@@ -155,4 +155,46 @@ class VimeoRendererTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
             $this->subject->render($fileResourceMock, '300m', '200', ['autoplay' => 1])
         );
     }
             $this->subject->render($fileResourceMock, '300m', '200', ['autoplay' => 1])
         );
     }
+
+    /**
+     * @test
+     */
+    public function renderOutputWithAdditionalAttributes()
+    {
+        /** @var File|\PHPUnit_Framework_MockObject_MockObject $fileResourceMock */
+        $fileResourceMock = $this->createMock(File::class);
+
+        $this->assertSame(
+            '<iframe src="https://player.vimeo.com/video/7331?title=0&amp;byline=0&amp;portrait=0" allowfullscreen foo="bar" custom-play="preload" width="300" height="200"></iframe>',
+            $this->subject->render($fileResourceMock, '300m', '200', ['additionalAttributes' => ['foo' => 'bar', 'custom-play' => 'preload']])
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function renderOutputWithDataAttributesForCustomization()
+    {
+        /** @var File|\PHPUnit_Framework_MockObject_MockObject $fileResourceMock */
+        $fileResourceMock = $this->createMock(File::class);
+
+        $this->assertSame(
+            '<iframe src="https://player.vimeo.com/video/7331?title=0&amp;byline=0&amp;portrait=0" allowfullscreen data-player-handler="vimeo" data-custom-playerId="player-123" width="300" height="200"></iframe>',
+            $this->subject->render($fileResourceMock, '300m', '200', ['data' => ['player-handler' => 'vimeo', 'custom-playerId' => 'player-123']])
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function renderOutputWithCombinationOfDataAndAdditionalAttributes()
+    {
+        /** @var File|\PHPUnit_Framework_MockObject_MockObject $fileResourceMock */
+        $fileResourceMock = $this->createMock(File::class);
+
+        $this->assertSame(
+            '<iframe src="https://player.vimeo.com/video/7331?title=0&amp;byline=0&amp;portrait=0" allowfullscreen foo="bar" custom-play="preload" data-player-handler="vimeo" data-custom-playerId="player-123" width="300" height="200"></iframe>',
+            $this->subject->render($fileResourceMock, '300m', '200', ['data' => ['player-handler' => 'vimeo', 'custom-playerId' => 'player-123'], 'additionalAttributes' => ['foo' => 'bar', 'custom-play' => 'preload']])
+        );
+    }
 }
 }
index de31b01..14d8e52 100644 (file)
@@ -243,4 +243,46 @@ class YouTubeRendererTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
             $this->subject->render($fileResourceMock, '300m', '200', ['relatedVideos' => 0])
         );
     }
             $this->subject->render($fileResourceMock, '300m', '200', ['relatedVideos' => 0])
         );
     }
+
+    /**
+     * @test
+     */
+    public function renderOutputWithAdditionalAttributes()
+    {
+        /** @var File|\PHPUnit_Framework_MockObject_MockObject $fileResourceMock */
+        $fileResourceMock = $this->createMock(File::class);
+
+        $this->assertSame(
+            '<iframe src="https://www.youtube.com/embed/7331?autohide=1&amp;controls=0&amp;enablejsapi=1&amp;origin=http%3A%2F%2Ftest.server.org&amp;showinfo=0" allowfullscreen foo="bar" custom-play="preload" width="300" height="200"></iframe>',
+            $this->subject->render($fileResourceMock, '300m', '200', ['controls' => 0, 'additionalAttributes' => ['foo' => 'bar', 'custom-play' => 'preload']])
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function renderOutputWithDataAttributesForCustomization()
+    {
+        /** @var File|\PHPUnit_Framework_MockObject_MockObject $fileResourceMock */
+        $fileResourceMock = $this->createMock(File::class);
+
+        $this->assertSame(
+            '<iframe src="https://www.youtube.com/embed/7331?autohide=1&amp;controls=0&amp;enablejsapi=1&amp;origin=http%3A%2F%2Ftest.server.org&amp;showinfo=0" allowfullscreen data-player-handler="youTube" data-custom-playerId="player-123" width="300" height="200"></iframe>',
+            $this->subject->render($fileResourceMock, '300m', '200', ['controls' => 0, 'data' => ['player-handler' => 'youTube', 'custom-playerId' => 'player-123']])
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function renderOutputWithCombinationOfDataAndAdditionalAttributes()
+    {
+        /** @var File|\PHPUnit_Framework_MockObject_MockObject $fileResourceMock */
+        $fileResourceMock = $this->createMock(File::class);
+
+        $this->assertSame(
+            '<iframe src="https://www.youtube.com/embed/7331?autohide=1&amp;controls=0&amp;enablejsapi=1&amp;origin=http%3A%2F%2Ftest.server.org&amp;showinfo=0" allowfullscreen foo="bar" custom-play="preload" data-player-handler="youTube" data-custom-playerId="player-123" width="300" height="200"></iframe>',
+            $this->subject->render($fileResourceMock, '300m', '200', ['controls' => 0, 'data' => ['player-handler' => 'youTube', 'custom-playerId' => 'player-123'], 'additionalAttributes' => ['foo' => 'bar', 'custom-play' => 'preload']])
+        );
+    }
 }
 }