[BUGFIX] Regenerate missing RTE magic image on rendering 84/27884/15
authorStanislas Rolland <typo3@sjbr.ca>
Wed, 26 Feb 2014 20:55:00 +0000 (15:55 -0500)
committerStanislas Rolland <typo3@sjbr.ca>
Wed, 19 Mar 2014 19:51:09 +0000 (20:51 +0100)
Problem: Magic images inserted in RTE content may be missing,
for instance after flushing the _processed_ directory.
Solution: Regenerate any missing magic image when rendering the content
element.

Revolves: #56147
Releases: 6.2
Change-Id: Ifa156791bcd1c446c7ae61888465bb680abdf36d
Reviewed-on: https://review.typo3.org/27884
Reviewed-by: Frans Saris
Tested-by: Frans Saris
Reviewed-by: Fabien Udriot
Tested-by: Fabien Udriot
Reviewed-by: Wouter Wolters
Reviewed-by: Stanislas Rolland
Tested-by: Stanislas Rolland
typo3/sysext/core/Classes/Html/RteHtmlParser.php
typo3/sysext/core/Classes/Resource/Service/MagicImageService.php
typo3/sysext/rtehtmlarea/Classes/Controller/ImageRenderingController.php [new file with mode: 0644]
typo3/sysext/rtehtmlarea/Classes/SelectImage.php
typo3/sysext/rtehtmlarea/Configuration/TypoScript/ImageRendering/setup.txt [new file with mode: 0644]
typo3/sysext/rtehtmlarea/ext_localconf.php
typo3/sysext/rtehtmlarea/extensions/TYPO3Image/ext_localconf.php [deleted file]

