Passed
Push — master ( 2b355a...25a926 )
by
unknown
13:06
created

InfoPageTyposcriptConfigController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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