e55bf18d5b076d41b221bb49cb4ccde74fd60d07
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Classes / View / Wizard / WizardView.php
1 <?php
2 namespace TYPO3\CMS\Form\View\Wizard;
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\Backend\Utility\BackendUtility;
18 use TYPO3\CMS\Core\Imaging\Icon;
19 use TYPO3\CMS\Core\Imaging\IconFactory;
20 use TYPO3\CMS\Core\Messaging\FlashMessage;
21 use TYPO3\CMS\Core\Page\PageRenderer;
22 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
23 use TYPO3\CMS\Core\Utility\GeneralUtility;
24
25 /**
26 * The form wizard view
27 */
28 class WizardView extends \TYPO3\CMS\Form\View\Wizard\AbstractWizardView {
29
30 /**
31 * The document template object
32 *
33 * Needs to be a local variable of the class.
34 *
35 * @var \TYPO3\CMS\Backend\Template\DocumentTemplate
36 */
37 public $doc;
38
39 /**
40 * @var PageRenderer
41 */
42 protected $pageRenderer;
43
44 /**
45 * Constructs this view
46 *
47 * Defines the global variable SOBE. Normally this is used by the wizards
48 * which are one file only. This view is now the class with the global
49 * variable name SOBE.
50 *
51 * Defines the document template object.
52 *
53 * @param \TYPO3\CMS\Form\Domain\Repository\ContentRepository $repository
54 * @see \TYPO3\CMS\Backend\Template\DocumentTemplate
55 */
56 public function __construct(\TYPO3\CMS\Form\Domain\Repository\ContentRepository $repository) {
57 parent::__construct($repository);
58 $GLOBALS['SOBE'] = $this;
59 // Define the document template object
60 $this->doc = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Template\DocumentTemplate::class);
61 $this->doc->setModuleTemplate('EXT:form/Resources/Private/Templates/Wizard.html');
62 $this->getPageRenderer()->enableConcatenateFiles();
63 $this->getPageRenderer()->enableCompressCss();
64 $this->getPageRenderer()->enableCompressJavascript();
65 }
66
67 /**
68 * The main render method
69 *
70 * Gathers all content and echos it to the screen
71 *
72 * @return void
73 */
74 public function render() {
75 $docHeaderButtons = array();
76 // Check if the referenced record is available
77 $this->recordIsAvailable = $this->repository->hasRecord();
78 if ($this->recordIsAvailable) {
79 // Load necessary JavaScript
80 $this->loadJavascript();
81 // Load necessary CSS
82 $this->loadCss();
83 // Load the settings
84 $this->loadSettings();
85 // Localization
86 $this->loadLocalization();
87 // Setting up the buttons and markers for docheader
88 $docHeaderButtons = $this->getButtons();
89 $markers['CSH'] = $docHeaderButtons['csh'];
90 // Hook
91 $this->callRenderHook();
92 }
93 // Getting the body content
94 $markers['CONTENT'] = $this->getBodyContent();
95 // Build the HTML for the module
96 $content = $this->doc->startPage($this->getLanguageService()->getLL('title', TRUE));
97 $content .= $this->doc->moduleBody(array(), $docHeaderButtons, $markers);
98 $content .= $this->doc->endPage();
99 $content = $this->doc->insertStylesAndJS($content);
100
101 echo $content;
102 die;
103 }
104
105 /**
106 * Load the necessarry javascript
107 *
108 * This will only be done when the referenced record is available
109 *
110 * @return void
111 */
112 protected function loadJavascript() {
113 $compress = TRUE;
114 $javascriptFiles = array(
115 'Initialize.js',
116 'Ux/Ext.ux.merge.js',
117 'Ux/Ext.ux.isemptyobject.js',
118 'Ux/Ext.ux.spinner.js',
119 'Ux/Ext.ux.form.spinnerfield.js',
120 'Ux/Ext.ux.form.textfieldsubmit.js',
121 'Ux/Ext.ux.grid.CheckColumn.js',
122 'Ux/Ext.ux.grid.SingleSelectCheckColumn.js',
123 'Ux/Ext.ux.grid.ItemDeleter.js',
124 'Helpers/History.js',
125 'Helpers/Element.js',
126 'Elements/ButtonGroup.js',
127 'Elements/Container.js',
128 'Elements/Elements.js',
129 'Elements/Dummy.js',
130 'Elements/Basic/Button.js',
131 'Elements/Basic/Checkbox.js',
132 'Elements/Basic/Fieldset.js',
133 'Elements/Basic/Fileupload.js',
134 'Elements/Basic/Form.js',
135 'Elements/Basic/Hidden.js',
136 'Elements/Basic/Password.js',
137 'Elements/Basic/Radio.js',
138 'Elements/Basic/Reset.js',
139 'Elements/Basic/Select.js',
140 'Elements/Basic/Submit.js',
141 'Elements/Basic/Textarea.js',
142 'Elements/Basic/Textline.js',
143 'Elements/Predefined/Email.js',
144 'Elements/Predefined/CheckboxGroup.js',
145 'Elements/Predefined/Name.js',
146 'Elements/Predefined/RadioGroup.js',
147 'Elements/Content/Header.js',
148 'Elements/Content/Textblock.js',
149 'Viewport.js',
150 'Viewport/Left.js',
151 'Viewport/Right.js',
152 'Viewport/Left/Elements.js',
153 'Viewport/Left/Elements/ButtonGroup.js',
154 'Viewport/Left/Elements/Basic.js',
155 'Viewport/Left/Elements/Predefined.js',
156 'Viewport/Left/Elements/Content.js',
157 'Viewport/Left/Options.js',
158 'Viewport/Left/Options/Dummy.js',
159 'Viewport/Left/Options/Panel.js',
160 'Viewport/Left/Options/Forms/Attributes.js',
161 'Viewport/Left/Options/Forms/Label.js',
162 'Viewport/Left/Options/Forms/Legend.js',
163 'Viewport/Left/Options/Forms/Options.js',
164 'Viewport/Left/Options/Forms/Various.js',
165 'Viewport/Left/Options/Forms/Filters.js',
166 'Viewport/Left/Options/Forms/Filters/Filter.js',
167 'Viewport/Left/Options/Forms/Filters/Dummy.js',
168 'Viewport/Left/Options/Forms/Filters/Alphabetic.js',
169 'Viewport/Left/Options/Forms/Filters/Alphanumeric.js',
170 'Viewport/Left/Options/Forms/Filters/Currency.js',
171 'Viewport/Left/Options/Forms/Filters/Digit.js',
172 'Viewport/Left/Options/Forms/Filters/Integer.js',
173 'Viewport/Left/Options/Forms/Filters/LowerCase.js',
174 'Viewport/Left/Options/Forms/Filters/RegExp.js',
175 'Viewport/Left/Options/Forms/Filters/RemoveXSS.js',
176 'Viewport/Left/Options/Forms/Filters/StripNewLines.js',
177 'Viewport/Left/Options/Forms/Filters/TitleCase.js',
178 'Viewport/Left/Options/Forms/Filters/Trim.js',
179 'Viewport/Left/Options/Forms/Filters/UpperCase.js',
180 'Viewport/Left/Options/Forms/Validation.js',
181 'Viewport/Left/Options/Forms/Validation/Rule.js',
182 'Viewport/Left/Options/Forms/Validation/Dummy.js',
183 'Viewport/Left/Options/Forms/Validation/Alphabetic.js',
184 'Viewport/Left/Options/Forms/Validation/Alphanumeric.js',
185 'Viewport/Left/Options/Forms/Validation/Between.js',
186 'Viewport/Left/Options/Forms/Validation/Date.js',
187 'Viewport/Left/Options/Forms/Validation/Digit.js',
188 'Viewport/Left/Options/Forms/Validation/Email.js',
189 'Viewport/Left/Options/Forms/Validation/Equals.js',
190 'Viewport/Left/Options/Forms/Validation/FileAllowedTypes.js',
191 'Viewport/Left/Options/Forms/Validation/FileMaximumSize.js',
192 'Viewport/Left/Options/Forms/Validation/FileMinimumSize.js',
193 'Viewport/Left/Options/Forms/Validation/Float.js',
194 'Viewport/Left/Options/Forms/Validation/GreaterThan.js',
195 'Viewport/Left/Options/Forms/Validation/InArray.js',
196 'Viewport/Left/Options/Forms/Validation/Integer.js',
197 'Viewport/Left/Options/Forms/Validation/Ip.js',
198 'Viewport/Left/Options/Forms/Validation/Length.js',
199 'Viewport/Left/Options/Forms/Validation/LessThan.js',
200 'Viewport/Left/Options/Forms/Validation/RegExp.js',
201 'Viewport/Left/Options/Forms/Validation/Required.js',
202 'Viewport/Left/Options/Forms/Validation/Uri.js',
203 'Viewport/Left/Form.js',
204 'Viewport/Left/Form/Behaviour.js',
205 'Viewport/Left/Form/Attributes.js',
206 'Viewport/Left/Form/Prefix.js',
207 'Viewport/Left/Form/PostProcessor.js',
208 'Viewport/Left/Form/PostProcessors/PostProcessor.js',
209 'Viewport/Left/Form/PostProcessors/Dummy.js',
210 'Viewport/Left/Form/PostProcessors/Mail.js',
211 'Viewport/Left/Form/PostProcessors/Redirect.js'
212 );
213 // Load ExtJS
214 $this->pageRenderer->loadExtJS();
215 // Load the wizards javascript
216 $baseUrl = ExtensionManagementUtility::extRelPath('form') . 'Resources/Public/JavaScript/Wizard/';
217 foreach ($javascriptFiles as $javascriptFile) {
218 $this->pageRenderer->addJsFile($baseUrl . $javascriptFile, 'text/javascript', $compress, FALSE);
219 }
220 }
221
222 /**
223 * Load the necessarry css
224 *
225 * This will only be done when the referenced record is available
226 *
227 * @return void
228 */
229 protected function loadCss() {
230 // @todo Set to TRUE when finished
231 $compress = FALSE;
232 $cssFiles = array(
233 'Wizard/Form.css',
234 'Wizard/Wizard.css'
235 );
236 $baseUrl = ExtensionManagementUtility::extRelPath('form') . 'Resources/Public/CSS/';
237 // Load the wizards css
238 foreach ($cssFiles as $cssFile) {
239 $this->pageRenderer->addCssFile($baseUrl . $cssFile, 'stylesheet', 'all', '', $compress, FALSE);
240 }
241 }
242
243 /**
244 * Load the settings
245 *
246 * The settings are defined in pageTSconfig mod.wizards.form
247 *
248 * @return void
249 */
250 protected function loadSettings() {
251 $record = $this->repository->getRecord();
252 $pageId = $record->getPageId();
253 $modTSconfig = BackendUtility::getModTSconfig($pageId, 'mod.wizards.form');
254 $settings = $modTSconfig['properties'];
255 $this->removeTrailingDotsFromTyposcript($settings);
256 $this->doc->JScode .= $this->doc->wrapScriptTags('TYPO3.Form.Wizard.Settings = ' . json_encode($settings) . ';');
257 }
258
259 /**
260 * Reads locallang file into array (for possible include in header)
261 *
262 * @return void
263 */
264 protected function loadLocalization() {
265 $wizardLabels = $this->getLanguageService()->includeLLFile('EXT:form/Resources/Private/Language/locallang_wizard.xlf', FALSE, TRUE);
266 $controllerLabels = $this->getLanguageService()->includeLLFile('EXT:form/Resources/Private/Language/locallang_controller.xlf', FALSE, TRUE);
267 \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($controllerLabels, $wizardLabels);
268 $this->pageRenderer->addInlineLanguageLabelArray($controllerLabels['default']);
269 }
270
271 /**
272 * Hook to extend the wizard interface.
273 *
274 * The hook is called just before content rendering. Use it by adding your function to the array
275 * $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['form']['hooks']['renderWizard']
276 *
277 * @return void
278 */
279 protected function callRenderHook() {
280 $params = array();
281 if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['form']['hooks']['renderWizard'])) {
282 foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['form']['hooks']['renderWizard'] as $funcRef) {
283 GeneralUtility::callUserFunction($funcRef, $params, $this);
284 }
285 }
286 }
287
288 /**
289 * Remove the trailing dots from the values in Typoscript
290 *
291 * @param array $array The array with the trailing dots
292 * @return void
293 */
294 protected function removeTrailingDotsFromTyposcript(array &$array) {
295 foreach ($array as $key => $value) {
296 if (is_array($value)) {
297 $this->removeTrailingDotsFromTyposcript($value);
298 }
299 if (substr($key, -1) === '.') {
300 $newKey = substr($key, 0, -1);
301 unset($array[$key]);
302 $array[$newKey] = $value;
303 }
304 }
305 }
306
307 /**
308 * Create the panel of buttons for submitting the form or otherwise perform
309 * operations.
310 *
311 * @return array all available buttons as an assoc. array
312 */
313 protected function getButtons() {
314 /** @var IconFactory $iconFactory */
315 $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
316
317 $buttons = array(
318 'csh' => '',
319 'csh_buttons' => '',
320 'close' => '',
321 'save' => '',
322 'save_close' => '',
323 'reload' => ''
324 );
325 // CSH
326 $buttons['csh'] = BackendUtility::cshItem('xMOD_csh_corebe', 'wizard_forms_wiz');
327 // CSH Buttons
328 $buttons['csh_buttons'] = BackendUtility::cshItem('xMOD_csh_corebe', 'wizard_forms_wiz_buttons');
329 // Close
330 $getPostVariables = GeneralUtility::_GP('P');
331 $title = 'title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:rm.closeDoc', TRUE) . '"';
332 $onClick = htmlspecialchars('jumpToUrl(unescape(\'' .
333 rawurlencode(GeneralUtility::sanitizeLocalUrl($getPostVariables['returnUrl'])) . '\')); return false;');
334 $buttons['close'] = '<a href="#" onclick="' . $onClick . '" ' . $title . '>' .
335 $iconFactory->getIcon('actions-document-close', Icon::SIZE_SMALL) . '</a>';
336 return $buttons;
337 }
338
339 /**
340 * Generate the body content
341 *
342 * If there is an error, no reference to a record, a Flash Message will be
343 * displayed
344 *
345 * @return string The body content
346 */
347 protected function getBodyContent() {
348 if ($this->recordIsAvailable) {
349 $bodyContent = '';
350 } else {
351 /** @var $flashMessage FlashMessage */
352 $flashMessage = GeneralUtility::makeInstance(FlashMessage::class,
353 $this->getLanguageService()->getLL('errorMessage', TRUE),
354 $this->getLanguageService()->getLL('errorTitle', TRUE),
355 FlashMessage::ERROR);
356 $bodyContent = $flashMessage->render();
357 }
358 return $bodyContent;
359 }
360
361 /**
362 * @return PageRenderer
363 */
364 protected function getPageRenderer() {
365 if (!isset($this->pageRenderer)) {
366 $this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
367 }
368
369 return $this->pageRenderer;
370 }
371
372 }