[FEATURE] EXT:form - Allow predefined forms 57/45357/23
authorRalf Zimmermann <ralf.zimmermann@tritum.de>
Sun, 6 Mar 2016 00:57:00 +0000 (01:57 +0100)
committerOliver Hader <oliver.hader@typo3.org>
Sun, 6 Mar 2016 01:40:02 +0000 (02:40 +0100)
This patchset enables the integration of predefined forms. An integrator
can define forms - for example within the site package - using
plugin.tx_form.predefinedForms. An editor can add a new mailform
content element to a page and choose a form from the list of predefined
elements.

Example integration:

plugin.tx_form.predefinedForms.someUniqueName = FORM
plugin.tx_form.predefinedForms.someUniqueName {
 ...
}

Resolves: #72309
Releases: master
Change-Id: I79def3cc00812bd5e5006b5226216064cc1b7ac7
Reviewed-on: https://review.typo3.org/45357
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Oliver Hader <oliver.hader@typo3.org>
typo3/sysext/core/Documentation/Changelog/master/Feature-72309-EXTform-AllowIntegrationOfPredefinedForms.rst [new file with mode: 0644]
typo3/sysext/form/Classes/Hooks/ContentObjectHook.php
typo3/sysext/form/Configuration/TCA/Overrides/tt_content.php
typo3/sysext/form/Resources/Private/Language/Database.xlf [new file with mode: 0644]
typo3/sysext/form/ext_tables.sql [new file with mode: 0644]

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-72309-EXTform-AllowIntegrationOfPredefinedForms.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-72309-EXTform-AllowIntegrationOfPredefinedForms.rst
new file mode 100644 (file)
index 0000000..b35b795
--- /dev/null
@@ -0,0 +1,108 @@
+============================================================
+Feature: #72309 - EXT:form - Integration of Predefined Forms
+============================================================
+
+Description
+===========
+
+The content element of EXT:form now allows the integration of predefined forms. An integrator can
+define forms - for example within a site package - using ``plugin.tx_form.predefinedForms``. An
+editor can add a new ``mailform`` content element to a page and choose a form from a list of
+predefined elements.
+
+There are even more advantages:
+
+- Integrators can build there forms with TypoScript which offers much more possibilites than doing
+it within the form wizard. Especially, the integrator is able to use stdWrap functionalities which
+are not available when using the form wizard (for security reasons).
+- There is no need anymore for editors to use the form wizard. They can choose the predefined forms
+which are optimized layout-wise.
+- Forms can be re-used throughout the whole installation.
+- Forms can be stored outside the DB and versionized.
+
+In order to be able to select the pre-defined form in the backend, the form has to be registered
+using PageTS.
+
+.. code-block:: typoscript
+
+   TCEFORM.tt_content.tx_form_predefinedform.addItems.contactForm = LLL:EXT:my_theme/Resources/Private/Language/locallang.xlf:contactForm
+
+Example form:
+
+.. code-block:: typoscript
+
+   plugin.tx_form.predefinedForms.contactForm = FORM
+   plugin.tx_form.predefinedForms.contactForm {
+     enctype = multipart/form-data
+     method = post
+     prefix = contact
+     confirmation = 1
+
+     postProcessor {
+       1 = mail
+       1 {
+         recipientEmail = test@mail.com
+         senderEmail = test@mail.com
+         subject {
+           value = Contact form
+           lang.de = Kontakt Formular
+         }
+       }
+     }
+
+     10 = TEXTLINE
+     10 {
+       name = name
+       type = text
+       required = required
+       label {
+         value = Name
+         lang.de = Name
+       }
+       placeholder {
+         value = Enter your name
+         lang.de = Name eingeben
+       }
+     }
+
+     20 = TEXTLINE
+     20 {
+       name = email
+       type = email
+       required = required
+       label {
+         value = Email
+         lang.de = E-Mail
+       }
+       placeholder {
+         value = Enter your email address
+         lang.de = E-Mail Adresse eingeben
+       }
+     }
+
+     30 = TEXTAREA
+     30 {
+       name = message
+       cols = 40
+       rows = 5
+       required = required
+       label {
+         value = Message
+         lang.de = Nachricht
+       }
+       placeholder {
+         value = Enter your message
+         lang.de = Nachricht eingeben
+       }
+     }
+
+     40 = SUBMIT
+     40 {
+       name = 5
+       type = submit
+       value {
+         value = Send
+         lang.de = Senden
+       }
+     }
+   }
\ No newline at end of file
index 81dcd57..734f32f 100644 (file)
@@ -18,6 +18,7 @@ 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;
 
@@ -30,10 +31,9 @@ class ContentObjectHook
      * Renders the application defined cObject FORM
      * which overrides the TYPO3 default cObject FORM
      *
