90e5b5db89d682566c9dfc4c49345ef34e734e35
[Packages/TYPO3.CMS.git] / typo3 / sysext / info / Classes / Controller / InfoPageTyposcriptConfigController.php
1 <?php
2 namespace TYPO3\CMS\Info\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\Utility\BackendUtility;
18 use TYPO3\CMS\Core\Database\ConnectionPool;
19 use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
20 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
21 use TYPO3\CMS\Core\Imaging\Icon;
22 use TYPO3\CMS\Core\Imaging\IconFactory;
23 use TYPO3\CMS\Core\Utility\GeneralUtility;
24 use TYPO3\CMS\Core\Utility\MathUtility;
25 use TYPO3\CMS\Fluid\View\StandaloneView;
26
27 /**
28 * Page TSconfig viewer
29 */
30 class InfoPageTyposcriptConfigController extends \TYPO3\CMS\Backend\Module\AbstractFunctionModule
31 {
32 /**
33 * @var IconFactory
34 */
35 protected $iconFactory;
36
37 /**
38 * @var StandaloneView
39 */
40 protected $view;
41
42 /**
43 * Constructor
44 */
45 public function __construct()
46 {
47 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
48 $this->getLanguageService()->includeLLFile('EXT:info/Resources/Private/Language/InfoPageTsConfig.xlf');
49
50 $this->view = $this->getFluidTemplateObject();
51 }
52
53 /**
54 * Function menu initialization
55 *
56 * @return array Menu array
57 */
58 public function modMenu()
59 {
60 $lang = $this->getLanguageService();
61 $modMenuAdd = [
62 'tsconf_parts' => [
63 0 => $lang->getLL('tsconf_parts_0'),
64 1 => $lang->getLL('tsconf_parts_1'),
65 '1a' => $lang->getLL('tsconf_parts_1a'),
66 '1b' => $lang->getLL('tsconf_parts_1b'),
67 '1c' => $lang->getLL('tsconf_parts_1c'),
68 '1d' => $lang->getLL('tsconf_parts_1d'),
69 '1e' => $lang->getLL('tsconf_parts_1e'),
70 '1f' => $lang->getLL('tsconf_parts_1f'),
71 '1g' => $lang->getLL('tsconf_parts_1g'),
72 2 => 'RTE.',
73 5 => 'TCEFORM.',
74 6 => 'TCEMAIN.',
75 3 => 'TSFE.',
76 4 => 'user.',
77 99 => $lang->getLL('tsconf_configFields')
78 ],
79 'tsconf_alphaSort' => '1'
80 ];
81 if (!$this->getBackendUser()->isAdmin()) {
82 unset($modMenuAdd['tsconf_parts'][99]);
83 }
84 return $modMenuAdd;
85 }
86
87 /**
88 * Main function of class
89 *
90 * @return string HTML output
91 */
92 public function main()
93 {
94 $pageId = (int)GeneralUtility::_GP('id');
95 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
96 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
97
98 if ($pageId === 0) {
99 $this->view->assign('pageZero', 1);
100 $pagesUsingTSConfig = $this->getOverviewOfPagesUsingTSConfig();
101 if (count($pagesUsingTSConfig) > 0) {
102 $this->view->assign('overviewOfPagesUsingTSConfig', $pagesUsingTSConfig);
103 }
104 } else {
105 if ($this->pObj->MOD_SETTINGS['tsconf_parts'] == 99) {
106 $TSparts = BackendUtility::getRawPagesTSconfig($this->pObj->id);
107 $lines = [];
108 $pUids = [];
109
110 foreach ($TSparts as $k => $v) {
111 if ($k !== 'uid_0') {
112 $line = [];
113 if ($k === 'defaultPageTSconfig') {
114 $line['defaultPageTSconfig'] = 1;
115 } else {
116 $editIdList = substr($k, 4);
117 $pUids[] = $editIdList;
118 $row = BackendUtility::getRecordWSOL('pages', $editIdList);
119
120 $icon = $this->iconFactory->getIconForRecord('pages', $row, Icon::SIZE_SMALL);
121 $urlParameters = [
122 'edit' => [
123 'pages' => [
124 $editIdList => 'edit',
125 ]
126 ],
127 'columnsOnly' => 'TSconfig',
128 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
129 ];
130 $line['editIcon'] = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
131 $line['editTitle'] = 'editTSconfig';
132 $line['title'] = BackendUtility::wrapClickMenuOnIcon($icon, 'pages', $row['uid'])
133 . ' ' . htmlspecialchars(BackendUtility::getRecordTitle('pages', $row));
134 }
135 $tsparser = GeneralUtility::makeInstance(\TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser::class);
136 $tsparser->lineNumberOffset = 0;
137 $line['content'] = $tsparser->doSyntaxHighlight(trim($v) . LF);
138 $lines[] = $line;
139 }
140 }
141
142 if (!empty($pUids)) {
143 $urlParameters = [
144 'edit' => [
145 'pages' => [
146 implode(',', $pUids) => 'edit',
147 ]
148 ],
149 'columnsOnly' => 'TSconfig',
150 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
151 ];
152 $url = (string)$uriBuilder->buildUriFromRoute('record_edit', $urlParameters);
153 $editIcon = htmlspecialchars($url);
154 $editTitle = 'editTSconfig_all';
155 } else {
156 $editIcon = '';
157 $editTitle = '';
158 }
159
160 $this->view->assign('tsconfParts99', 1);
161 $this->view->assign('csh', BackendUtility::cshItem('_MOD_web_info', 'tsconfig_edit', null, '|'));
162 $this->view->assign('lines', $lines);
163 $this->view->assign('editIcon', $editIcon);
164 $this->view->assign('editTitle', $editTitle);
165 } else {
166 $this->view->assign('tsconfParts99', 0);
167 // Defined global here!
168 $tmpl = GeneralUtility::makeInstance(\TYPO3\CMS\Core\TypoScript\ExtendedTemplateService::class);
169 $tmpl->ext_expandAllNotes = 1;
170 $tmpl->ext_noPMicons = 1;
171
172 $pageTsConfig = BackendUtility::getPagesTSconfig($this->pObj->id);
173 switch ($this->pObj->MOD_SETTINGS['tsconf_parts']) {
174 case '1':
175 $pageTsConfig = $pageTsConfig['mod.'] ?? [];
176 break;
177 case '1a':
178 $pageTsConfig = $pageTsConfig['mod.']['web_layout.'] ?? [];
179 break;
180 case '1b':
181 $pageTsConfig = $pageTsConfig['mod.']['web_view.'] ?? [];
182 break;
183 case '1c':
184 $pageTsConfig = $pageTsConfig['mod.']['web_modules.'] ?? [];
185 break;
186 case '1d':
187 $pageTsConfig = $pageTsConfig['mod.']['web_list.'] ?? [];
188 break;
189 case '1e':
190 $pageTsConfig = $pageTsConfig['mod.']['web_info.'] ?? [];
191 break;
192 case '1f':
193 $pageTsConfig = $pageTsConfig['mod.']['web_func.'] ?? [];
194 break;
195 case '1g':
196 $pageTsConfig = $pageTsConfig['mod.']['web_ts.'] ?? [];
197 break;
198 case '2':
199 $pageTsConfig = $pageTsConfig['RTE.'] ?? [];
200 break;
201 case '5':
202 $pageTsConfig = $pageTsConfig['TCEFORM.'] ?? [];
203 break;
204 case '6':
205 $pageTsConfig = $pageTsConfig['TCEMAIN.'] ?? [];
206 break;
207 case '3':
208 $pageTsConfig = $pageTsConfig['TSFE.'] ?? [];
209 break;
210 case '4':
211 $pageTsConfig = $pageTsConfig['user.'] ?? [];
212 break;
213 default:
214 // Entire array
215 }
216
217 $this->view->assign('csh', BackendUtility::cshItem('_MOD_web_info', 'tsconfig_hierarchy', null, '|'));
218 $this->view->assign('tree', $tmpl->ext_getObjTree($pageTsConfig, '', '', '', '', $this->pObj->MOD_SETTINGS['tsconf_alphaSort']));
219 }
220 $this->view->assign('alphaSort', BackendUtility::getFuncCheck($this->pObj->id, 'SET[tsconf_alphaSort]', $this->pObj->MOD_SETTINGS['tsconf_alphaSort'], '', '', 'id="checkTsconf_alphaSort"'));
221 $this->view->assign('dropdownMenu', BackendUtility::getDropdownMenu($this->pObj->id, 'SET[tsconf_parts]', $this->pObj->MOD_SETTINGS['tsconf_parts'], $this->pObj->MOD_MENU['tsconf_parts']));
222 }
223 return $this->view->render();
224 }
225
226 /**
227 * Renders table rows of all pages containing TSConfig together with its rootline
228 *
229 * @return array
230 */
231 protected function getOverviewOfPagesUsingTSConfig()
232 {
233 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
234 $queryBuilder->getRestrictions()
235 ->removeAll()
236 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
237 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
238
239 $res = $queryBuilder
240 ->select('uid', 'TSconfig')
241 ->from('pages')
242 ->where(
243 $queryBuilder->expr()->neq(
244 'TSconfig',
245 $queryBuilder->createNamedParameter('', \PDO::PARAM_STR)
246 )
247 )
248 ->groupBy('uid')
249 ->execute();
250
251 $pageArray = [];
252
253 while ($row = $res->fetch()) {
254 $this->setInPageArray($pageArray, BackendUtility::BEgetRootLine($row['uid'], 'AND 1=1'), $row);
255 }
256 return $this->getList($pageArray);
257 }
258
259 /**
260 * Set page in array
261 * This function is called recursively and builds a multi-dimensional array that reflects the page
262 * hierarchy.
263 *
264 * @param array $hierarchicArray The hierarchic array (passed by reference)
265 * @param array $rootlineArray The rootline array
266 * @param array $row The row from the database containing the uid and TSConfig fields
267 */
268 protected function setInPageArray(&$hierarchicArray, $rootlineArray, $row)
269 {
270 ksort($rootlineArray);
271 reset($rootlineArray);
272 if (!$rootlineArray[0]['uid']) {
273 array_shift($rootlineArray);
274 }
275 $currentElement = current($rootlineArray);
276 $hierarchicArray[$currentElement['uid']] = htmlspecialchars($currentElement['title']);
277 array_shift($rootlineArray);
278 if (!empty($rootlineArray)) {
279 if (!isset($hierarchicArray[$currentElement['uid'] . '.'])) {
280 $hierarchicArray[$currentElement['uid'] . '.'] = [];
281 }
282 $this->setInPageArray($hierarchicArray[$currentElement['uid'] . '.'], $rootlineArray, $row);
283 } else {
284 $hierarchicArray[$currentElement['uid'] . '_'] = $this->extractLinesFromTSConfig($row);
285 }
286 }
287
288 /**
289 * Extract the lines of TSConfig from a given pages row
290 *
291 * @param array $row The row from the database containing the uid and TSConfig fields
292 * @return array
293 */
294 protected function extractLinesFromTSConfig(array $row)
295 {
296 $out = [];
297 $includeLines = 0;
298 $out['uid'] = $row['uid'];
299 $lines = GeneralUtility::trimExplode("\r\n", $row['TSconfig']);
300 foreach ($lines as $line) {
301 if (strpos($line, '<INCLUDE_TYPOSCRIPT:') !== false) {
302 $includeLines++;
303 }
304 }
305 $out['includeLines'] = $includeLines;
306 $out['writtenLines'] = (count($lines) - $includeLines);
307 return $out;
308 }
309
310 /**
311 * Get the list of pages to show.
312 * This function is called recursively
313 *
314 * @param array $pageArray The Page Array
315 * @param array $lines Lines that have been processed up to this point
316 * @param int $pageDepth The level of the current $pageArray being processed
317 * @return array
318 */
319 protected function getList($pageArray, $lines = [], $pageDepth = 0)
320 {
321 if (!is_array($pageArray)) {
322 return $lines;
323 }
324
325 foreach ($pageArray as $identifier => $_) {
326 if (!MathUtility::canBeInterpretedAsInteger($identifier)) {
327 continue;
328 }
329 $line = [];
330 $line['padding'] = ($pageDepth * 20) + 10;
331 if (isset($pageArray[$identifier . '_'])) {
332 $line['link'] = GeneralUtility::linkThisScript(['id' => $identifier]);
333 $line['icon'] = $this->iconFactory->getIconForRecord('pages', BackendUtility::getRecordWSOL('pages', $identifier), Icon::SIZE_SMALL)->render();
334 $line['title'] = 'ID: ' . $identifier;
335 $line['pageTitle'] = GeneralUtility::fixed_lgd_cs($pageArray[$identifier], 30);
336 $line['includedFiles'] = ($pageArray[$identifier . '_']['includeLines'] === 0 ? '' : $pageArray[$identifier . '_']['includeLines']);
337 $line['lines'] = ($pageArray[$identifier . '_']['writtenLines'] === 0 ? '' : $pageArray[$identifier . '_']['writtenLines']);
338 } else {
339 $line['link'] = '';
340 $line['icon'] = $this->iconFactory->getIconForRecord('pages', BackendUtility::getRecordWSOL('pages', $identifier), Icon::SIZE_SMALL)->render();
341 $line['title'] = '';
342 $line['pageTitle'] = GeneralUtility::fixed_lgd_cs($pageArray[$identifier], 30);
343 $line['includedFiles'] = '';
344 $line['lines'] = '';
345 }
346 $lines[] = $line;
347 $lines = $this->getList($pageArray[$identifier . '.'], $lines, $pageDepth + 1);
348 }
349 return $lines;
350 }
351
352 /**
353 * Returns LanguageService
354 *
355 * @return \TYPO3\CMS\Core\Localization\LanguageService
356 */
357 protected function getLanguageService()
358 {
359 return $GLOBALS['LANG'];
360 }
361
362 /**
363 * Returns the current BE user.
364 *
365 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
366 */
367 protected function getBackendUser()
368 {
369 return $GLOBALS['BE_USER'];
370 }
371
372 /**
373 * returns a new standalone view, shorthand function
374 *
375 * @return StandaloneView
376 */
377 protected function getFluidTemplateObject()
378 {
379 /** @var StandaloneView $view */
380 $view = GeneralUtility::makeInstance(StandaloneView::class);
381 $view->setLayoutRootPaths([GeneralUtility::getFileAbsFileName('EXT:info/Resources/Private/Layouts')]);
382 $view->setPartialRootPaths([GeneralUtility::getFileAbsFileName('EXT:info/Resources/Private/Partials')]);
383 $view->setTemplateRootPaths([GeneralUtility::getFileAbsFileName('EXT:info/Resources/Private/Templates')]);
384
385 $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:info/Resources/Private/Templates/PageTsConfig.html'));
386
387 $view->getRequest()->setControllerExtensionName('info');
388 return $view;
389 }
390 }