Test Failed
Branch master (137376)
by Tymoteusz
20:39
created

FormResultCompiler::printNeededJSFunctions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
1
<?php
2
namespace TYPO3\CMS\Backend\Form;
3
4
/*
5
 * This file is part of the TYPO3 CMS project.
6
 *
7
 * It is free software; you can redistribute it and/or modify it under
8
 * the terms of the GNU General Public License, either version 2
9
 * of the License, or any later version.
10
 *
11
 * For the full copyright and license information, please read the
12
 * LICENSE.txt file that was distributed with this source code.
13
 *
14
 * The TYPO3 project - inspiring people to share!
15
 */
16
17
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
18
use TYPO3\CMS\Core\Page\PageRenderer;
19
use TYPO3\CMS\Core\Utility\ArrayUtility;
20
use TYPO3\CMS\Core\Utility\GeneralUtility;
21
22
/**
23
 * This is form engine - Class for creating the backend editing forms.
24
 *
25
 * @internal This class and its exposed method and method signatures will change
26
 */
27
class FormResultCompiler
28
{
29
    /**
30
     * @var array HTML of additional hidden fields rendered by sub containers
31
     */
32
    protected $hiddenFieldAccum = [];
33
34
    /**
35
     * Can be set to point to a field name in the form which will be set to '1' when the form
36
     * is submitted with a *save* button. This way the recipient script can determine that
37
     * the form was submitted for save and not "close" for example.
38
     *
39
     * @var string
40
     */
41
    protected $doSaveFieldName = '';
42
43
    /**
44
     * @var array Data array from IRRE pushed to frontend as json array
45
     */
46
    protected $inlineData = [];
47
48
    /**
49
     * List of additional style sheet files to load
50
     *
51
     * @var array
52
     */
53
    protected $stylesheetFiles = [];
54
55
    /**
56
     * Additional JavaScript printed after the form
57
     *
58
     * @var array
59
     */
60
    protected $additionalJavaScriptPost = [];
61
62
    /**
63
     * Additional JavaScript executed on submit; If you set "OK" variable it will raise an error
64
     * about RTEs not being loaded and offer to block further submission.
65
     *
66
     * @var array
67
     */
68
    protected $additionalJavaScriptSubmit = [];
69
70
    /**
71
     * Additional language label files to include.
72
     *
73
     * @var array
74
     */
75
    protected $additionalInlineLanguageLabelFiles = [];
76
77
    /**
78
     * Array with requireJS modules, use module name as key, the value could be callback code.
79
     * Use NULL as value if no callback is used.
80
     *
81
     * @var array
82
     */
83
    protected $requireJsModules = [];
84
85
    /**
86
     * @var PageRenderer
87
     */
88
    protected $pageRenderer = null;
89
90
    /**
91
     * Merge existing data with the given result array
92
     *
93
     * @param array $resultArray Array returned by child
94
     * @internal Temporary method to use FormEngine class as final data merger
95
     */
96
    public function mergeResult(array $resultArray)
97
    {
98
        $this->doSaveFieldName = $resultArray['doSaveFieldName'];
99
        foreach ($resultArray['additionalJavaScriptPost'] as $element) {
100
            $this->additionalJavaScriptPost[] = $element;
101
        }
102
        foreach ($resultArray['additionalJavaScriptSubmit'] as $element) {
103
            $this->additionalJavaScriptSubmit[] = $element;
104
        }
105
        if (!empty($resultArray['requireJsModules'])) {
106
            foreach ($resultArray['requireJsModules'] as $module) {
107
                $moduleName = null;
108
                $callback = null;
109
                if (is_string($module)) {
110
                    // if $module is a string, no callback
111
                    $moduleName = $module;
112
                    $callback = null;
113
                } elseif (is_array($module)) {
114
                    // if $module is an array, callback is possible
115
                    foreach ($module as $key => $value) {
116
                        $moduleName = $key;
117
                        $callback = $value;
118
                        break;
119
                    }
120
                }
121
                if ($moduleName !== null) {
122
                    if (!empty($this->requireJsModules[$moduleName]) && $callback !== null) {
123
                        $existingValue = $this->requireJsModules[$moduleName];
124
                        if (!is_array($existingValue)) {
125
                            $existingValue = [$existingValue];
126
                        }
127
                        $existingValue[] = $callback;
128
                        $this->requireJsModules[$moduleName] = $existingValue;
129
                    } else {
130
                        $this->requireJsModules[$moduleName] = $callback;
131
                    }
132
                }
133
            }
134
        }
135
136
        foreach ($resultArray['additionalHiddenFields'] as $element) {
137
            $this->hiddenFieldAccum[] = $element;
138
        }
139
        foreach ($resultArray['stylesheetFiles'] as $stylesheetFile) {
140
            if (!in_array($stylesheetFile, $this->stylesheetFiles)) {
141
                $this->stylesheetFiles[] = $stylesheetFile;
142
            }
143
        }
144
145
        if (!empty($resultArray['inlineData'])) {
146
            $resultArrayInlineData = $this->inlineData;
147
            $resultInlineData = $resultArray['inlineData'];
148
            ArrayUtility::mergeRecursiveWithOverrule($resultArrayInlineData, $resultInlineData);
149
            $this->inlineData = $resultArrayInlineData;
150
        }
151
152
        if (!empty($resultArray['additionalInlineLanguageLabelFiles'])) {
153
            foreach ($resultArray['additionalInlineLanguageLabelFiles'] as $additionalInlineLanguageLabelFile) {
154
                $this->additionalInlineLanguageLabelFiles[] = $additionalInlineLanguageLabelFile;
155
            }
156
        }
157
    }
158
159
    /**
160
     * Adds CSS files BEFORE the form is drawn
161
     *
162
     * @return string
163
     */
164
    public function addCssFiles()
165
    {
166
        $pageRenderer = $this->getPageRenderer();
167
        foreach ($this->stylesheetFiles as $stylesheetFile) {
168
            $pageRenderer->addCssFile($stylesheetFile);
169
        }
170
        return '';
171
    }
172
173
    /**
174
     * Prints necessary JavaScript for TCEforms (after the form HTML).
175
     * currently this is used to transform page-specific options in the TYPO3.Settings array for JS
176
     * so the JS module can access these values
177
     *
178
     * @return string
179
     */
180
    public function printNeededJSFunctions()
181
    {
182
        // set variables to be accessible for JS
183
        $pageRenderer = $this->getPageRenderer();
184
        $pageRenderer->addInlineSetting('FormEngine', 'formName', 'editform');
185
186
        return $this->JSbottom();
187
    }
188
189
    /**
190
     * JavaScript bottom code
191
     *
192
     * @return string A section with JavaScript - if $update is FALSE, embedded in <script></script>
193
     */
194
    protected function JSbottom()
195
    {
196
        $pageRenderer = $this->getPageRenderer();
197
        /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
198
        $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
199
200
        // @todo: this is messy here - "additional hidden fields" should be handled elsewhere
201
        $html = implode(LF, $this->hiddenFieldAccum);
202
        $pageRenderer->addJsFile('EXT:backend/Resources/Public/JavaScript/md5.js');
203
        // load the main module for FormEngine with all important JS functions
204
        $this->requireJsModules['TYPO3/CMS/Backend/FormEngine'] = 'function(FormEngine) {
205
			FormEngine.initialize(
206
				' . GeneralUtility::quoteJSvalue((string)$uriBuilder->buildUriFromRoute('wizard_element_browser')) . ',
207
				' . ($GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? '1' : '0') . '
208
			);
209
		}';
210
        $this->requireJsModules['TYPO3/CMS/Backend/FormEngineReview'] = null;
211
212
        foreach ($this->requireJsModules as $moduleName => $callbacks) {
213
            if (!is_array($callbacks)) {
214
                $callbacks = [$callbacks];
215
            }
216
            foreach ($callbacks as $callback) {
217
                $pageRenderer->loadRequireJsModule($moduleName, $callback);
218
            }
219
        }
220
        $pageRenderer->loadJquery();
221
        $beUserAuth = $this->getBackendUserAuthentication();
222
223
        // define the window size of the element browser etc.
224
        $popupWindowWidth  = 800;
225
        $popupWindowHeight = 600;
226
        $popupWindowSize = trim($beUserAuth->getTSConfigVal('options.popupWindowSize'));
227
        if (!empty($popupWindowSize)) {
228
            list($popupWindowWidth, $popupWindowHeight) = GeneralUtility::intExplode('x', $popupWindowSize);
229
        }
230
231
        // define the window size of the popups within the RTE
232
        $rtePopupWindowSize = trim($beUserAuth->getTSConfigVal('options.rte.popupWindowSize'));
233
        if (!empty($rtePopupWindowSize)) {
234
            list($rtePopupWindowWidth, $rtePopupWindowHeight) = GeneralUtility::trimExplode('x', $rtePopupWindowSize);
235
        }
236
        $rtePopupWindowWidth  = !empty($rtePopupWindowWidth) ? (int)$rtePopupWindowWidth : ($popupWindowWidth);
237
        $rtePopupWindowHeight = !empty($rtePopupWindowHeight) ? (int)$rtePopupWindowHeight : ($popupWindowHeight);
238
239
        // Make textareas resizable and flexible ("autogrow" in height)
240
        $textareaSettings = [
241
            'autosize'  => (bool)$beUserAuth->uc['resizeTextareas_Flexible'],
242
            'RTEPopupWindow' => [
243
                'width' => $rtePopupWindowWidth,
244
                'height' => $rtePopupWindowHeight
245
            ]
246
        ];
247
        $pageRenderer->addInlineSettingArray('Textarea', $textareaSettings);
248
249
        $popupSettings = [
250
            'PopupWindow' => [
251
                'width' => $popupWindowWidth,
252
                'height' => $popupWindowHeight
253
            ]
254
        ];
255
        $pageRenderer->addInlineSettingArray('Popup', $popupSettings);
256
257
        $pageRenderer->addJsFile('EXT:backend/Resources/Public/JavaScript/jsfunc.tbe_editor.js');
258
        // Needed for FormEngine manipulation (date picker)
259
        $dateFormat = ($GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? ['MM-DD-YYYY', 'HH:mm MM-DD-YYYY'] : ['DD-MM-YYYY', 'HH:mm DD-MM-YYYY']);
260
        $pageRenderer->addInlineSetting('DateTimePicker', 'DateFormat', $dateFormat);
0 ignored issues
show
Bug introduced by
$dateFormat of type array<integer,string> is incompatible with the type string expected by parameter $value of TYPO3\CMS\Core\Page\Page...rer::addInlineSetting(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

260
        $pageRenderer->addInlineSetting('DateTimePicker', 'DateFormat', /** @scrutinizer ignore-type */ $dateFormat);
Loading history...
261
262
        $pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileListLocalisation');
263
264
        $pageRenderer->addInlineLanguageLabelFile('EXT:lang/Resources/Private/Language/locallang_core.xlf', 'file_upload');
265
        if (!empty($this->additionalInlineLanguageLabelFiles)) {
266
            foreach ($this->additionalInlineLanguageLabelFiles as $additionalInlineLanguageLabelFile) {
267
                $pageRenderer->addInlineLanguageLabelFile($additionalInlineLanguageLabelFile);
268
            }
269
        }
270
        // We want to load jQuery-ui inside our js. Enable this using requirejs.
271
        $pageRenderer->addJsFile('EXT:backend/Resources/Public/JavaScript/jsfunc.inline.js');
272
273
        // todo: change these things in JS
274
        $pageRenderer->addInlineLanguageLabelArray([
275
            'FormEngine.noRecordTitle'          => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.no_title',
276
            'FormEngine.fieldsChanged'          => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.fieldsChanged',
277
            'FormEngine.fieldsMissing'          => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.fieldsMissing',
278
            'FormEngine.maxItemsAllowed'        => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.maxItemsAllowed',
279
            'FormEngine.refreshRequiredTitle'   => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:mess.refreshRequired.title',
280
            'FormEngine.refreshRequiredContent' => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:mess.refreshRequired.content',
281
            'FormEngine.remainingCharacters'    => 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.remainingCharacters',
282
        ], true);
283
284
        $out = LF . 'TBE_EDITOR.doSaveFieldName = "' . ($this->doSaveFieldName ? addslashes($this->doSaveFieldName) : '') . '";';
285
286
        // Add JS required for inline fields
287
        if (!empty($this->inlineData)) {
288
            $out .= LF . 'inline.addToDataArray(' . json_encode($this->inlineData) . ');';
289
        }
290
        // $this->additionalJS_submit:
291
        if ($this->additionalJavaScriptSubmit) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->additionalJavaScriptSubmit of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
292
            $additionalJS_submit = implode('', $this->additionalJavaScriptSubmit);
293
            $additionalJS_submit = str_replace([CR, LF], '', $additionalJS_submit);
294
            $out .= 'TBE_EDITOR.addActionChecks("submit", "' . addslashes($additionalJS_submit) . '");';
295
        }
296
        $out .= LF . implode(LF, $this->additionalJavaScriptPost);
297
298
        return $html . LF . TAB . GeneralUtility::wrapJS($out);
299
    }
300
301
    /**
302
     * @return BackendUserAuthentication
303
     */
304
    protected function getBackendUserAuthentication()
305
    {
306
        return $GLOBALS['BE_USER'];
307
    }
308
309
    /**
310
     * Wrapper for access to the current page renderer object
311
     *
312
     * @return \TYPO3\CMS\Core\Page\PageRenderer
313
     */
314 View Code Duplication
    protected function getPageRenderer()
315
    {
316
        if ($this->pageRenderer === null) {
317
            $this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
318
        }
319
        return $this->pageRenderer;
320
    }
321
}
322