-     * Convert FORM to COA_INT - COA_INT.10 = FORM_INT
-     * If FORM_INT is also dedected by the ContentObjectRenderer, and now
-     * the Extbaseplugin "Form" is initalized. At this time the
-     * controller "Frontend" action "execute" do the rest.
+     * 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
@@ -44,45 +44,64 @@ class ContentObjectHook
     public function cObjGetSingleExt($typoScriptObjectName, array $typoScript, $typoScriptKey, ContentObjectRenderer $contentObject)
     {
         $content = '';
-        if (
-            $typoScriptObjectName === 'FORM'
+        // 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') {
-                $bodytext = $contentObject->data['bodytext'];
-                /** @var $typoScriptParser TypoScriptParser */
-                $typoScriptParser = GeneralUtility::makeInstance(TypoScriptParser::class);
-                $typoScriptParser->parse($bodytext);
-                $mergedTypoScript = (array)$typoScriptParser->setup;
-                ArrayUtility::mergeRecursiveWithOverrule($mergedTypoScript, $typoScript);
-                // Disables content elements since TypoScript is handled that could contain insecure settings:
-                $mergedTypoScript[Configuration::DISABLE_CONTENT_ELEMENT_RENDERING] = true;
-            }
-            $newTypoScript = array(
-                '10' => 'FORM_INT',
-                '10.' => (is_array($mergedTypoScript) ? $mergedTypoScript : $typoScript),
-            );
-            $content = $contentObject->cObjGetSingle('COA_INT', $newTypoScript);
-            // Only apply stdWrap to TypoScript that was NOT created by the wizard:
-            if (isset($typoScript['stdWrap.'])) {
-                $content = $contentObject->stdWrap($content, $typoScript['stdWrap.']);
+                // 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;
+                }
             }
-        } elseif ($typoScriptObjectName === 'FORM_INT') {
-            $extbase = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Core\Bootstrap::class);
+            $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' => $typoScript),
+                '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 0f59733..e0c0a34 100644 (file)
@@ -34,6 +34,38 @@ if ($groupFound && $groupPosition) {
     \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItem('tt_content', 'CType', $additionalCTypeItem);
 }
 
+// predefined forms
+\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns(
+    'tt_content',
+    array(
+        'tx_form_predefinedform' => array(
+            'label' => 'LLL:EXT:form/Resources/Private/Language/Database.xlf:tx_form_predefinedform',
+            'exclude' => 1,
+            'config' => array(
+                'type' => 'select',
+                'items' => array(
+                    array(
+                        'LLL:EXT:form/Resources/Private/Language/Database.xlf:tx_form_predefinedform.selectPredefinedForm',
+                        ''
+                    ),
+                ),
+            ),
+        ),
+    )
+);
+$GLOBALS['TCA']['tt_content']['ctrl']['requestUpdate'] .= ',tx_form_predefinedform';
+
+// Hide bodytext if a predefined form is selected
+$GLOBALS['TCA']['tt_content']['columns']['bodytext']['displayCond']['AND'] = array(
+    'OR' => array(
+        'FIELD:CType:!=:mailform',
+        'AND' => array(
+            'FIELD:CType:=:mailform',
+            'FIELD:tx_form_predefinedform:REQ:false',
+        ),
+    ),
+);
+
 $GLOBALS['TCA']['tt_content']['columns']['bodytext']['config']['wizards']['forms'] = array(
     'notNewRecords' => 1,
     'enableByTypeConfig' => 1,
@@ -72,6 +104,7 @@ $GLOBALS['TCA']['tt_content']['types']['mailform']['showitem'] = '
        --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.header;header,rowDescription,
        --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:CType.I.8,
                bodytext;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:bodytext.ALT.mailform,
+               tx_form_predefinedform;LLL:EXT:form/Resources/Private/Language/Database.xlf:tx_form_predefinedform,
        --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.appearance,
                --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.frames;frames,
        --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access,
diff --git a/typo3/sysext/form/Resources/Private/Language/Database.xlf b/typo3/sysext/form/Resources/Private/Language/Database.xlf
new file mode 100644 (file)
index 0000000..069dedb
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.0" xmlns:t3="http://typo3.org/schemas/xliff">
+       <file t3:id="1450450398" source-language="en" datatype="plaintext" original="messages" date="2015-12-18T15:53:55Z" product-name="form">
+               <header/>
+               <body>
+                       <trans-unit id="tx_form_predefinedform">
+                               <source>Predefined form</source>
+                       </trans-unit>
+                       <trans-unit id="tx_form_predefinedform.selectPredefinedForm">
+                               <source>Choose a predefined form</source>
+                       </trans-unit>
+               </body>
+       </file>
+</xliff>
diff --git a/typo3/sysext/form/ext_tables.sql b/typo3/sysext/form/ext_tables.sql
new file mode 100644 (file)
index 0000000..21ac6fb
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Table structure for table 'tt_content'
+#
+CREATE TABLE tt_content (
+       tx_form_predefinedform varchar(255) DEFAULT '' NOT NULL,
+);