[FEATURE] Add force absolute image URL 82/41682/10
authorHelmut Hummel <helmut.hummel@typo3.org>
Sat, 18 Jul 2015 15:21:54 +0000 (18:21 +0300)
committerHelmut Hummel <helmut.hummel@typo3.org>
Mon, 5 Oct 2015 17:31:43 +0000 (19:31 +0200)
Adds a new parameter to ImageViewHelper to force
an absolute URL for image path.

Resolves: #64286
Releases: master
Change-Id: I16a38fa4565d251a7ea953cd58f73efa2c4ed12f
Reviewed-on: http://review.typo3.org/41682
Reviewed-by: Frans Saris <franssaris@gmail.com>
Tested-by: Frans Saris <franssaris@gmail.com>
Reviewed-by: Helmut Hummel <helmut.hummel@typo3.org>
Tested-by: Helmut Hummel <helmut.hummel@typo3.org>
typo3/sysext/core/Documentation/Changelog/master/Feature-64286-AddedAbsoluteUrlOptionToUriimageAndImageViewHelper.rst [new file with mode: 0644]
typo3/sysext/extbase/Classes/Service/ImageService.php
typo3/sysext/extbase/Tests/Unit/Service/ImageScriptServiceTest.php
typo3/sysext/fluid/Classes/ViewHelpers/ImageViewHelper.php
typo3/sysext/fluid/Classes/ViewHelpers/Uri/ImageViewHelper.php

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-64286-AddedAbsoluteUrlOptionToUriimageAndImageViewHelper.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-64286-AddedAbsoluteUrlOptionToUriimageAndImageViewHelper.rst
new file mode 100644 (file)
index 0000000..8e840ba
--- /dev/null
@@ -0,0 +1,28 @@
+=============================================================================
+Feature: #64286 - Added absolute url option to uri.image and image viewHelper
+=============================================================================
+
+Description
+===========
+
+The ImageViewhelper and Uri/ImageViewHelper got an new option ``absolute``. With this option you are able to force
+the ViewHelpers to output an absolute url.
+
+Examples:
+---------
+
+.. code-block:: html
+
+    <code title="ImageViewHelper">
+        <f:image image="{file}" width="400" height="375" absolute="1" />
+    </code>
+    <output>
+        <img alt="alt set in image record" src="http://www.mydomain.com/fileadmin/_processed_/323223424.png" width="400" height="375" />
+    </output>
+
+    <code title="Uri/ImageViewHelper">
+        <f:uri.image image="{file}" width="400" height="375" absolute="1" />
+    </code>
+    <output>
+        http://www.mydomain.com/fileadmin/_processed_/323223424.png
+    </output>
\ No newline at end of file
index ede1b94..bcddc39 100644 (file)
@@ -74,14 +74,15 @@ class ImageService implements \TYPO3\CMS\Core\SingletonInterface {
         * Get public url of image depending on the environment
         *
         * @param FileInterface $image
+        * @param bool|FALSE $absolute Force absolute URL
         * @return string
         * @api
         */
-       public function getImageUri(FileInterface $image) {
+       public function getImageUri(FileInterface $image, $absolute = FALSE) {
                $imageUrl = $image->getPublicUrl();
-
-               // no prefix in case of an already fully qualified URL (having a schema)
-               if (parse_url($imageUrl, PHP_URL_HOST) !== NULL) {
+               $parsedUrl = parse_url($imageUrl);
+               // no prefix in case of an already fully qualified URL
+               if (isset($parsedUrl['host'])) {
                        $uriPrefix = '';
                } elseif ($this->environmentService->isEnvironmentInFrontendMode()) {
                        $uriPrefix = $GLOBALS['TSFE']->absRefPrefix;
@@ -89,7 +90,16 @@ class ImageService implements \TYPO3\CMS\Core\SingletonInterface {
                        $uriPrefix = GeneralUtility::getIndpEnv('TYPO3_SITE_PATH');
                }
 
-               return $uriPrefix . $imageUrl;
+               if ($absolute) {
+                       // If full URL has no scheme we add the same scheme as used by the site
+                       // so we have an absolute URL also usable outside of browser scope (e.g. in an email message)
+                       if (isset($parsedUrl['host']) && !isset($parsedUrl['scheme'])) {
+                               $uriPrefix = (GeneralUtility::getIndpEnv('TYPO3_SSL') ? 'https:' : 'http:') . $uriPrefix;
+                       }
+                       return GeneralUtility::locationHeaderUrl($uriPrefix . $imageUrl);
+               } else {
+                       return $uriPrefix . $imageUrl;
+               }
        }
 
        /**
index 44a0525..bc15dd2 100644 (file)
@@ -17,6 +17,7 @@ namespace TYPO3\CMS\Extbase\Tests\Unit\Service;
 use TYPO3\CMS\Core\Resource\File;
 use TYPO3\CMS\Core\Resource\FileReference;
 use TYPO3\CMS\Core\Resource\ProcessedFile;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Extbase\Service\EnvironmentService;
 use TYPO3\CMS\Extbase\Service\ImageService;
 
@@ -42,6 +43,8 @@ class ImageServiceTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                $this->subject = new ImageService();
                $this->environmentService = $this->getMock(EnvironmentService::class);
                $this->inject($this->subject, 'environmentService', $this->environmentService);
+               GeneralUtility::flushInternalRuntimeCaches();
+               $_SERVER['HTTP_HOST'] = 'foo.bar';
        }
 
        /**
@@ -83,4 +86,30 @@ class ImageServiceTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
                $this->assertSame($expected, $this->subject->getImageUri($file));
        }
 
+       /**
+        * @return array
+        */
+       public function prefixIsCorrectlyAppliedToGetImageUriWithAbsolutePathDataProvider() {
+               return array(
+                       'with scheme' => array('http://foo.bar/img.jpg', 'http://foo.bar/img.jpg'),
+                       'scheme relative' => array('//foo.bar/img.jpg', 'http://foo.bar/img.jpg'),
+                       'without scheme' => array('foo.bar/img.jpg', 'http://foo.bar/prefix/foo.bar/img.jpg'),
+               );
+       }
+
+       /**
+        * @test
+        * @dataProvider prefixIsCorrectlyAppliedToGetImageUriWithAbsolutePathDataProvider
+        */
+       public function prefixIsCorrectlyAppliedToGetImageUriWithForcedAbsoluteUrl($imageUri, $expected) {
+               $this->environmentService->expects($this->any())->method('isEnvironmentInFrontendMode')->willReturn(TRUE);
+               $GLOBALS['TSFE'] = new \stdClass();
+               $GLOBALS['TSFE']->absRefPrefix = '/prefix/';
+
+               $file = $this->getMock(File::class, array(), array(), '', FALSE);
+               $file->expects($this->once())->method('getPublicUrl')->willReturn($imageUri);
+
+               $this->assertSame($expected, $this->subject->getImageUri($file, TRUE));
+       }
+
 }
index cc14713..ed19dba 100644 (file)
@@ -94,11 +94,12 @@ class ImageViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractTagBasedV
         * @param bool $treatIdAsReference given src argument is a sys_file_reference record
         * @param FileInterface|AbstractFileFolder $image a FAL object
         * @param string|bool $crop overrule cropping of image (setting to FALSE disables the cropping set in FileReference)
+        * @param bool $absolute Force absolute URL
         *
         * @throws \TYPO3\CMS\Fluid\Core\ViewHelper\Exception
         * @return string Rendered tag
         */
-       public function render($src = NULL, $width = NULL, $height = NULL, $minWidth = NULL, $minHeight = NULL, $maxWidth = NULL, $maxHeight = NULL, $treatIdAsReference = FALSE, $image = NULL, $crop = NULL) {
+       public function render($src = NULL, $width = NULL, $height = NULL, $minWidth = NULL, $minHeight = NULL, $maxWidth = NULL, $maxHeight = NULL, $treatIdAsReference = FALSE, $image = NULL, $crop = NULL, $absolute = FALSE) {
                if (is_null($src) && is_null($image) || !is_null($src) && !is_null($image)) {
                        throw new \TYPO3\CMS\Fluid\Core\ViewHelper\Exception('You must either specify a string src or a File object.', 1382284106);
                }
@@ -116,7 +117,7 @@ class ImageViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractTagBasedV
                        'crop' => $crop,
                );
                $processedImage = $this->imageService->applyProcessingInstructions($image, $processingInstructions);
-               $imageUri = $this->imageService->getImageUri($processedImage);
+               $imageUri = $this->imageService->getImageUri($processedImage, $absolute);
 
                $this->tag->addAttribute('src', $imageUri);
                $this->tag->addAttribute('width', $processedImage->getProperty('width'));
index 7358374..4c56025 100644 (file)
@@ -79,10 +79,11 @@ class ImageViewHelper extends AbstractViewHelper  implements CompilableInterface
         * @param int $maxHeight maximum height of the image
         * @param bool $treatIdAsReference given src argument is a sys_file_reference record
         * @param string|bool $crop overrule cropping of image (setting to FALSE disables the cropping set in FileReference)
+        * @param bool $absolute Force absolute URL
         * @throws Exception
         * @return string path to the image
         */
-       public function render($src = NULL, $image = NULL, $width = NULL, $height = NULL, $minWidth = NULL, $minHeight = NULL, $maxWidth = NULL, $maxHeight = NULL, $treatIdAsReference = FALSE, $crop = NULL) {
+       public function render($src = NULL, $image = NULL, $width = NULL, $height = NULL, $minWidth = NULL, $minHeight = NULL, $maxWidth = NULL, $maxHeight = NULL, $treatIdAsReference = FALSE, $crop = NULL, $absolute = FALSE) {
                return self::renderStatic(
                        array(
                                'src' => $src,
@@ -95,6 +96,7 @@ class ImageViewHelper extends AbstractViewHelper  implements CompilableInterface
                                'maxHeight' => $maxHeight,
                                'treatIdAsReference' => $treatIdAsReference,
                                'crop' => $crop,
+                               'absolute' => $absolute,
                        ),
                        $this->buildRenderChildrenClosure(),
                        $this->renderingContext
@@ -106,12 +108,14 @@ class ImageViewHelper extends AbstractViewHelper  implements CompilableInterface
         * @param callable $renderChildrenClosure
         * @param RenderingContextInterface $renderingContext
         * @return string
+        * @throws Exception
         */
        static public function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) {
                $src = $arguments['src'];
                $image = $arguments['image'];
                $treatIdAsReference = $arguments['treatIdAsReference'];
                $crop = $arguments['crop'];
+               $absolute = $arguments['absolute'];
 
                if (is_null($src) && is_null($image) || !is_null($src) && !is_null($image)) {
                        throw new Exception('You must either specify a string src or a File object.', 1382284105);
@@ -134,7 +138,7 @@ class ImageViewHelper extends AbstractViewHelper  implements CompilableInterface
                        'crop' => $crop,
                );
                $processedImage = $imageService->applyProcessingInstructions($image, $processingInstructions);
-               return $imageService->getImageUri($processedImage);
+               return $imageService->getImageUri($processedImage, $absolute);
        }
 
        /**
@@ -148,4 +152,4 @@ class ImageViewHelper extends AbstractViewHelper  implements CompilableInterface
                return $objectManager->get(ImageService::class);
        }
 
-}
\ No newline at end of file
+}