index 37452ac..a08ce6a 100644 (file)
@@ -111,18 +111,6 @@ class RteHtmlParser extends \TYPO3\CMS\Core\Html\HtmlParser {
        public $preserveTags = '';
 
        /**
-        * Maximum width of magic images
-        * @var integer
-        */
-       protected $magicImageMaximumWidth;
-
-       /**
-        * Maximum height of magic images
-        * @var integer
-        */
-       protected $magicImageMaximumHeight;
-
-       /**
         * Initialize, setting element reference and record PID
         *
         * @param string $elRef Element reference, eg "tt_content:bodytext
@@ -379,7 +367,7 @@ class RteHtmlParser extends \TYPO3\CMS\Core\Html\HtmlParser {
                        $resourceFactory = Resource\ResourceFactory::getInstance();
                        /** @var $magicImageService Resource\Service\MagicImageService */
                        $magicImageService = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\Service\\MagicImageService');
-                       $this->setMagicImageMaximumDimensions();
+                       $magicImageService->setMagicImageMaximumDimensions($this->tsConfig);
                        foreach ($imgSplit as $k => $v) {
                                // Image found, do processing:
                                if ($k % 2) {
@@ -409,7 +397,9 @@ class RteHtmlParser extends \TYPO3\CMS\Core\Html\HtmlParser {
                                                        /** @var $originalImageFile Resource\File */
                                                        $originalImageFile = $resourceFactory->getFileObject(intval($attribArray['data-htmlarea-file-uid']));
                                                } catch (Resource\Exception\FileDoesNotExistException $fileDoesNotExistException) {
-                                                       // The file has disappeared...
+                                                       // Log the fact the file could not be retrieved.
+                                                       $message = sprintf('Could not find file with uid "%s"', $attribArray['data-htmlarea-file-uid']);
+                                                       $this->getLogger()->error($message);
                                                }
                                        }
                                        if ($originalImageFile instanceof Resource\File) {
@@ -433,9 +423,7 @@ class RteHtmlParser extends \TYPO3\CMS\Core\Html\HtmlParser {
                                                        // Magic image case: get a processed file with the requested configuration
                                                        $imageConfiguration = array(
                                                                'width' => $imgTagDimensions[0],
-                                                               'height' => $imgTagDimensions[1],
-                                                               'maxW' => $this->magicImageMaximumWidth,
-                                                               'maxH' => $this->magicImageMaximumHeight
+                                                               'height' => $imgTagDimensions[1]
                                                        );
                                                        $magicImage = $magicImageService->createMagicImage($originalImageFile, $imageConfiguration);
                                                        $attribArray['width'] = $magicImage->getProperty('width');
@@ -456,9 +444,7 @@ class RteHtmlParser extends \TYPO3\CMS\Core\Html\HtmlParser {
                                                                $fileObject = $folder->createFile($fileName)->setContents($externalFile);
                                                                $imageConfiguration = array(
                                                                        'width' => $attribArray['width'],
-                                                                       'height' => $attribArray['height'],
-                                                                       'maxW' => $this->magicImageMaximumWidth,
-                                                                       'maxH' => $this->magicImageMaximumHeight
+                                                                       'height' => $attribArray['height']
                                                                );
                                                                $magicImage = $magicImageService->createMagicImage($fileObject, $imageConfiguration);
                                                                $attribArray['width'] = $magicImage->getProperty('width');
@@ -1737,32 +1723,6 @@ class RteHtmlParser extends \TYPO3\CMS\Core\Html\HtmlParser {
        }
 
        /**
-        * Set variables for maximum dimensions of magic images
-        *
-        * @return  void
-        */
-       protected function setMagicImageMaximumDimensions() {
-               // Get maximum dimensions from the configuration of the image button
-               $buttonConfig = is_array($this->tsConfig['buttons.']) && is_array($this->tsConfig['buttons.']['image.']) ? $this->tsConfig['buttons.']['image.'] : array();
-               if (is_array($buttonConfig['options.']) && is_array($buttonConfig['options.']['magic.'])) {
-                       if ($buttonConfig['options.']['magic.']['maxWidth']) {
-                               $this->magicImageMaximumWidth = $buttonConfig['options.']['magic.']['maxWidth'];
-                       }
-                       if ($buttonConfig['options.']['magic.']['maxHeight']) {
-                               $this->magicImageMaximumHeight = $buttonConfig['options.']['magic.']['maxHeight'];
-                       }
-               }
-               // These defaults allow images to be based on their width - to a certain degree - by setting a high height.
-               // Then we're almost certain the image will be based on the width
-               if (!$this->magicImageMaximumWidth) {
-                       $this->magicImageMaximumWidth = 300;
-               }
-               if (!$this->magicImageMaximumHeight) {
-                       $this->magicImageMaximumHeight = 1000;
-               }
-       }
-
-       /**
         * Apply plain image settings to the dimensions of the image
         *
         * @param array $imageInfo: info array of the image
@@ -1792,4 +1752,15 @@ class RteHtmlParser extends \TYPO3\CMS\Core\Html\HtmlParser {
                return $attribArray;
        }
 
+       /**
+       * @return \TYPO3\CMS\Core\Log\Logger
+       */
+       protected function getLogger() {
+
+               /** @var $logManager \TYPO3\CMS\Core\Log\LogManager */
+               $logManager = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Log\\LogManager');
+
+               return $logManager->getLogger(get_class($this));
+       }
+
 }
index 325eddf..8ce4db3 100644 (file)
@@ -37,21 +37,35 @@ use TYPO3\CMS\Core\Utility\MathUtility;
 class MagicImageService {
 
        /**
+        * Maximum width of magic images
+        * These defaults allow images to be based on their width - to a certain degree - by setting a high height.
+        * Then we're almost certain the image will be based on the width
+        * @var int
+        */
+       protected $magicImageMaximumWidth = 300;
+
+       /**
+        * Maximum height of magic images
+        * @var int
+        */
+       protected $magicImageMaximumHeight = 1000;
+
+       /**
         * Creates a magic image
         *
         * @param Resource\File $imageFileObject: the original image file
-        * @param array $fileConfiguration (width, height, maxW, maxH)
+        * @param array $fileConfiguration (width, height)
         * @return Resource\ProcessedFile
         */
        public function createMagicImage(Resource\File $imageFileObject, array $fileConfiguration) {
                // Process dimensions
-               $maxWidth = MathUtility::forceIntegerInRange($fileConfiguration['width'], 0, $fileConfiguration['maxW']);
-               $maxHeight = MathUtility::forceIntegerInRange($fileConfiguration['height'], 0, $fileConfiguration['maxH']);
+               $maxWidth = MathUtility::forceIntegerInRange($fileConfiguration['width'], 0, $this->magicImageMaximumWidth);
+               $maxHeight = MathUtility::forceIntegerInRange($fileConfiguration['height'], 0, $this->magicImageMaximumHeight);
                if (!$maxWidth) {
-                       $maxWidth = $fileConfiguration['maxW'];
+                       $maxWidth = $this->magicImageMaximumWidth;
                }
                if (!$maxHeight) {
-                       $maxHeight = $fileConfiguration['maxH'];
+                       $maxHeight = $this->magicImageMaximumHeight;
                }
                // Create the magic image
                $magicImage = $imageFileObject->process(
@@ -64,4 +78,22 @@ class MagicImageService {
                return $magicImage;
        }
 
+       /**
+        * Set maximum dimensions of magic images based on RTE configuration
+        *
+        * @param array $rteConfiguration: RTE configuration probably coming from PageTSConfig
+        * @return void
+        */
+       public function setMagicImageMaximumDimensions(array $rteConfiguration) {
+               // Get maximum dimensions from the configuration of the RTE image button
+               $imageButtonConfiguration = (is_array($rteConfiguration['buttons.']) && is_array($rteConfiguration['buttons.']['image.'])) ? $rteConfiguration['buttons.']['image.'] : array();
+               if (is_array($imageButtonConfiguration['options.']) && is_array($imageButtonConfiguration['options.']['magic.'])) {
+                       if ((int) $imageButtonConfiguration['options.']['magic.']['maxWidth'] > 0) {
+                               $this->magicImageMaximumWidth = (int) $imageButtonConfiguration['options.']['magic.']['maxWidth'];
+                       }
+                       if ((int) $imageButtonConfiguration['options.']['magic.']['maxHeight'] > 0) {
+                               $this->magicImageMaximumHeight = (int) $imageButtonConfiguration['options.']['magic.']['maxHeight'];
+                       }
+               }
+       }
 }
diff --git a/typo3/sysext/rtehtmlarea/Classes/Controller/ImageRenderingController.php b/typo3/sysext/rtehtmlarea/Classes/Controller/ImageRenderingController.php
new file mode 100644 (file)
index 0000000..2d61d3f
--- /dev/null
@@ -0,0 +1,176 @@
+<?php
+namespace TYPO3\CMS\Rtehtmlarea\Controller;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2014 Stanislas Rolland <typo3(arobas)sjbr.ca>
+ *           Fabien Udriot <fabien.udriot@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the text file GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Resource;
+
+/**
+ * Render the image attributes and reconstruct magic images, if necessary (and possible)
+ */
+class ImageRenderingController extends \TYPO3\CMS\Frontend\Plugin\AbstractPlugin {
+
+       /**
+        * Same as class name
+        *
+        * @var string
+        */
+       public $prefixId = 'ImageRenderingController';
+
+       /**
+        * Path to this script relative to the extension dir
+        *
+        * @var string
+        */
+       public $scriptRelPath = 'Classes/Controller/ImageRenderingController.php';
+
+       /**
+        * The extension key
+        *
+        * @var string
+        */
+       public $extKey = 'rtehtmlarea';
+
+       /**
+        * Configuration
+        *
+        * @var array
+        */
+       public $conf = array();
+
+       /**
+        * cObj object
+        *
+        * @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
+        */
+       public $cObj;
+
+       /**
+        * Returns a processed image to be displayed on the Frontend.
+        *
+        * @param string $content Content input (not used).
+        * @param array $conf TypoScript configuration
+        * @return string HTML output
+        */
+       public function renderImageAttributes($content = '', $conf) {
+
+               $imageAttributes = $this->getImageAttributes();
+
+               // It is pretty rare to be in presence of an external image as the default behaviour
+               // of the RTE is to download the external image and create a local image.
+               // However, it may happen if the RTE has the flag "disable"
+               if (!$this->isExternalImage()) {
+                       $fileUid = (int)$imageAttributes['data-htmlarea-file-uid'];
+                       if ($fileUid) {
+                               try {
+                                       $file = Resource\ResourceFactory::getInstance()->getFileObject($fileUid);
+                                       if ($imageAttributes['src'] !== $file->getPublicUrl()) {
+                                               // Source file is a processed image
+                                               $imageConfiguration = array(
+                                                       'width' => (int)$imageAttributes['width'],
+                                                       'height' => (int)$imageAttributes['height']
+                                               );
+                                               $processedFile = $this->getMagicImageService()->createMagicImage($file, $imageConfiguration);
+                                               $additionalAttributes = array(
+                                                       'src' => $processedFile->getPublicUrl(),
+                                                       'title' => $imageAttributes['title'] ?: $file->getProperty('title'),
+                                                       'alt' => $imageAttributes['alt'] ?: $file->getProperty('alternative'),
+                                                       'width' => $processedFile->getProperty('width'),
+                                                       'height' => $processedFile->getProperty('height'),
+                                               );
+                                               $imageAttributes = array_merge($imageAttributes, $additionalAttributes);
+                                       }
+                               } catch (Resource\Exception\FileDoesNotExistException $fileDoesNotExistException) {
+                                       // Log the fact the file could not be retrieved.
+                                       $message = sprintf('I could not find file with uid "%s"', $fileUid);
+                                       $this->getLogger()->error($message);
+                               }
+                       }
+               }
+               return '<img ' . GeneralUtility::implodeAttributes($imageAttributes, TRUE, TRUE) . ' />';
+       }
+
+       /**
+        * Returns a sanitizes array of attributes out of $this->cObj
+        *
+        * @return array
+        */
+       protected function getImageAttributes() {
+               return $this->cObj->parameters;
+       }
+
+       /**
+        * Instantiates and prepares the Magic Image service.
+        *
+        * @return \TYPO3\CMS\Core\Resource\Service\MagicImageService
+        */
+       protected function getMagicImageService() {
+
+               /** @var $magicImageService Resource\Service\MagicImageService */
+               $magicImageService = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\Service\\MagicImageService');
+
+               // Get RTE configuration
+               $pageTSConfig = $this->getFrontendObject()->getPagesTSconfig();
+               if (is_array($pageTSConfig) && is_array($pageTSConfig['RTE.'])) {
+                       $magicImageService->setMagicImageMaximumDimensions($pageTSConfig['RTE.']);
+               }
+
+               return $magicImageService;
+       }
+
+       /**
+        * Tells whether the image URL is found to be "external".
+        *
+        * @return bool
+        */
+       protected function isExternalImage() {
+               $srcAbsoluteUrl = $this->cObj->parameters['src'];
+               return strtolower(substr($srcAbsoluteUrl, 0, 4)) === 'http' || substr($srcAbsoluteUrl, 0, 2) === '//';
+       }
+
+       /**
+        * @return \TYPO3\CMS\Core\Log\Logger
+        */
+       protected function getLogger() {
+
+               /** @var $logManager \TYPO3\CMS\Core\Log\LogManager */
+               $logManager = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Log\\LogManager');
+
+               return $logManager->getLogger(get_class($this));
+       }
+
+       /**
+        * Returns an instance of the Frontend object.
+        *
+        * @return \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
+        */
+       protected function getFrontendObject() {
+               return $GLOBALS['TSFE'];
+       }
+}
index 5e098c9..68bb53a 100644 (file)
@@ -76,10 +76,6 @@ class SelectImage extends \TYPO3\CMS\Recordlist\Browser\ElementBrowser {
         */
        protected $plainMaxHeight;
 
-       protected $magicMaxWidth;
-
-       protected $magicMaxHeight;
-
        protected $imgPath;
 
        public $editorNo;
@@ -225,12 +221,11 @@ class SelectImage extends \TYPO3\CMS\Recordlist\Browser\ElementBrowser {
                // Create the magic image service
                /** @var $magicImageService Resource\Service\MagicImageService */
                $magicImageService = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\Service\\MagicImageService');
+               $magicImageService->setMagicImageMaximumDimensions($this->thisConfig);
                // Create the magic image
                $imageConfiguration = array(
                        'width' => GeneralUtility::_GP('cWidth'),
-                       'height' => GeneralUtility::_GP('cHeight'),
-                       'maxW' => $this->magicMaxWidth,
-                       'maxH' => $this->magicMaxHeight
+                       'height' => GeneralUtility::_GP('cHeight')
                );
                $magicImage = $magicImageService->createMagicImage($fileObject, $imageConfiguration);
                $imageUrl = $magicImage->getPublicUrl();
@@ -848,7 +843,7 @@ class SelectImage extends \TYPO3\CMS\Recordlist\Browser\ElementBrowser {
                $this->buttonConfig = $this->getButtonConfig();
                $this->imgPath = $this->getImgPath();
                $this->defaultClass = $this->getDefaultClass();
-               $this->setMaximumImageDimensions();
+               $this->setMaximumPlainImageDimensions();
        }
 
        /**
@@ -933,11 +928,11 @@ class SelectImage extends \TYPO3\CMS\Recordlist\Browser\ElementBrowser {
        }
 
        /**
-        * Set variables for maximum image dimensions
+        * Set variables for maximum plain image dimensions
         *
         * @return      void
         */
-       protected function setMaximumImageDimensions() {
+       protected function setMaximumPlainImageDimensions() {
                if (is_array($this->buttonConfig['options.']) && is_array($this->buttonConfig['options.']['plain.'])) {
                        if ($this->buttonConfig['options.']['plain.']['maxWidth']) {
                                $this->plainMaxWidth = $this->buttonConfig['options.']['plain.']['maxWidth'];
@@ -952,21 +947,6 @@ class SelectImage extends \TYPO3\CMS\Recordlist\Browser\ElementBrowser {
                if (!$this->plainMaxHeight) {
                        $this->plainMaxHeight = 680;
                }
-               if (is_array($this->buttonConfig['options.']) && is_array($this->buttonConfig['options.']['magic.'])) {
-                       if ($this->buttonConfig['options.']['magic.']['maxWidth']) {
-                               $this->magicMaxWidth = $this->buttonConfig['options.']['magic.']['maxWidth'];
-                       }
-                       if ($this->buttonConfig['options.']['magic.']['maxHeight']) {
-                               $this->magicMaxHeight = $this->buttonConfig['options.']['magic.']['maxHeight'];
-                       }
-               }
-               // These defaults allow images to be based on their width - to a certain degree - by setting a high height. Then we're almost certain the image will be based on the width
-               if (!$this->magicMaxWidth) {
-                       $this->magicMaxWidth = 300;
-               }
-               if (!$this->magicMaxHeight) {
-                       $this->magicMaxHeight = 1000;
-               }
        }
 
        /**
diff --git a/typo3/sysext/rtehtmlarea/Configuration/TypoScript/ImageRendering/setup.txt b/typo3/sysext/rtehtmlarea/Configuration/TypoScript/ImageRendering/setup.txt
new file mode 100644 (file)
index 0000000..1b14cd3
--- /dev/null
@@ -0,0 +1,18 @@
+## TS setup for TYPO3 image rendering
+
+#******************************************************
+# Including library for processing of magic images and file abstraction attributes on img tag
+#******************************************************
+
+lib.parseFunc_RTE {
+       tags.img = TEXT
+       tags.img {
+               current = 1
+               preUserFunc = TYPO3\CMS\Rtehtmlarea\Controller\ImageRenderingController->renderImageAttributes
+       }
+       nonTypoTagStdWrap.HTMLparser.tags.img.fixAttrib {
+               allparams.unset = 1
+               data-htmlarea-file-uid.unset = 1
+               data-htmlarea-file-table.unset = 1
+       }
+}
\ No newline at end of file
index a2bcadb..e6bc6a1 100644 (file)
@@ -117,11 +117,12 @@ if ($TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['enableImages']) {
        $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['TYPO3Image']['addIconsToSkin'] = 0;
        $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['TYPO3Image']['disableInFE'] = 1;
 
-       require_once \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($_EXTKEY) . 'extensions/TYPO3Image/ext_localconf.php';
        if ($TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['defaultConfiguration'] == 'Advanced' || $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['defaultConfiguration'] == 'Typical') {
                \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPageTSConfig('<INCLUDE_TYPOSCRIPT: source="FILE:EXT:' . $_EXTKEY . '/res/image/pageTSConfig.txt">');
        }
 }
+// Add frontend image rendering TypoScript anyways
+\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScript($_EXTKEY, 'setup', '<INCLUDE_TYPOSCRIPT: source="FILE:EXT:' . $_EXTKEY . '/Configuration/TypoScript/ImageRendering/setup.txt">', 43);
 
 $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['DefaultLink'] = array();
 $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['DefaultLink']['objectReference'] = '&TYPO3\\CMS\\Rtehtmlarea\\Extension\\DefaultLink';
diff --git a/typo3/sysext/rtehtmlarea/extensions/TYPO3Image/ext_localconf.php b/typo3/sysext/rtehtmlarea/extensions/TYPO3Image/ext_localconf.php
deleted file mode 100644 (file)
index eda2d7d..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php
-if (!defined('TYPO3_MODE')) {
-       die('Access denied.');
-}
-// Extending TypoScript from static template uid=43 to set up parsing of custom file abstraction attributes on img tag
-\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScript($_EXTKEY, 'setup', '
-       #******************************************************
-       # Including library for processing of custom file abstraction attributes on img tag
-       #******************************************************
-       ##includeLibs.tx_rtehtmlarea_renderimgtag = EXT:rtehtmlarea/extensions/TYPO3Image/class.tx_rtehtmlarea_renderimgtag.php
-
-       lib.parseFunc_RTE {
-               ##tags.img = TEXT
-               ##tags.img {
-               ##      current = 1
-               ##      preUserFunc = tx_rtehtmlarea_renderimgtag->renderImgageAttributes
-               ##}
-               nonTypoTagStdWrap.HTMLparser.tags.img.fixAttrib {
-                       data-htmlarea-file-uid.unset = 1
-                       data-htmlarea-file-table.unset = 1
-               }
-       }
-', 43);