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