[!!!][FEATURE] Flash message view helper add deferred rendering 18/34818/18
authorHelmut Hummel <helmut.hummel@typo3.org>
Sun, 30 Nov 2014 15:39:32 +0000 (16:39 +0100)
committerAnja Leichsenring <aleichsenring@ab-softlab.de>
Wed, 3 Jun 2015 19:04:44 +0000 (21:04 +0200)
Deprecate renderMode in favor of a flexible deferred
rendering of flash messages in the Fluid template.

This means that flash messages should no longer contain HTML tags
but only plain text, if rendered by the default rendering.

The rendered output will by default now be a <ul> list.
The usage of renderMode in the Core is removed and styles are
adapted to match the previous output.

The core is adapted to now use htmlspecialchars in a controller context
for user input. Encoding is now taken care of during rendering of
the Fluid template.

Resolves: #63453
Releases: master
Change-Id: Ie02d2e1441ca2b3c7c159ffa917f7040f50327b5
Reviewed-on: http://review.typo3.org/34818
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
35 files changed:
typo3/sysext/beuser/Classes/Controller/PermissionController.php
typo3/sysext/beuser/Resources/Private/Layouts/Default.html
typo3/sysext/beuser/Resources/Private/Layouts/Permission.html
typo3/sysext/core/Documentation/Changelog/master/Breaking-63453-ChangedRenderingOfFlashMessagesViewHelper.rst [new file with mode: 0644]
typo3/sysext/core/Documentation/Changelog/master/Deprecation-63453-DeprecateRenderModeAttributeOfFlashMessageViewHelper.rst [new file with mode: 0644]
typo3/sysext/core/Documentation/Changelog/master/Feature-63453-TemplateSupportForFlashMessagesViewHelper.rst [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Templates/Content/Edit.html
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Templates/Content/List.html
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Templates/Content/New.html
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Resources/Private/Templates/Content/Show.html
typo3/sysext/documentation/Classes/Controller/DocumentController.php
typo3/sysext/documentation/Resources/Private/Layouts/Default.html
typo3/sysext/extensionmanager/Classes/Controller/ActionController.php
typo3/sysext/extensionmanager/Classes/Controller/DownloadController.php
typo3/sysext/extensionmanager/Classes/Controller/ListController.php
typo3/sysext/extensionmanager/Classes/Controller/UploadExtensionFileController.php
typo3/sysext/extensionmanager/Classes/Utility/DownloadUtility.php
typo3/sysext/extensionmanager/Classes/Utility/Parser/ExtensionXmlPullParser.php
typo3/sysext/extensionmanager/Classes/Utility/Parser/ExtensionXmlPushParser.php
typo3/sysext/extensionmanager/Classes/Utility/Parser/MirrorXmlPullParser.php
typo3/sysext/extensionmanager/Classes/Utility/Parser/MirrorXmlPushParser.php
typo3/sysext/extensionmanager/Classes/Utility/Repository/Helper.php
typo3/sysext/extensionmanager/Resources/Private/Templates/Distribution/Show.html
typo3/sysext/extensionmanager/Resources/Private/Templates/List/Distributions.html
typo3/sysext/extensionmanager/Resources/Private/Templates/List/Index.html
typo3/sysext/extensionmanager/Resources/Private/Templates/List/UnresolvedDependencies.html
typo3/sysext/fluid/Classes/ViewHelpers/FlashMessagesViewHelper.php
typo3/sysext/indexed_search/Resources/Private/Templates/Administration/StatisticDetails.html
typo3/sysext/lang/Resources/Private/Templates/Language/ListLanguages.html
typo3/sysext/lang/Resources/Private/Templates/Language/ListTranslations.html
typo3/sysext/lowlevel/Resources/Private/Templates/Backend/Configuration.html
typo3/sysext/recycler/Resources/Private/Layouts/Default.html
typo3/sysext/reports/Resources/Private/Layouts/Default.html
typo3/sysext/workspaces/Resources/Private/Layouts/Module.html
typo3/sysext/workspaces/Resources/Private/Layouts/Nodoc.html

index 3d613fa..88dfa4a 100644 (file)
@@ -120,8 +120,8 @@ class PermissionController extends ActionController {
                if ($this->getBackendUser()->workspace != 0) {
                        // Adding section with the permission setting matrix:
                        $this->addFlashMessage(
-                               LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarningText', 'beuser'),
-                               LocalizationUtility::translate('LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarning', 'beuser'),
+                               'LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarningText',
+                               'LLL:EXT:beuser/Resources/Private/Language/locallang_mod_permission.xlf:WorkspaceWarning',
                                FlashMessage::WARNING
                        );
                }
index c691e8b..28bfc82 100644 (file)
@@ -26,7 +26,7 @@
                        <div id="typo3-inner-docbody">
                                <f:render section="headline" />
 
-                               <f:flashMessages renderMode="div" />
+                               <f:flashMessages />
 
                                <f:render section="content" />
                        </div>
index 604545f..da2918a 100644 (file)
                        <div id="typo3-inner-docbody">
                                <f:render section="headline" />
 
-                               <f:flashMessages renderMode="div" />
+                               <f:flashMessages as="flashMessages">
+                                       <ul class="typo3-flashMessages">
+                                               <f:for each="{flashMessages}" as="flashMessage">
+                                                       <li class="alert {flashMessage.class}">
+                                                               <h4><f:translate id="{flashMessage.title}" extensionName="beuser" /></h4>
+                                                               <f:translate id="{flashMessage.message}" extensionName="beuser" />
+                                                       </li>
+                                               </f:for>
+                                       </ul>
+                               </f:flashMessages>
 
                                <f:render section="content" />
                        </div>
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-63453-ChangedRenderingOfFlashMessagesViewHelper.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-63453-ChangedRenderingOfFlashMessagesViewHelper.rst
new file mode 100644 (file)
index 0000000..70734ec
--- /dev/null
@@ -0,0 +1,40 @@
+===============================================================
+Breaking: #63453 - Changed rendering of FlashMessagesViewHelper
+===============================================================
+
+Description
+===========
+
+The default (``renderMode="ul"``) rendering output of the ``FlashMessagesViewHelper`` has been changed.
+
+By default the view helper rendered an unordered list, each list item containing one message.
+This output has been adjusted and more markup is added.
+
+
+Impact
+======
+
+You may see unexpected formatting of flash messages.
+
+
+Affected Installations
+======================
+
+Any template using the ``FlashMessagesViewHelper`` unless the attribute ``renderMode`` is set to "div".
+Be aware, though, that the ``renderMode`` attribute is deprecated.
+
+
+Migration
+=========
+
+Add a custom rendering template for the flash messages, like outlined in the example, to obtain the same output as before.
+
+.. code-block:: html
+
+       <f:flashMessages as="flashMessages">
+               <ul class="myFlashMessages">
+                       <f:for each="{flashMessages}" as="flashMessage">
+                               <li>{flashMessage.message}</li>
+                       </f:for>
+               </ul>
+       </f:flashMessages>
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-63453-DeprecateRenderModeAttributeOfFlashMessageViewHelper.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-63453-DeprecateRenderModeAttributeOfFlashMessageViewHelper.rst
new file mode 100644 (file)
index 0000000..2d68476
--- /dev/null
@@ -0,0 +1,40 @@
+===============================================================================
+Deprecation: #63453 - Deprecate renderMode attribute of FlashMessagesViewHelper
+===============================================================================
+
+Description
+===========
+
+Deprecated renderMode in favor of a flexible deferred rendering of flash messages in the Fluid template.
+This means that flash messages should no longer contain HTML, but the HTML output can and should be adjusted in the Fluid template.
+
+
+Impact
+======
+
+Using renderMode on FlashMessage output will throw a deprecation warning.
+
+
+Affected Installations
+======================
+
+All instances using the renderMode attribute in FlashMessage output.
+
+
+Migration
+=========
+
+Adjust flash messages to contain only plain text and remove the renderMode attribute in the output Templates.
+
+.. code-block:: html
+
+       <f:flashMessages as="flashMessages">
+               <ul class="typo3-flashMessages">
+                       <f:for each="{flashMessages}" as="flashMessage">
+                               <li class="alert {flashMessage.class}">
+                                       <h4>{flashMessage.title}</h4>
+                                       {flashMessage.message}
+                               </li>
+                       </f:for>
+               </ul>
+       </f:flashMessages>
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-63453-TemplateSupportForFlashMessagesViewHelper.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-63453-TemplateSupportForFlashMessagesViewHelper.rst
new file mode 100644 (file)
index 0000000..4124305
--- /dev/null
@@ -0,0 +1,27 @@
+==============================================================
+Feature: #63453 - Template support for FlashMessagesViewHelper
+==============================================================
+
+Description
+===========
+
+Template support for ``FlashMessagesViewHelper`` has been added.
+This allows to define a custom rendering for flash messages.
+
+The new attribute ``as`` for the ``FlashMessagesViewHelper`` allows to specify a variable name,
+which can be used within the view helper's child elements to access the flash messages.
+
+Example usage:
+
+.. code-block:: html
+
+       <f:flashMessages as="flashMessages">
+               <ul class="myFlashMessages">
+                       <f:for each="{flashMessages}" as="flashMessage">
+                               <li class="alert {flashMessage.class}">
+                                       <h4>{flashMessage.title}</h4>
+                                       <span class="fancy-icon">{flashMessage.message}</span>
+                               </li>
+                       </f:for>
+               </ul>
+       </f:flashMessages>
index bb2d188..21b6c04 100644 (file)
@@ -15,7 +15,7 @@ Otherwise your changes will be overwritten the next time you save the extension
 <f:section name="main">
 <h1>Edit Content</h1>
 
-<f:flashMessages renderMode="div" />
+<f:flashMessages />
 
 <f:render partial="FormErrors" arguments="{object:Content}" />
 
index bcba1b1..996a16f 100644 (file)
@@ -15,7 +15,7 @@ Otherwise your changes will be overwritten the next time you save the extension
 <f:section name="main">
 <h1>Listing for Content</h1>
 
-<f:flashMessages renderMode="div" />
+<f:flashMessages />
 
 <table  class="tx_irretutorial" >
        <tr>
index 64f19c6..9b8feb5 100644 (file)
@@ -15,7 +15,7 @@ Otherwise your changes will be overwritten the next time you save the extension
 <f:section name="main">
 <h1>New Content</h1>
 
-<f:flashMessages renderMode="div" />
+<f:flashMessages />
 
 <f:render partial="FormErrors" arguments="{object:Content}" />
 
index dfb338e..98c18ea 100644 (file)
@@ -16,7 +16,7 @@ Otherwise your changes will be overwritten the next time you save the extension
 <h1>Single View for Content</h1>
 <f:debug>{content}</f:debug>
 
-<f:flashMessages renderMode="div" />
+<f:flashMessages />
 <f:render partial="Content/Properties" arguments="{content:content}" />
 <f:link.action action="list">Back to list</f:link.action><br />
 <f:link.action action="new">New Content</f:link.action>
index 1c04815..57784c9 100644 (file)
@@ -149,23 +149,17 @@ class DocumentController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControl
                $language = $this->languageUtility->getDocumentationLanguage();
                try {
                        $result = $this->documentationService->fetchNearestDocument($url, $key, $version ?: 'latest', $language);
-
                        if ($result) {
-                               /** @var FlashMessage $message */
-                               $message = GeneralUtility::makeInstance(
-                                       FlashMessage::class,
+                               $this->addFlashMessage(
                                        \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate(
                                                'downloadSucceeded',
                                                'documentation'
                                        ),
                                        '',
-                                       \TYPO3\CMS\Core\Messaging\AbstractMessage::OK,
-                                       TRUE
+                                       FlashMessage::OK
                                );
                        } else {
-                               /** @var FlashMessage $message */
-                               $message = GeneralUtility::makeInstance(
-                                       FlashMessage::class,
+                               $this->addFlashMessage(
                                        \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate(
                                                'downloadFailedNoArchive',
                                                'documentation'
@@ -174,16 +168,11 @@ class DocumentController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControl
                                                'downloadFailed',
                                                'documentation'
                                        ),
-                                       FlashMessage::ERROR,
-                                       TRUE
+                                       FlashMessage::ERROR
                                );
-
                        }
-                       $this->controllerContext->getFlashMessageQueue()->enqueue($message);
                } catch (\Exception $e) {
-                       /** @var FlashMessage $message */
-                       $message = GeneralUtility::makeInstance(
-                               FlashMessage::class,
+                       $this->addFlashMessage(
                                \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate(
                                        'downloadFailedDetails',
                                        'documentation',
@@ -197,10 +186,8 @@ class DocumentController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControl
                                        'downloadFailed',
                                        'documentation'
                                ),
-                               FlashMessage::ERROR,
-                               TRUE
+                               FlashMessage::ERROR
                        );
-                       $this->controllerContext->getFlashMessageQueue()->enqueue($message);
                }
                $this->redirect('download');
        }
index c210a5f..b39f799 100644 (file)
@@ -19,7 +19,7 @@
        <div id="typo3-docbody">
                <div id="typo3-inner-docbody" class="typo3-documentation">
                        <f:render section="module-headline" />
-                       <f:flashMessages renderMode="div" />
+                       <f:flashMessages />
                        <f:render section="Content" />
                </div>
        </div>
index 1019342..ccfdf5f 100644 (file)
@@ -67,9 +67,9 @@ class ActionController extends AbstractController {
                                }
                        }
                } catch (\TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException $e) {
-                       $this->addFlashMessage(htmlspecialchars($e->getMessage()), '', \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);
+                       $this->addFlashMessage($e->getMessage(), '', \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);
                } catch (\TYPO3\CMS\Core\Package\Exception\PackageStatesFileNotWritableException $e) {
-                       $this->addFlashMessage(htmlspecialchars($e->getMessage()), '', \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);
+                       $this->addFlashMessage($e->getMessage(), '', \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);
                }
                $this->redirect('index', 'List', NULL, array(self::TRIGGER_RefreshModuleMenu => TRUE));
        }
@@ -104,7 +104,7 @@ class ActionController extends AbstractController {
                                )
                        );
                } catch (\TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException $e) {
-                       $this->addFlashMessage(htmlspecialchars($e->getMessage()), '', \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);
+                       $this->addFlashMessage($e->getMessage(), '', \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);
                }
 
                return '';
