[!!!][BUGFIX] EXT:form - Resolve caching issues with predefined forms 52/47752/11
authorRalf Zimmermann <ralf.zimmermann@tritum.de>
Fri, 24 Jun 2016 13:35:33 +0000 (15:35 +0200)
committerBenni Mack <benni@typo3.org>
Mon, 27 Jun 2016 07:58:13 +0000 (09:58 +0200)
The FORM content object is now introduced, which EXT:form is using
internally to call extbase and set itself as a non-cacheable cObject.

This way, caching issues with predefined forms are resolved.

Additionally, support for EXT:compatibility6 is dropped.

Resolves: #75747
Releases: master
Change-Id: If5816b1df146706f4149874a0cacc4d2fedbea2d
Reviewed-on: https://review.typo3.org/47752
Reviewed-by: Andreas Fernandez <typo3@scripting-base.de>
Tested-by: Andreas Fernandez <typo3@scripting-base.de>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
typo3/sysext/core/Documentation/Changelog/master/Breaking-75747-EXTform-RemovedUseDefaultContentObjectSetting.rst [new file with mode: 0644]
typo3/sysext/core/Documentation/Changelog/master/Important-75747-EXTform-RemovedSupportForCompatibility6.rst [new file with mode: 0644]
typo3/sysext/form/Classes/ContentObject/FormContentObject.php [new file with mode: 0644]
typo3/sysext/form/Classes/Hooks/ContentObjectHook.php [deleted file]
typo3/sysext/form/ext_localconf.php

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-75747-EXTform-RemovedUseDefaultContentObjectSetting.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-75747-EXTform-RemovedUseDefaultContentObjectSetting.rst
new file mode 100644 (file)
index 0000000..b316e7e
--- /dev/null
@@ -0,0 +1,28 @@
+=====================================================================
+Breaking: #75747 - EXT:form - Removed useDefaultContentObject setting
+=====================================================================
+
+Description
+===========
+
+The TypoScript option :ts:``useDefaultContentObject`` of the FORM cObject has been removed. Setting this value to 0 allowed the usage of the prehistoric content type ``mailform``.
+
+
+Impact
+======
+
+It is not possible to configure the rendering of the FORM cOject. The setting is not evaluated anymore.
+
+
+Affected Installations
+======================
+
+Any installation that uses the TypoScript option :ts:``useDefaultContentObject = 0``.
+
+
+Migration
+=========
+
+Remove the TypoScript option from any TypoScript settings. Migrate manually to use the features of EXT:form.
+
+.. index:: typoscript
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Important-75747-EXTform-RemovedSupportForCompatibility6.rst b/typo3/sysext/core/Documentation/Changelog/master/Important-75747-EXTform-RemovedSupportForCompatibility6.rst
new file mode 100644 (file)
index 0000000..1598319
--- /dev/null
@@ -0,0 +1,8 @@
+=================================================================
+Important: #75747 - EXT:form - Removed support for compatibility6
+=================================================================
+
+Description
+===========
+
+EXT:compatibility6 contains the prehistoric CType mailform. Since compatibility6 is not avilable for TYPO3 v8 the compatibility between EXT:form and the prehistoric CType mailform has been removed.
diff --git a/typo3/sysext/form/Classes/ContentObject/FormContentObject.php b/typo3/sysext/form/Classes/ContentObject/FormContentObject.php
new file mode 100644 (file)
index 0000000..b3def56
--- /dev/null
@@ -0,0 +1,124 @@
+<?php
+namespace TYPO3\CMS\Form\ContentObject;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser;
+use TYPO3\CMS\Core\Utility\ArrayUtility;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Form\Domain\Model\Configuration;
+use TYPO3\CMS\Frontend\ContentObject\AbstractContentObject;
+use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
+
+/**
+ * FORM cObject, a wrapper to allow to use 10 = FORM in TypoScript
+ * which actually executes the Extbase plugin (marked as non-cached)
+ */
+class FormContentObject extends AbstractContentObject
+{
+    /**
+     * Renders the application defined cObject FORM
+     *
+     * The Extbase plugin "Form" is initialized. At this time, the
+     * controller "Frontend" action "show" does the rest.
+     *
+     * @param array $conf TS configuration for this cObject
+     * @return string HTML output
+     * @throws \InvalidArgumentException
+     */
+    public function render($conf = array())
+    {
+        $mergedTypoScript = null;
+        // If the FORM configuration is retrieved from the database
+        // all TypoScript interpretation will be disabled for security.
+        if ($this->cObj->data['CType'] === 'mailform') {
+            // If the FORM configuration is retrieved from the database
+            // and a predefined form is selected then the TypoScript
+            // interpretation is allowed.
+            $renderPredefinedForm = false;
+            $predefinedFormIdentifier = null;
+            if (!empty($this->cObj->data['tx_form_predefinedform'])) {
+                $predefinedFormIdentifier = $this->cObj->data['tx_form_predefinedform'];
+                if (isset($this->getTypoScriptFrontendController()->tmpl->setup['plugin.']['tx_form.']['predefinedForms.'][$predefinedFormIdentifier . '.'])) {
+                    $renderPredefinedForm = true;
+                } else {
+                    throw new \InvalidArgumentException('No FORM configuration for identifier "' . $predefinedFormIdentifier . '" available.', 1466769483);
+                }
+            }
+
+            if ($renderPredefinedForm && $predefinedFormIdentifier) {
+                $mergedTypoScript = $this->getTypoScriptFrontendController()->tmpl->setup['plugin.']['tx_form.']['predefinedForms.'][$predefinedFormIdentifier . '.'];
+                ArrayUtility::mergeRecursiveWithOverrule($mergedTypoScript, $conf);
+            } else {
+                $bodytext = $this->cObj->data['bodytext'];
+                /** @var $typoScriptParser TypoScriptParser */
+                $typoScriptParser = GeneralUtility::makeInstance(TypoScriptParser::class);
+                $typoScriptParser->parse($bodytext);
+                $mergedTypoScript = (array)$typoScriptParser->setup;
+                ArrayUtility::mergeRecursiveWithOverrule($mergedTypoScript, $conf);
+                // Disables TypoScript interpretation since TypoScript is handled that could contain insecure settings:
+                $mergedTypoScript[Configuration::DISABLE_CONTENT_ELEMENT_RENDERING] = true;
+            }
+        }
+
+        // make sure the extbase plugin is marked as Uncached
+        $content = $this->prepareNonCacheableUserFunction(is_array($mergedTypoScript) ? $mergedTypoScript : $conf);
+
+        // Only apply stdWrap to TypoScript that was NOT created by the wizard:
+        if (isset($conf['stdWrap.'])) {
+            $content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
+        }
+        return $content;
+    }
+
+    /**
+     * Set up the extbase plugin to be a non-cacheable user function
+     *
+     * @param array $typoScript
+     * @return string the content as placeholder for USER_INT code
+     */
+    protected function prepareNonCacheableUserFunction($typoScript)
+    {
+        $configuration = array (
+            'userFunc' => 'TYPO3\\CMS\\Extbase\\Core\\Bootstrap->run',
+            'pluginName' => 'Form',
+            'extensionName' => 'Form',
+            'vendorName' => 'TYPO3\\CMS',
+            'controller' => 'Frontend',
+            'action' => 'show',
+            'settings' => array('typoscript' => $typoScript),
+            'persistence' => array(),
+            'view' => array(),
+        );
+
+        $this->cObj->setUserObjectType(ContentObjectRenderer::OBJECTTYPE_USER_INT);
+        $substKey = 'INT_SCRIPT.' . $this->getTypoScriptFrontendController()->uniqueHash();
+        $content = '<!--' . $substKey . '-->';
+        $this->getTypoScriptFrontendController()->config['INTincScript'][$substKey] = array(
+            'conf' => $configuration,
+            'cObj' => serialize($this->cObj),
+            'type' => 'FUNC'
+        );
+        $this->cObj->setUserObjectType(false);
+        return $content;
+    }
+
+    /**
+     * @return \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
+     */
+    protected function getTypoScriptFrontendController()
+    {
+        return $GLOBALS['TSFE'];
+    }
+}
diff --git a/typo3/sysext/form/Classes/Hooks/ContentObjectHook.php b/typo3/sysext/form/Classes/Hooks/ContentObjectHook.php
deleted file mode 100644 (file)
index 734f32f..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-<?php
-namespace TYPO3\CMS\Form\Hooks;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser;
-use TYPO3\CMS\Core\Utility\ArrayUtility;
-use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Extbase\Core\Bootstrap;
-use TYPO3\CMS\Form\Domain\Model\Configuration;
-use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
-
-/**
- * Hook cObjGetSingleExt
- */
-class ContentObjectHook
-{
-    /**
-     * Renders the application defined cObject FORM
-     * which overrides the TYPO3 default cObject FORM
-     *
-     * If FORM is dedected by the ContentObjectRenderer,
-     * the Extbase plugin "Form" is initialized. At this time, the
-     * controller "Frontend" action "execute" does the rest.
-     *
-     * @param string $typoScriptObjectName Name of the object
-     * @param array $typoScript TS configuration for this cObject
-     * @param string $typoScriptKey A string label used for the internal debugging tracking.
-     * @param ContentObjectRenderer $contentObject reference
-     * @return string HTML output
-     */
-    public function cObjGetSingleExt($typoScriptObjectName, array $typoScript, $typoScriptKey, ContentObjectRenderer $contentObject)
-    {
-        $content = '';
-        // render the FORM CE from TYPO3 < 4.6
-        if ($typoScriptObjectName === 'FORM'
-            && !empty($typoScript['useDefaultContentObject'])
-            && ExtensionManagementUtility::isLoaded('compatibility6')
-        ) {
-            $content = $contentObject->getContentObject($typoScriptObjectName)->render($typoScript);
-        } elseif ($typoScriptObjectName === 'FORM') {
-            $mergedTypoScript = null;
-            // If the FORM configuration comes from the database
-            // all TypoScript interpretation will be disabled for security.
-            if ($contentObject->data['CType'] === 'mailform') {
-                // If the FORM configuration comes from the database
-                // and a predefined form is selected than the TypoScript
-                // interpretation is allowed.
-                $renderPredefinedForm = false;
-                if (isset($contentObject->data['tx_form_predefinedform'])
-                    && !empty($contentObject->data['tx_form_predefinedform'])
-                ) {
-                    $predefinedFormIdentifier = $contentObject->data['tx_form_predefinedform'];
-                    if (isset($GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_form.']['predefinedForms.'][$predefinedFormIdentifier . '.'])) {
-                        $renderPredefinedForm = true;
-                    } else {
-                        throw new \InvalidArgumentException('No FORM configuration for identifier "' . $predefinedFormIdentifier . '" available.', 1457097250);
-                    }
-                }
-
-                if ($renderPredefinedForm) {
-                    $mergedTypoScript = $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_form.']['predefinedForms.'][$predefinedFormIdentifier . '.'];
-                    ArrayUtility::mergeRecursiveWithOverrule($mergedTypoScript, $typoScript);
-                } else {
-                    $bodytext = $contentObject->data['bodytext'];
-                    /** @var $typoScriptParser TypoScriptParser */
-                    $typoScriptParser = GeneralUtility::makeInstance(TypoScriptParser::class);
-                    $typoScriptParser->parse($bodytext);
-                    $mergedTypoScript = (array)$typoScriptParser->setup;
-                    ArrayUtility::mergeRecursiveWithOverrule($mergedTypoScript, $typoScript);
-                    // Disables TypoScript interpretation since TypoScript is handled that could contain insecure settings:
-                    $mergedTypoScript[Configuration::DISABLE_CONTENT_ELEMENT_RENDERING] = true;
-                }
-            }
-            $newTypoScript = (is_array($mergedTypoScript) ? $mergedTypoScript : $typoScript);
-
-            $extbase = GeneralUtility::makeInstance(Bootstrap::class);
-            $content = $extbase->run('', array(
-                'pluginName' => 'Form',
-                'extensionName' => 'Form',
-                'vendorName' => 'TYPO3\\CMS',
-                'controller' => 'Frontend',
-                'action' => 'show',
-                'settings' => array('typoscript' => $newTypoScript),
-                'persistence' => array(),
-                'view' => array(),
-            ));
-
-            // Only apply stdWrap to TypoScript that was NOT created by the wizard:
-            if (isset($typoScript['stdWrap.'])) {
-                $content = $contentObject->stdWrap($content, $typoScript['stdWrap.']);
-            }
-        }
-        return $content;
-    }
-}
index f5d6cac..1f9c613 100644 (file)
@@ -19,36 +19,29 @@ if (TYPO3_MODE === 'BE') {
     $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][1440772316] = array(
         'nodeName' => 'formwizard',
         'priority' => 40,
-        'class' => \TYPO3\CMS\Form\View\Wizard\Element\FormWizardElement::class,
-    );
-} else {
-    // Handling of cObjects "FORM" and "FORM_INT"
-    $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'][] = array(
-        'FORM',
-        \TYPO3\CMS\Form\Hooks\ContentObjectHook::class
-    );
-    $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['cObjTypeAndClass'][] = array(
-        'FORM_INT',
-        \TYPO3\CMS\Form\Hooks\ContentObjectHook::class
+        'class'    => \TYPO3\CMS\Form\View\Wizard\Element\FormWizardElement::class,
     );
