[TASK] Use strict comparison for strings
[Packages/TYPO3.CMS.git] / typo3 / sysext / tstemplate / Classes / Controller / TypoScriptTemplateObjectBrowserModuleFunctionController.php
1 <?php
2 namespace TYPO3\CMS\Tstemplate\Controller;
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\Module\AbstractFunctionModule;
18 use TYPO3\CMS\Backend\Utility\BackendUtility;
19 use TYPO3\CMS\Core\DataHandling\DataHandler;
20 use TYPO3\CMS\Core\Exception;
21 use TYPO3\CMS\Core\Messaging\FlashMessage;
22 use TYPO3\CMS\Core\Messaging\FlashMessageService;
23 use TYPO3\CMS\Core\TypoScript\ExtendedTemplateService;
24 use TYPO3\CMS\Core\Utility\GeneralUtility;
25 use TYPO3\CMS\Fluid\View\StandaloneView;
26 use TYPO3\CMS\Frontend\Page\PageRepository;
27
28 /**
29 * This class displays the submodule "TypoScript Object Browser" inside the Web > Template module
30 */
31 class TypoScriptTemplateObjectBrowserModuleFunctionController extends AbstractFunctionModule
32 {
33 /**
34 * @var string
35 */
36 protected $localLanguageFilePath;
37
38 /**
39 * @var TypoScriptTemplateModuleController
40 */
41 public $pObj;
42
43 /**
44 * The currently selected sys_template record
45 * @var array
46 */
47 protected $templateRow;
48
49 /**
50 * @var ExtendedTemplateService
51 */
52 protected $templateService;
53
54 /**
55 * Init
56 *
57 * @param TypoScriptTemplateModuleController $pObj
58 * @param array $conf
59 * @return void
60 */
61 public function init(&$pObj, $conf)
62 {
63 parent::init($pObj, $conf);
64 $this->pObj->modMenu_dontValidateList .= ',ts_browser_toplevel_setup,ts_browser_toplevel_const,ts_browser_TLKeys_setup,ts_browser_TLKeys_const';
65 $this->pObj->modMenu_setDefaultList .= ',ts_browser_fixedLgd,ts_browser_showComments';
66 $this->localLanguageFilePath = 'EXT:tstemplate/Resources/Private/Language/locallang_objbrowser.xlf';
67 }
68
69 /**
70 * Mod menu
71 *
72 * @return array
73 */
74 public function modMenu()
75 {
76 $lang = $this->getLanguageService();
77 $lang->includeLLFile('EXT:tstemplate/Resources/Private/Language/locallang_objbrowser.xlf');
78 $modMenu = [
79 'ts_browser_type' => [
80 'const' => $lang->getLL('constants'),
81 'setup' => $lang->getLL('setup')
82 ],
83 'ts_browser_toplevel_setup' => [
84 '0' => mb_strtolower($lang->getLL('all'), 'utf-8')
85 ],
86 'ts_browser_toplevel_const' => [
87 '0' => mb_strtolower($lang->getLL('all'), 'utf-8')
88 ],
89 'ts_browser_const' => [
90 '0' => $lang->getLL('plainSubstitution'),
91 'subst' => $lang->getLL('substitutedGreen'),
92 'const' => $lang->getLL('unsubstitutedGreen')
93 ],
94 'ts_browser_regexsearch' => '1',
95 'ts_browser_fixedLgd' => '1',
96 'ts_browser_showComments' => '1',
97 'ts_browser_alphaSort' => '1'
98 ];
99 foreach (['setup', 'const'] as $bType) {
100 $addKey = GeneralUtility::_GET('addKey');
101 // If any plus-signs were clicked, it's registered.
102 if (is_array($addKey)) {
103 reset($addKey);
104 if (current($addKey)) {
105 $this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType][key($addKey)] = key($addKey);
106 } else {
107 unset($this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType][key($addKey)]);
108 }
109 $this->getBackendUserAuthentication()->pushModuleData($this->pObj->MCONF['name'], $this->pObj->MOD_SETTINGS);
110 }
111 if (!empty($this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType])) {
112 $modMenu['ts_browser_toplevel_' . $bType]['-'] = '---';
113 $modMenu['ts_browser_toplevel_' . $bType] = $modMenu['ts_browser_toplevel_' . $bType] + $this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType];
114 }
115 }
116 return $modMenu;
117 }
118
119 /**
120 * Initialize editor
121 *
122 * Initializes the module. Done in this function because we may need to re-initialize if data is submitted!
123 *
124 * @param int $pageId
125 * @param int $template_uid
126 * @return bool
127 */
128 public function initialize_editor($pageId, $template_uid = 0)
129 {
130 // Defined global here!
131 $this->templateService = GeneralUtility::makeInstance(ExtendedTemplateService::class);
132 $this->templateService->init();
133
134 // Gets the rootLine
135 $sys_page = GeneralUtility::makeInstance(PageRepository::class);
136 $rootLine = $sys_page->getRootLine($pageId);
137 // This generates the constants/config + hierarchy info for the template.
138 $this->templateService->runThroughTemplates($rootLine, $template_uid);
139
140 // Get the row of the first VISIBLE template of the page. whereclause like the frontend.
141 $this->templateRow = $this->templateService->ext_getFirstTemplate($pageId, $template_uid);
142 return is_array($this->templateRow);
143 }
144
145 /**
146 * Main
147 *
148 * @return string
149 */
150 public function main()
151 {
152 $lang = $this->getLanguageService();
153 $POST = GeneralUtility::_POST();
154
155 // Checking for more than one template an if, set a menu...
156 $manyTemplatesMenu = $this->pObj->templateMenu();
157 $template_uid = 0;
158 if ($manyTemplatesMenu) {
159 $template_uid = $this->pObj->MOD_SETTINGS['templatesOnPage'];
160 }
161 $bType = $this->pObj->MOD_SETTINGS['ts_browser_type'];
162 $existTemplate = $this->initialize_editor($this->pObj->id, $template_uid);
163 // initialize
164 $assigns = [];
165 $assigns['LLPrefix'] = 'LLL:' . $this->localLanguageFilePath . ':';
166 $assigns['existTemplate'] = $existTemplate;
167 $assigns['tsBrowserType'] = $this->pObj->MOD_SETTINGS['ts_browser_type'];
168 if ($existTemplate) {
169 $assigns['templateRecord'] = $this->templateRow;
170 $assigns['linkWrapTemplateTitle'] = $this->pObj->linkWrapTemplateTitle($this->templateRow['title'], ($bType === 'setup' ? 'config' : 'constants'));
171 $assigns['manyTemplatesMenu'] = $manyTemplatesMenu;
172
173 if ($POST['add_property'] || $POST['update_value'] || $POST['clear_object']) {
174 // add property
175 $line = '';
176 if (is_array($POST['data'])) {
177 $name = key($POST['data']);
178 if ($POST['data'][$name]['name'] !== '') {
179 // Workaround for this special case: User adds a key and submits by pressing the return key. The form however will use "add_property" which is the name of the first submit button in this form.
180 unset($POST['update_value']);
181 $POST['add_property'] = 'Add';
182 }
183 if ($POST['add_property']) {
184 $property = trim($POST['data'][$name]['name']);
185 if (preg_replace('/[^a-zA-Z0-9_\\.]*/', '', $property) != $property) {
186 $badPropertyMessage = GeneralUtility::makeInstance(FlashMessage::class, $lang->getLL('noSpaces') . $lang->getLL('nothingUpdated'), $lang->getLL('badProperty'), FlashMessage::ERROR);
187 $this->addFlashMessage($badPropertyMessage);
188 } else {
189 $pline = $name . '.' . $property . ' = ' . trim($POST['data'][$name]['propertyValue']);
190 $propertyAddedMessage = GeneralUtility::makeInstance(FlashMessage::class, $pline, $lang->getLL('propertyAdded'));
191 $this->addFlashMessage($propertyAddedMessage);
192 $line .= LF . $pline;
193 }
194 } elseif ($POST['update_value']) {
195 $pline = $name . ' = ' . trim($POST['data'][$name]['value']);
196 $updatedMessage = GeneralUtility::makeInstance(FlashMessage::class, $pline, $lang->getLL('valueUpdated'));
197 $this->addFlashMessage($updatedMessage);
198 $line .= LF . $pline;
199 } elseif ($POST['clear_object']) {
200 if ($POST['data'][$name]['clearValue']) {
201 $pline = $name . ' >';
202 $objectClearedMessage = GeneralUtility::makeInstance(FlashMessage::class, $pline, $lang->getLL('objectCleared'));
203 $this->addFlashMessage($objectClearedMessage);
204 $line .= LF . $pline;
205 }
206 }
207 }
208 if ($line) {
209 $saveId = $this->templateRow['_ORIG_uid'] ?: $this->templateRow['uid'];
210 // Set the data to be saved
211 $recData = [];
212 $field = $bType === 'setup' ? 'config' : 'constants';
213 $recData['sys_template'][$saveId][$field] = $this->templateRow[$field] . $line;
214 // Create new tce-object
215 $tce = GeneralUtility::makeInstance(DataHandler::class);
216 // Initialize
217 $tce->start($recData, []);
218 // Saved the stuff
219 $tce->process_datamap();
220 // Clear the cache (note: currently only admin-users can clear the cache in tce_main.php)
221 $tce->clear_cacheCmd('all');
222 // re-read the template ...
223 $this->initialize_editor($this->pObj->id, $template_uid);
224 }
225 }
226 }
227 $tsbr = GeneralUtility::_GET('tsbr');
228 $update = 0;
229 if (is_array($tsbr)) {
230 // If any plus-signs were clicked, it's registred.
231 $this->pObj->MOD_SETTINGS['tsbrowser_depthKeys_' . $bType] = $this->templateService->ext_depthKeys($tsbr, $this->pObj->MOD_SETTINGS['tsbrowser_depthKeys_' . $bType]);
232 $update = 1;
233 }
234 if ($POST['Submit']) {
235 // If any POST-vars are send, update the condition array
236 $this->pObj->MOD_SETTINGS['tsbrowser_conditions'] = $POST['conditions'];
237 $update = 1;
238 }
239 if ($update) {
240 $this->getBackendUserAuthentication()->pushModuleData($this->pObj->MCONF['name'], $this->pObj->MOD_SETTINGS);
241 }
242 $this->templateService->matchAlternative = $this->pObj->MOD_SETTINGS['tsbrowser_conditions'];
243 $this->templateService->matchAlternative[] = 'dummydummydummydummydummydummydummydummydummydummydummy';
244 // This is just here to make sure that at least one element is in the array so that the tsparser actually uses this array to match.
245 $this->templateService->constantMode = $this->pObj->MOD_SETTINGS['ts_browser_const'];
246 if ($this->pObj->sObj && $this->templateService->constantMode) {
247 $this->templateService->constantMode = 'untouched';
248 }
249 $this->templateService->regexMode = $this->pObj->MOD_SETTINGS['ts_browser_regexsearch'];
250 $this->templateService->fixedLgd = $this->pObj->MOD_SETTINGS['ts_browser_fixedLgd'];
251 $this->templateService->linkObjects = true;
252 $this->templateService->ext_regLinenumbers = true;
253 $this->templateService->ext_regComments = $this->pObj->MOD_SETTINGS['ts_browser_showComments'];
254 $this->templateService->bType = $bType;
255 if ($this->pObj->MOD_SETTINGS['ts_browser_type'] === 'const') {
256 $this->templateService->ext_constants_BRP = (int)GeneralUtility::_GP('breakPointLN');
257 } else {
258 $this->templateService->ext_config_BRP = (int)GeneralUtility::_GP('breakPointLN');
259 }
260 $this->templateService->generateConfig();
261 if ($bType === 'setup') {
262 $theSetup = $this->templateService->setup;
263 } else {
264 $theSetup = $this->templateService->setup_constants;
265 }
266 // EDIT A VALUE:
267 $assigns['typoScriptPath'] = $this->pObj->sObj;
268 if ($this->pObj->sObj) {
269 list($theSetup, $theSetupValue) = $this->templateService->ext_getSetup($theSetup, $this->pObj->sObj ? $this->pObj->sObj : '');
270 $assigns['theSetupValue'] = $theSetupValue;
271 if ($existTemplate === false) {
272 $noTemplateMessage = GeneralUtility::makeInstance(FlashMessage::class, $lang->getLL('noCurrentTemplate'), $lang->getLL('edit'), FlashMessage::ERROR);
273 $this->addFlashMessage($noTemplateMessage);
274 }
275 // Links:
276 $urlParameters = [
277 'id' => $this->pObj->id
278 ];
279 $aHref = BackendUtility::getModuleUrl('web_ts', $urlParameters);
280 $assigns['moduleUrl'] = BackendUtility::getModuleUrl('web_ts', $urlParameters);
281 $assigns['isNotInTopLevelKeyList'] = !isset($this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType][$this->pObj->sObj]);
282 $assigns['hasProperties'] = !empty($theSetup);
283 if (!$this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType][$this->pObj->sObj]) {
284 if (!empty($theSetup)) {
285 $assigns['moduleUrlObjectListAction'] = $aHref . '&addKey[' . rawurlencode($this->pObj->sObj) . ']=1&SET[ts_browser_toplevel_' . $bType . ']=' . rawurlencode($this->pObj->sObj);
286 }
287 } else {
288 $assigns['moduleUrlObjectListAction'] = $aHref . '&addKey[' . rawurlencode($this->pObj->sObj) . ']=0&SET[ts_browser_toplevel_' . $bType . ']=0';
289 }
290 } else {
291 $this->templateService->tsbrowser_depthKeys = $this->pObj->MOD_SETTINGS['tsbrowser_depthKeys_' . $bType];
292 if (GeneralUtility::_POST('search') && GeneralUtility::_POST('search_field')) {
293 // If any POST-vars are send, update the condition array
294 $searchString = GeneralUtility::_POST('search_field');
295 try {
296 $this->templateService->tsbrowser_depthKeys =
297 $this->templateService->ext_getSearchKeys(
298 $theSetup,
299 '',
300 $searchString,
301 []
302 );
303 } catch (Exception $e) {
304 $this->addFlashMessage(
305 GeneralUtility::makeInstance(FlashMessage::class, sprintf($lang->getLL('error.' . $e->getCode()), $searchString), '', FlashMessage::ERROR)
306 );
307 }
308 }
309 $assigns['hasTsBrowserTypes'] = is_array($this->pObj->MOD_MENU['ts_browser_type']) && count($this->pObj->MOD_MENU['ts_browser_type']) > 1;
310 if (is_array($this->pObj->MOD_MENU['ts_browser_type']) && count($this->pObj->MOD_MENU['ts_browser_type']) > 1) {
311 $assigns['browserTypeDropdownMenu'] = BackendUtility::getDropdownMenu($this->pObj->id, 'SET[ts_browser_type]', $bType, $this->pObj->MOD_MENU['ts_browser_type']);
312 }
313 $assigns['hasTopLevelInObjectList'] = is_array($this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]) && count($this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]) > 1;
314 if (is_array($this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]) && count($this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]) > 1) {
315 $assigns['objectListDropdownMenu'] = BackendUtility::getDropdownMenu($this->pObj->id, 'SET[ts_browser_toplevel_' . $bType . ']', $this->pObj->MOD_SETTINGS['ts_browser_toplevel_' . $bType], $this->pObj->MOD_MENU['ts_browser_toplevel_' . $bType]);
316 }
317
318 $assigns['regexSearchCheckbox'] = BackendUtility::getFuncCheck($this->pObj->id, 'SET[ts_browser_regexsearch]', $this->pObj->MOD_SETTINGS['ts_browser_regexsearch'], '', '', 'id="checkTs_browser_regexsearch"');
319 $assigns['postSearchField'] = $POST['search_field'];
320 $theKey = $this->pObj->MOD_SETTINGS['ts_browser_toplevel_' . $bType];
321 if (!$theKey || !str_replace('-', '', $theKey)) {
322 $theKey = '';
323 }
324 list($theSetup, $theSetupValue) = $this->templateService->ext_getSetup($theSetup, $this->pObj->MOD_SETTINGS['ts_browser_toplevel_' . $bType] ? $this->pObj->MOD_SETTINGS['ts_browser_toplevel_' . $bType] : '');
325 $tree = $this->templateService->ext_getObjTree($theSetup, $theKey, '', '', $theSetupValue, $this->pObj->MOD_SETTINGS['ts_browser_alphaSort']);
326 $tree = $this->templateService->substituteCMarkers($tree);
327 $urlParameters = [
328 'id' => $this->pObj->id
329 ];
330 $aHref = BackendUtility::getModuleUrl('web_ts', $urlParameters);
331 // Parser Errors:
332 $pEkey = $bType === 'setup' ? 'config' : 'constants';
333 $assigns['hasParseErrors'] = !empty($this->templateService->parserErrors[$pEkey]);
334 if (!empty($this->templateService->parserErrors[$pEkey])) {
335 $assigns['showErrorDetailsUri'] = $aHref . '&SET[function]=TYPO3\\CMS\\Tstemplate\\Controller\\TemplateAnalyzerModuleFunctionController&template=all&SET[ts_analyzer_checkLinenum]=1#line-';
336 $assigns['parseErrors'] = $this->templateService->parserErrors[$pEkey];
337 }
338
339 if (isset($this->pObj->MOD_SETTINGS['ts_browser_TLKeys_' . $bType][$theKey])) {
340 $assigns['moduleUrlRemoveFromObjectList'] = $aHref . '&addKey[' . $theKey . ']=0&SET[ts_browser_toplevel_' . $bType . ']=0';
341 }
342
343 $assigns['hasKeySelected'] = $theKey !== '';
344
345 if ($theKey) {
346 $assigns['treeLabel'] = $theKey;
347 } else {
348 $assigns['rootLLKey'] = $bType === 'setup' ? 'setupRoot' : 'constantRoot';
349 }
350 $assigns['tsTree'] = $tree;
351
352 // second row options
353 $assigns['isSetupAndCropLinesDisabled'] = $bType === 'setup' && !$this->pObj->MOD_SETTINGS['ts_browser_fixedLgd'];
354 $assigns['checkBoxShowComments'] = BackendUtility::getFuncCheck($this->pObj->id, 'SET[ts_browser_showComments]', $this->pObj->MOD_SETTINGS['ts_browser_showComments'], '', '', 'id="checkTs_browser_showComments"');
355 $assigns['checkBoxAlphaSort'] = BackendUtility::getFuncCheck($this->pObj->id, 'SET[ts_browser_alphaSort]', $this->pObj->MOD_SETTINGS['ts_browser_alphaSort'], '', '', 'id="checkTs_browser_alphaSort"');
356 $assigns['checkBoxCropLines'] = BackendUtility::getFuncCheck($this->pObj->id, 'SET[ts_browser_fixedLgd]', $this->pObj->MOD_SETTINGS['ts_browser_fixedLgd'], '', '', 'id="checkTs_browser_fixedLgd"');
357 if ($bType === 'setup' && !$this->pObj->MOD_SETTINGS['ts_browser_fixedLgd']) {
358 $assigns['dropdownDisplayConstants'] = BackendUtility::getDropdownMenu($this->pObj->id, 'SET[ts_browser_const]', $this->pObj->MOD_SETTINGS['ts_browser_const'], $this->pObj->MOD_MENU['ts_browser_const']);
359 }
360
361 // Conditions:
362 $assigns['hasConditions'] = is_array($this->templateService->sections) && !empty($this->templateService->sections);
363 if (is_array($this->templateService->sections) && !empty($this->templateService->sections)) {
364 $tsConditions = [];
365 foreach ($this->templateService->sections as $key => $val) {
366 $tsConditions[] = [
367 'key' => $key,
368 'value' => $val,
369 'label' => $this->templateService->substituteCMarkers(htmlspecialchars($val)),
370 'isSet' => $this->pObj->MOD_SETTINGS['tsbrowser_conditions'][$key] ? true : false
371 ];
372 }
373 $assigns['tsConditions'] = $tsConditions;
374 }
375 // Ending section displayoptions
376 }
377
378 $view = GeneralUtility::makeInstance(StandaloneView::class);
379 $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName(
380 'EXT:tstemplate/Resources/Private/Templates/TemplateObjectBrowserModuleFunction.html'
381 ));
382 $view->assignMultiple($assigns);
383
384 return $view->render();
385 }
386
387 /**
388 * Add flash message to queue
389 *
390 * @param FlashMessage $flashMessage
391 * @return void
392 */
393 protected function addFlashMessage(FlashMessage $flashMessage)
394 {
395 /** @var $flashMessageService FlashMessageService */
396 $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
397 /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */
398 $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
399 $defaultFlashMessageQueue->enqueue($flashMessage);
400 }
401 }