index 3503004..3adebe9 100644 (file)
@@ -168,7 +168,7 @@ class DownloadController extends AbstractController {
                        // FlashMessage that extension is installed
                        $this->addFlashMessage(
                                \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('distribution.welcome.message', 'extensionmanager')
-                                       . ' <strong>' . $extension->getExtensionKey() . '</strong>',
+                                       . $extension->getExtensionKey(),
                                \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate('distribution.welcome.headline', 'extensionmanager')
                        );
 
@@ -206,11 +206,11 @@ class DownloadController extends AbstractController {
                                $this->managementService->downloadMainExtension($extension);
                        }
                        $this->addFlashMessage(
-                               htmlspecialchars($this->translate('extensionList.updateFlashMessage.body', array($extensionKey))),
+                               $this->translate('extensionList.updateFlashMessage.body', array($extensionKey)),
                                $this->translate('extensionList.updateFlashMessage.title')
                        );
                } catch (\Exception $e) {
-                       $this->addFlashMessage(htmlspecialchars($e->getMessage()), '', FlashMessage::ERROR);
+                       $this->addFlashMessage($e->getMessage(), '', FlashMessage::ERROR);
                }
 
                return '';
index 2f1f061..7dfcaeb 100644 (file)
@@ -132,7 +132,7 @@ class ListController extends AbstractController {
                                        $repositoryHelper->updateExtList();
                                }
                        } catch (ExtensionManagerException $e) {
-                               $this->addFlashMessage(htmlspecialchars($e->getMessage()), $e->getCode(), FlashMessage::ERROR);
+                               $this->addFlashMessage($e->getMessage(), $e->getCode(), FlashMessage::ERROR);
                        }
 
                        $officialDistributions = $this->extensionRepository->findAllOfficialDistributions();