+}
 
-    // Extbase handling
-    \TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerTypeConverter(
-        \TYPO3\CMS\Form\Domain\Property\TypeConverter\ArrayToValidationElementConverter::class
-    );
+// Extbase handling
+\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerTypeConverter(
+    \TYPO3\CMS\Form\Domain\Property\TypeConverter\ArrayToValidationElementConverter::class
+);
 
-    \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
-        'TYPO3.CMS.Form',
-        'Form',
-        array('Frontend' => 'show, confirmation, dispatchConfirmationButtonClick, process, afterProcess'),
-        array('Frontend' => 'show, confirmation, dispatchConfirmationButtonClick, process, afterProcess')
-    );
+\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
+    'TYPO3.CMS.Form',
+    'Form',
+    array('Frontend' => 'show, confirmation, dispatchConfirmationButtonClick, process, afterProcess'),
+    array('Frontend' => 'show, confirmation, dispatchConfirmationButtonClick, process, afterProcess')
+);
 
-    $signalSlotDispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\SignalSlot\Dispatcher::class);
-    $signalSlotDispatcher->connect(
-        \TYPO3\CMS\Form\Domain\Builder\FormBuilder::class,
-        'txFormHandleIncomingValues',
-        \TYPO3\CMS\Form\Hooks\HandleIncomingFormValues::class,
-        'handleIncomingFormValues'
-    );
-}
+$signalSlotDispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\SignalSlot\Dispatcher::class);
+$signalSlotDispatcher->connect(
+    \TYPO3\CMS\Form\Domain\Builder\FormBuilder::class,
+    'txFormHandleIncomingValues',
+    \TYPO3\CMS\Form\Hooks\HandleIncomingFormValues::class,
+    'handleIncomingFormValues'
+);
+
+// Register the extbase plugin as shorthand for typoscript 10 = FORM
+$GLOBALS['TYPO3_CONF_VARS']['FE']['ContentObjects']['FORM'] = \TYPO3\CMS\Form\ContentObject\FormContentObject::class;