index 2974c96..10495e3 100644 (file)
@@ -100,14 +100,14 @@ class UploadExtensionFileController extends AbstractController {
                        $emConfiguration = $this->configurationUtility->getCurrentConfiguration('extensionmanager');
                        if (!$emConfiguration['automaticInstallation']['value']) {
                                $this->addFlashMessage(
-                                       htmlspecialchars($this->translate('extensionList.uploadFlashMessage.message', array($extensionData['extKey']))),
-                                       htmlspecialchars($this->translate('extensionList.uploadFlashMessage.title')),
+                                       $this->translate('extensionList.uploadFlashMessage.message', array($extensionData['extKey'])),
+                                       $this->translate('extensionList.uploadFlashMessage.title'),
                                        FlashMessage::OK
                                );
                        } else {
                                if ($this->activateExtension($extensionData['extKey'])) {
                                        $this->addFlashMessage(
-                                               htmlspecialchars($this->translate('extensionList.installedFlashMessage.message', array($extensionData['extKey']))),
+                                               $this->translate('extensionList.installedFlashMessage.message', array($extensionData['extKey'])),
                                                '',
                                                FlashMessage::OK
                                        );
@@ -119,7 +119,7 @@ class UploadExtensionFileController extends AbstractController {
                        throw $exception;
                } catch (\Exception $exception) {
                        $this->removeExtensionAndRestoreFromBackup($fileName);
-                       $this->addFlashMessage(htmlspecialchars($exception->getMessage()), '', FlashMessage::ERROR);
+                       $this->addFlashMessage($exception->getMessage(), '', FlashMessage::ERROR);
                }
                $this->redirect('index', 'List', NULL, array(self::TRIGGER_RefreshModuleMenu => TRUE));
        }
index 4f3711c..a64c1d6 100644 (file)
@@ -67,7 +67,7 @@ class DownloadUtility implements \TYPO3\CMS\Core\SingletonInterface {
         */
        public function setDownloadPath($downloadPath) {
                if (!in_array($downloadPath, \TYPO3\CMS\Extensionmanager\Domain\Model\Extension::returnAllowedInstallTypes())) {
-                       throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(htmlspecialchars($downloadPath) . ' not in allowed download paths', 1344766387);
+                       throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException($downloadPath . ' not in allowed download paths', 1344766387);
                }
                $this->downloadPath = $downloadPath;
        }
index d814e5b..41b8ba0 100644 (file)
@@ -58,7 +58,7 @@ class ExtensionXmlPullParser extends AbstractExtensionXmlParser {
                        throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('Unable to create XML parser.', 1342640540);
                }
                if ($this->objXml->open($file, 'utf-8') === FALSE) {
-                       throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(sprintf('Unable to open file resource %s.', htmlspecialchars($file)));
+                       throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(sprintf('Unable to open file resource %s.', $file));
                }
                while ($this->objXml->read()) {
                        if ($this->objXml->nodeType == \XMLReader::ELEMENT) {
index 17a12aa..7cf58d3 100644 (file)
@@ -76,11 +76,11 @@ class ExtensionXmlPushParser extends AbstractExtensionXmlParser {
                xml_set_element_handler($this->objXml, 'startElement', 'endElement');
                xml_set_character_data_handler($this->objXml, 'characterData');
                if (!($fp = fopen($file, 'r'))) {
-                       throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(sprintf('Unable to open file resource %s.', htmlspecialchars($file)), 1342640689);
+                       throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(sprintf('Unable to open file resource %s.', $file), 1342640689);
                }
                while ($data = fread($fp, 4096)) {
                        if (!xml_parse($this->objXml, $data, feof($fp))) {
-                               throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(sprintf('XML error %s in line %u of file resource %s.', xml_error_string(xml_get_error_code($this->objXml)), xml_get_current_line_number($this->objXml), htmlspecialchars($file)), 1342640703);
+                               throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(sprintf('XML error %s in line %u of file resource %s.', xml_error_string(xml_get_error_code($this->objXml)), xml_get_current_line_number($this->objXml), $file), 1342640703);
                        }
                }
                xml_parser_free($this->objXml);
index 82359eb..a44c148 100644 (file)
@@ -57,7 +57,7 @@ class MirrorXmlPullParser extends AbstractMirrorXmlParser {
                        throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('Unable to create XML parser.', 1342640820);
                }
                if ($this->objXml->open($file, 'utf-8') === FALSE) {
-                       throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(sprintf('Unable to open file resource %s.', htmlspecialchars($file)), 1342640893);
+                       throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(sprintf('Unable to open file resource %s.', $file), 1342640893);
                }
                while ($this->objXml->read()) {
                        if ($this->objXml->nodeType == \XMLReader::ELEMENT) {
index 5fbd3e9..ef4b825 100644 (file)
@@ -71,11 +71,11 @@ class MirrorXmlPushParser extends AbstractMirrorXmlParser {
                xml_set_element_handler($this->objXml, 'startElement', 'endElement');
                xml_set_character_data_handler($this->objXml, 'characterData');
                if (!($fp = fopen($file, 'r'))) {
-                       throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(sprintf('Unable to open file resource %s.', htmlspecialchars($file)), 1342641010);
+                       throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(sprintf('Unable to open file resource %s.', $file), 1342641010);
                }
                while ($data = fread($fp, 4096)) {
                        if (!xml_parse($this->objXml, $data, feof($fp))) {
-                               throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(sprintf('XML error %s in line %u of file resource %s.', xml_error_string(xml_get_error_code($this->objXml)), xml_get_current_line_number($this->objXml), htmlspecialchars($file)), 1342641011);
+                               throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(sprintf('XML error %s in line %u of file resource %s.', xml_error_string(xml_get_error_code($this->objXml)), xml_get_current_line_number($this->objXml), $file), 1342641011);
                        }
                }
                xml_parser_free($this->objXml);
index 3f1ea73..2b85b27 100644 (file)
@@ -139,10 +139,10 @@ class Helper implements \TYPO3\CMS\Core\SingletonInterface {
                        $fileContent = \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl($remoteResource, 0, array(TYPO3_user_agent));
                        if ($fileContent !== FALSE) {
                                if (\TYPO3\CMS\Core\Utility\GeneralUtility::writeFile($localResource, $fileContent) === FALSE) {
-                                       throw new ExtensionManagerException(sprintf('Could not write to file %s.', htmlspecialchars($localResource)), 1342635378);
+                                       throw new ExtensionManagerException(sprintf('Could not write to file %s.', $localResource), 1342635378);
                                }
                        } else {
-                               throw new ExtensionManagerException(sprintf('Could not access remote resource %s.', htmlspecialchars($remoteResource)), 1342635425);
+                               throw new ExtensionManagerException(sprintf('Could not access remote resource %s.', $remoteResource), 1342635425);
                        }
                }
        }
index c3147f4..d393f7f 100644 (file)
@@ -9,7 +9,7 @@
 </f:section>
 
 <f:section name="Content">
-       <f:flashMessages class="distribution-detail-flashmessage" renderMode="div" />
+       <f:flashMessages class="distribution-detail-flashmessage" />
        <div class="distribution-detail">
                <div class="distribution-detail-previewpane">
                        <em:image
index 15aff02..d85293c 100644 (file)
@@ -10,7 +10,7 @@
 </f:section>
 
 <f:section name="Content">
-       <f:flashMessages renderMode="div" />
+       <f:flashMessages />
        <f:if condition="{enableDistributionsView}">
                <f:then>
                        <div class="distribution-holder">
index e76fa96..805d374 100644 (file)
@@ -13,7 +13,7 @@
 </f:section>
 
 <f:section name="Content">
-       <f:flashMessages renderMode="div" />
+       <f:flashMessages />
 
        <f:render partial="List/UploadForm" />
 
index 90b187a..38323c4 100644 (file)
@@ -10,7 +10,7 @@
 </f:section>
 
 <f:section name="Content">
-       <f:flashMessages renderMode="div" />
+       <f:flashMessages />
        <f:render partial="List/UnresolvedDependencies" arguments="{_all}" />
        <f:be.infobox title="{f:translate(key: 'dependencyCheck.unresolvedDependencies.title')}" state="1">
                <f:render partial="List/UnresolvedDependenciesMessage" />
index 01da12b..a3c05b0 100644 (file)
@@ -20,6 +20,8 @@ namespace TYPO3\CMS\Fluid\ViewHelpers;
  *                                                                        *
  * The TYPO3 project - inspiring people to share!                         *
  *                                                                        */
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
 /**
  * View helper which renders the flash messages (if there are any) as an unsorted list.
  *
@@ -45,18 +47,34 @@ namespace TYPO3\CMS\Fluid\ViewHelpers;
  * </output>
  *
  * <code title="TYPO3 core style">
- * <f:flashMessages renderMode="div" />
+ * <f:flashMessages />
  * </code>
  * <output>
- * <div class="typo3-messages">
- * <div class="alert alert-ok">
+ * <ul class="typo3-messages">
+ * <li class="alert alert-ok">
  * <h4>Some Message Header</h4>
- * <div class="alert-body">Some message body</div>
- * </div>
- * <div class="alert alert-notice">
- * <div class="alert-body">Some notice message without header</div>
- * </div>
- * </div>
+ * Some message body
+ * </li>
+ * <li class="alert alert-notice">
+ * Some notice message without header
+ * </li>
+ * </ul>
+ * </output>
+ * <code title="Output flash messages as a description list">
+ * <f:flashMessages as="flashMessages">
+ *     <dl class="messages">
+ *     <f:for each="{flashMessages}" as="flashMessage">
+ *             <dt>{flashMessage.code}</dt>
+ *             <dd>{flashMessage.message}</dd>
+ *     </f:for>
+ *     </dl>
+ * </f:flashMessages>
+ * </code>
+ * <output>
+ * <dl class="messages">
+ *     <dt>1013</dt>
+ *     <dd>Some Warning Message.</dd>
+ * </dl>
  * </output>
  *
  * @api
@@ -67,9 +85,9 @@ class FlashMessagesViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractT
        const RENDER_MODE_DIV = 'div';
 
        /**
-        * @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
+        * @var string
         */
-       protected $contentObject;
+       protected $tagName = 'ul';
 
        /**
         * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
@@ -82,7 +100,6 @@ class FlashMessagesViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractT
         */
        public function injectConfigurationManager(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager) {
                $this->configurationManager = $configurationManager;
-               $this->contentObject = $this->configurationManager->getContentObject();
        }
 
        /**
@@ -101,42 +118,52 @@ class FlashMessagesViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractT
         * from being cached.
         *
         * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::no_cache
-        * @param string $renderMode one of the RENDER_MODE_* constants
+        * @param string $renderMode @deprecated since TYPO3 CMS 7.3. If you need custom output, use <f:flashMessages as="messages"><f:for each="messages" as="message">...</f:for></f:flashMessages>
+        * @param string $as The name of the current flashMessage variable for rendering inside
         * @return string rendered Flash Messages, if there are any.
         * @api
         */
-       public function render($renderMode = self::RENDER_MODE_UL) {
+       public function render($renderMode = NULL, $as = NULL) {
                $flashMessages = $this->controllerContext->getFlashMessageQueue()->getAllMessagesAndFlush();
                if ($flashMessages === NULL || count($flashMessages) === 0) {
                        return '';
                }
-               if (isset($GLOBALS['TSFE']) && $this->contentObject->getUserObjectType() === \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::OBJECTTYPE_USER) {
-                       $GLOBALS['TSFE']->no_cache = 1;
-               }
-               switch ($renderMode) {
-                       case self::RENDER_MODE_UL:
-                               return $this->renderUl($flashMessages);
-                       case self::RENDER_MODE_DIV:
-                               return $this->renderDiv($flashMessages);
-                       default:
-                               throw new \TYPO3\CMS\Fluid\Core\ViewHelper\Exception('Invalid render mode "' . $renderMode . '" passed to FlashMessageViewhelper', 1290697924);
+               if ($renderMode !== NULL) {
+                       GeneralUtility::deprecationLog('renderMode has been deprecated in TYPO3 CMS 7.3 and will be removed in TYPO3 CMS 8');
+                       if ($renderMode === self::RENDER_MODE_DIV) {
+                               $content = $this->renderDiv($flashMessages);
+                       } else {
+                               $content = $this->renderAsList($flashMessages);
+                       }
+               } else {
+                       if ($as === NULL) {
+                               $content = $this->renderAsList($flashMessages);
+                       } else {
+                               $content = $this->renderFromTemplate($flashMessages, $as);
+                       }
                }
+
+               return $content;
        }
 
        /**
         * Renders the flash messages as unordered list
         *
-        * @param array $flashMessages array<\TYPO3\CMS\Core\Messaging\FlashMessage>
+        * @param array $flashMessages \TYPO3\CMS\Core\Messaging\FlashMessage[]
         * @return string
         */
-       protected function renderUl(array $flashMessages) {
-               $this->tag->setTagName('ul');
-               if ($this->hasArgument('class')) {
-                       $this->tag->addAttribute('class', $this->arguments['class']);
-               }
+       protected function renderAsList(array $flashMessages) {
+               $flashMessagesClass = $this->hasArgument('class') ? $this->arguments['class'] : 'typo3-messages';
                $tagContent = '';
+               $this->tag->addAttribute('class', $flashMessagesClass);
+               /** @var $singleFlashMessage \TYPO3\CMS\Core\Messaging\FlashMessage */
                foreach ($flashMessages as $singleFlashMessage) {
-                       $tagContent .= '<li>' . htmlspecialchars($singleFlashMessage->getMessage()) . '</li>';
+                       $severityClass = sprintf('alert %s', $singleFlashMessage->getClass());
+                       $messageContent = htmlspecialchars($singleFlashMessage->getMessage());
+                       if ($singleFlashMessage->getTitle() !== '') {
+                               $messageContent = sprintf('<h4>%s</h4>', htmlspecialchars($singleFlashMessage->getTitle())) . $messageContent;
+                       }
+                       $tagContent .= sprintf('<li class="%s">%s</li>', htmlspecialchars($severityClass), $messageContent);
                }
                $this->tag->setContent($tagContent);
                return $this->tag->render();
@@ -144,8 +171,28 @@ class FlashMessagesViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractT
 
        /**
         * Renders the flash messages as nested divs
+        * Defer the rendering of Flash Messages to the template. In this case,
+        * the flash messages are stored in the template inside the variable specified
+        * in "as".
+        *
+        * @param array $flashMessages \TYPO3\CMS\Core\Messaging\FlashMessage[]
+        * @param string $as
+        * @return string
+        */
+       protected function renderFromTemplate(array $flashMessages, $as) {
+               $templateVariableContainer = $this->renderingContext->getTemplateVariableContainer();
+               $templateVariableContainer->add($as, $flashMessages);
+               $content = $this->renderChildren();
+               $templateVariableContainer->remove($as);
+
+               return $content;
+       }
+
+       /**
+        * Renders the flash messages as nested divs
         *
-        * @param array $flashMessages array<\TYPO3\CMS\Core\Messaging\FlashMessage>
+        * @deprecated in 7.3 will be removed in 8.0
+        * @param array $flashMessages \TYPO3\CMS\Core\Messaging\FlashMessage[]
         * @return string
         */
        protected function renderDiv(array $flashMessages) {
index bcf7ee8..6928305 100644 (file)
@@ -4,7 +4,7 @@
 
 <f:section name="Content">
        <p class="lead"><f:translate key="administration.document.description"/></p>
-       <f:flashMessages renderMode="div"/>
+       <f:flashMessages />
        <f:if condition="{phashRow}">
                <f:then>
                        <table class="table table-striped table-hover">
index 53107c5..6f3adaa 100644 (file)
@@ -7,58 +7,85 @@
 <f:section name="iconButtons">
        <div class="menuItems">
                <span class="menuItem updateItem" data-action="updateActiveLanguages">
-                       <f:be.buttons.icon icon="actions-system-extension-download" title="{f:translate(key:'button.downloadAll')}" />
+                       <f:be.buttons.icon icon="actions-system-extension-download"
+                                                          title="{f:translate(key:'button.downloadAll')}"/>
                </span>
                <span class="menuItem loadingItem">
                        <span title="" class="t3-icon fa fa-spin fa-circle-o-notch">&nbsp;</span>
                </span>
                <span class="menuItem cancelItem" data-action="cancelLanguageUpdate">
-                       &nbsp;<f:be.buttons.icon icon="actions-document-close" title="{f:translate(key:'button.cancel')}" />
+                       &nbsp;<f:be.buttons.icon icon="actions-document-close" title="{f:translate(key:'button.cancel')}"/>
                </span>
        </div>
 </f:section>
 
 <f:section name="content">
-       <h1><f:translate key="header.languages" /></h1>
-       <f:flashMessages renderMode="div" />
+       <h1>
+               <f:translate key="header.languages"/>
+       </h1>
+       <f:flashMessages/>
        <form class="form-inline">
                <div class="form-group">
-                       <f:form.textfield name="typo3-language-searchfield" placeholder="{f:translate(key:'table.search')}" id="typo3-language-searchfield" value="{search}" class="form-control t3js-language-searchfield" />
+                       <f:form.textfield name="typo3-language-searchfield" placeholder="{f:translate(key:'table.search')}"
+                                                         id="typo3-language-searchfield" value="{search}"
+                                                         class="form-control t3js-language-searchfield"/>
                </div>
        </form>
        <table id="typo3-language-list" class="t3-table t3-datatable">
                <thead>
-                       <tr>
-                               <th title="{f:translate(key:'table.ad.title')}"><f:translate key="table.ad" /></th>
-                               <th><f:translate key="table.language" /></th>
-                               <th><f:translate key="table.locale" /></th>
-                               <th><f:translate key="table.date" /></th>
-                               <th><f:translate key="table.actions" /></th>
-                       </tr>
+               <tr>
+                       <th title="{f:translate(key:'table.ad.title')}">
+                               <f:translate key="table.ad"/>
+                       </th>
+                       <th>
+                               <f:translate key="table.language"/>
+                       </th>
+                       <th>
+                               <f:translate key="table.locale"/>
+                       </th>
+                       <th>
+                               <f:translate key="table.date"/>
+                       </th>
+                       <th>
+                               <f:translate key="table.actions"/>
+                       </th>
+               </tr>
                </thead>
                <tbody>
-                       <f:for each="{languages}" as="language" iteration="iterator">
-                               <tr id="language-{language.locale}" data-locale="{language.locale}" class="{f:if(condition: language.selected, then: 'enabled', else: 'disabled')} {f:if(condition: iterator.isEven, then: 'even', else: 'odd')}" role="row">
-                                       <td>
-                                               <a class="btn btn-default deactivateLanguageLink" data-action="deactivateLanguage" data-locale="{language.locale}" data-language="{language.label}" data-selected="{f:if(condition: language.selected, then: 'true', else: 'false')}"><span title="Deactivate" class="t3-icon fa fa-minus-square"> </span></a>
-                                               <a class="btn btn-default activateLanguageLink" data-action="activateLanguage" data-locale="{language.locale}" data-language="{language.label}" data-selected="{f:if(condition: language.selected, then: 'true', else: 'false')}"><span title="Activate" class="t3-icon fa fa-plus-circle"> </span></a>
-                                       </td>
-                                       <td class="sorting_1">{language.label}</td>
-                                       <td>{language.locale}</td>
-                                       <td class="lastUpdate">
-                                               <f:format.date date="{language.lastUpdate}" format="Y-m-d H:i" />
-                                       </td>
-                                       <td class="actions">
-                                               <a class="btn btn-default updateLanguageLink" data-action="updateLanguage" data-locale="{language.locale}" data-language="{language.label}" data-selected="true"><span title="Download" class="t3-icon fa fa-download"> </span></a>
-                                               <div class="progressBar">
-                                                       <div class="progress">
-                                                               <div class="progress-text"></div>
-                                                               <div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div>
-                                                       </div>
+               <f:for each="{languages}" as="language" iteration="iterator">
+                       <tr id="language-{language.locale}" data-locale="{language.locale}"
+                               class="{f:if(condition: language.selected, then: 'enabled', else: 'disabled')} {f:if(condition: iterator.isEven, then: 'even', else: 'odd')}"
+                               role="row">
+                               <td>
+                                       <a class="btn btn-default deactivateLanguageLink" data-action="deactivateLanguage"
+                                          data-locale="{language.locale}" data-language="{language.label}"
+                                          data-selected="{f:if(condition: language.selected, then: 'true', else: 'false')}"><span
+                                               title="Deactivate" class="t3-icon fa fa-minus-square"> </span></a>
+                                       <a class="btn btn-default activateLanguageLink" data-action="activateLanguage"
+                                          data-locale="{language.locale}" data-language="{language.label}"
+                                          data-selected="{f:if(condition: language.selected, then: 'true', else: 'false')}"><span
+                                               title="Activate" class="t3-icon fa fa-plus-circle"> </span></a>
+                               </td>
+                               <td class="sorting_1">{language.label}</td>
+                               <td>{language.locale}</td>
+                               <td class="lastUpdate">
+                                       <f:format.date date="{language.lastUpdate}" format="Y-m-d H:i"/>
+                               </td>
+                               <td class="actions">
+                                       <a class="btn btn-default updateLanguageLink" data-action="updateLanguage"
+                                          data-locale="{language.locale}" data-language="{language.label}" data-selected="true"><span
+                                               title="Download" class="t3-icon fa fa-download"> </span></a>
+
+                                       <div class="progressBar">
+                                               <div class="progress">
+                                                       <div class="progress-text"></div>
+                                                       <div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0"
+                                                                aria-valuemax="100" style="width: 0;"></div>
                                                </div>
-                                       </td>
-                               </tr>
-                       </f:for>
+                                       </div>
+                               </td>
+                       </tr>
+               </f:for>
                </tbody>
        </table>
 </f:section>
index 2f8262e..11405c8 100644 (file)
@@ -6,7 +6,7 @@
 
 <f:section name="content">
        <h1><f:translate key="header.translations" /></h1>
-       <f:flashMessages renderMode="div" />
+       <f:flashMessages />
        <form class="form-inline">
                <div class="form-group">
                        <f:form.textfield name="typo3-language-searchfield" placeholder="{f:translate(key:'table.search')}" id="typo3-language-searchfield" value="{search}" class="form-control t3js-language-searchfield" />
@@ -26,4 +26,4 @@
                        <!-- Will be filled by JS -->
                </tbody>
        </table>
-</f:section>
\ No newline at end of file
+</f:section>
index 11270b3..f50c287 100644 (file)
@@ -27,7 +27,7 @@
                        <div id="typo3-inner-docbody">
                                <h1><f:translate key="title" /></h1>
 
-                               <f:flashMessages renderMode="div" />
+                               <f:flashMessages />
 
                                <f:render section="content" />
                        </div>
index 9e3b5a5..61d0adb 100644 (file)
@@ -18,8 +18,7 @@
                </div>
                <div id="typo3-docbody">
                        <div id="typo3-inner-docbody">
-                               <f:flashMessages renderMode="div" />
-
+                               <f:flashMessages />
                                <f:render section="content" />
                        </div>
                </div>
index a78a7f5..e437255 100644 (file)
@@ -26,7 +26,7 @@
 <div id="typo3-docbody">
        <div id="typo3-inner-docbody">
                <f:if condition="{pageTitle}"><h1>{pageTitle}</h1></f:if>
-               <f:flashMessages renderMode="div" />
+               <f:flashMessages />
                <div id="workspacetabs"></div>
                <div class="well well-sm"><f:render section="main" /></div>
                <f:if condition="{showLegend}"><f:render partial="legend" /></f:if>
index d3ebb50..7fcd5a3 100644 (file)
@@ -3,7 +3,7 @@
        <div id="typo3-docbody">
                <div id="typo3-inner-docbody">
 
-                       <f:flashMessages renderMode="div" />
+                       <f:flashMessages />
 
                        <f:render section="main"/>
                </div>