‪TYPO3CMS  11.5
TemplateAnalyzerModuleFunctionController.php
Go to the documentation of this file.
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 
17 
18 use Psr\Http\Message\ServerRequestInterface;
19 use TYPO3\CMS\Core\Page\PageRenderer;
20 use TYPO3\CMS\Core\TypoScript\ExtendedTemplateService;
25 
31 {
35  protected ‪$pObj;
36 
41  protected ‪$templateRow;
42 
46  protected ‪$templateService;
47 
51  protected ‪$request;
52 
59  public function ‪init(‪$pObj, ServerRequestInterface ‪$request)
60  {
61  $this->pObj = ‪$pObj;
62  $this->request = ‪$request;
63  }
64 
70  public function ‪main()
71  {
72  // The page id TypoScript tree should be show for
73  $pageUid = (int)($this->request->getParsedBody()['id'] ?? $this->request->getQueryParams()['id'] ?? 0);
74  // Set if user clicked on one template to show content of this specific one
75  $selectedTemplate = ($this->request->getQueryParams()['template'] ?? '');
76  // The template object browser shows info boxes with parser errors and links to template analyzer to highlight
77  // affected line. Increased by one if set to avoid an off-by-one error.
78  $highlightLine = (int)($this->request->getQueryParams()['highlightLine'] ?? 0);
79  // 'const' or 'setup' or not set
80  $highlightType = (string)($this->request->getQueryParams()['highlightType'] ?? '');
81 
82  $assigns = [
83  'pageUid' => $pageUid,
84  ];
85 
86  $templateUid = 0;
87  $assigns['manyTemplatesMenu'] = $this->pObj->templateMenu($this->request);
88  if ($assigns['manyTemplatesMenu']) {
89  $templateUid = (int)$this->pObj->MOD_SETTINGS['templatesOnPage'];
90  }
91 
92  $assigns['existTemplate'] = $this->‪initializeTemplates($pageUid, $templateUid);
93  if ($assigns['existTemplate']) {
94  $assigns['templateRecord'] = ‪$this->templateRow;
95  $assigns['linkWrappedTemplateTitle'] = $this->pObj->linkWrapTemplateTitle($this->templateRow['title']);
96  }
97 
98  $this->templateService->clearList_const_temp = array_flip($this->templateService->clearList_const);
99  $this->templateService->clearList_setup_temp = array_flip($this->templateService->clearList_setup);
100  $pointer = count($this->templateService->hierarchyInfo);
101  $hierarchyInfo = $this->templateService->ext_process_hierarchyInfo([], $pointer);
102  $assigns['hierarchy'] = implode('', array_reverse($this->templateService->ext_getTemplateHierarchyArr(
103  $hierarchyInfo,
104  '',
105  [],
106  1
107  )));
108 
109  $assigns['constants'] = $this->‪renderTemplates($this->templateService->constants, $selectedTemplate, $highlightType === 'const', $highlightLine);
110  $assigns['setups'] = $this->‪renderTemplates($this->templateService->config, $selectedTemplate, $highlightType === 'setup', $highlightLine);
111 
112  if (‪ExtensionManagementUtility::isLoaded('t3editor')) {
113  // @todo: Let EXT:t3editor add the deps via events in the render-loops above
114  $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
115  $pageRenderer->addCssFile('EXT:t3editor/Resources/Public/JavaScript/Contrib/codemirror/lib/codemirror.css');
116  $pageRenderer->addCssFile('EXT:t3editor/Resources/Public/Css/t3editor.css');
117  $pageRenderer->loadRequireJsModule('TYPO3/CMS/T3editor/Element/CodeMirrorElement');
118  }
119 
120  $view = GeneralUtility::makeInstance(StandaloneView::class);
121  $view->setTemplatePathAndFilename('EXT:tstemplate/Resources/Private/Templates/TemplateAnalyzerModuleFunction.html');
122  $view->assignMultiple($assigns);
123  return $view->render();
124  }
125 
126  protected function ‪initializeTemplates(int $pageId, int $templateUid = 0): bool
127  {
128  // Initializes the module. Done in this function because we may need to re-initialize if data is submitted!
129  $this->templateService = GeneralUtility::makeInstance(ExtendedTemplateService::class);
130 
131  // Gets the rootLine
132  $rootlineUtility = GeneralUtility::makeInstance(RootlineUtility::class, $pageId);
133  $rootLine = $rootlineUtility->get();
134 
135  // This generates the constants/config + hierarchy info for the template.
136  $this->templateService->runThroughTemplates($rootLine, $templateUid);
137 
138  // Get the row of the first VISIBLE template of the page. where clause like the frontend.
139  $this->templateRow = $this->templateService->ext_getFirstTemplate($pageId, $templateUid);
140  return is_array($this->templateRow);
141  }
142 
152  protected function ‪renderTemplates(array $templates, string $selectedTemplate, bool $highlight, int $highlightLine): array
153  {
154  $templatesMarkup = [];
155  $totalLines = 0;
156  foreach ($templates as $templateNumber => $templateContent) {
157  $totalLines += 1 + count(explode(LF, $templateContent));
158  }
159  $thisLineOffset = $nextLineOffset = 0;
160  foreach ($templates as $templateNumber => $templateContent) {
161  $templateId = $this->templateService->hierarchyInfo[$templateNumber]['templateID'] ?? null;
162  $templateTitle = $this->templateService->hierarchyInfo[$templateNumber]['title'] ?? 'Template';
163  // Prefix content with '[GLOBAL]' even for empty strings, the TemplateService does that, too.
164  // Not replicating this leads to shifted line numbers when parser errors are reported in FE and object browser.
165  // @todo: Locate where TemplateService hard prefixes this for empty strings and drop it.
166  $templateContent = '[GLOBAL]' . LF . (string)$templateContent;
167  $linesInTemplate = count(explode(LF, $templateContent));
168  $nextLineOffset += $linesInTemplate;
169  if ($selectedTemplate === 'all'
170  || $templateId === $selectedTemplate
171  || $highlight && $highlightLine && $highlightLine > $thisLineOffset && $highlightLine <= $nextLineOffset
172  ) {
173  if (‪ExtensionManagementUtility::isLoaded('t3editor')) {
174  // @todo: Fire event and let EXT:t3editor fill the markup
175  $templatesMarkup[] = $this->‪getCodeMirrorMarkup(
176  $templateTitle,
177  $thisLineOffset,
178  $linesInTemplate,
179  $totalLines,
180  $highlight ? $highlightLine : 0,
181  $templateContent
182  );
183  } else {
184  $templatesMarkup[] = $this->‪getTextareaMarkup(
185  $templateTitle,
186  $linesInTemplate,
187  $templateContent
188  );
189  }
190  }
191  $thisLineOffset = $nextLineOffset;
192  }
193  return $templatesMarkup;
194  }
195 
196  protected function ‪getCodeMirrorMarkup(
197  string $label,
198  int $lineOffset,
199  int $lines,
200  int $totalLines,
201  int $highlightLine,
202  string $content
203  ): string {
204  $codeMirrorConfig = [
205  'label' => $label,
206  'panel' => 'top',
207  'mode' => 'TYPO3/CMS/T3editor/Mode/typoscript/typoscript',
208  'autoheight' => 'true',
209  'nolazyload' => 'true',
210  'linedigits' => (string)strlen((string)$totalLines),
211  'options' => GeneralUtility::jsonEncodeForHtmlAttribute([
212  'readOnly' => true,
213  'format' => 'typoscript',
214  'rows' => 'auto',
215  'firstLineNumber' => $lineOffset + 1,
216  ], false),
217  ];
218  $textareaAttributes = [
219  'rows' => (string)$lines,
220  'readonly' => 'readonly',
221  ];
222 
223  // If we want to highlight
224  if ($highlightLine && $highlightLine >= $lineOffset && $highlightLine <= ($lineOffset + $lines)) {
225  // Scroll to affected line and highlight line if requested
226  $targetLineInTemplate = $highlightLine - $lineOffset;
227  $codeMirrorConfig['scrollto'] = (string)$targetLineInTemplate;
228  $codeMirrorConfig['marktext'] = GeneralUtility::jsonEncodeForHtmlAttribute([
229  [
230  'from' => [
231  'line' => $targetLineInTemplate - 1,
232  'ch' => 0,
233  ],
234  'to' => [
235  'line' => $targetLineInTemplate - 1,
236  // Arbitrary high value to match full line
237  'ch' => 10000,
238  ],
239  ],
240  ], false);
241  }
242 
243  $code = '<typo3-t3editor-codemirror ' . GeneralUtility::implodeAttributes($codeMirrorConfig, true) . '>';
244  $code .= '<textarea ' . GeneralUtility::implodeAttributes($textareaAttributes, true) . '>' . htmlspecialchars($content) . '</textarea>';
245  $code .= '</typo3-t3editor-codemirror>';
246 
247  return $code;
248  }
249 
250  protected function ‪getTextareaMarkup(string $title, int $linesInTemplate, string $content): string
251  {
252  return htmlspecialchars($title)
253  . '<textarea class="form-control" rows="' . ($linesInTemplate + 1) . '" disabled>'
254  . htmlspecialchars($content)
255  . '</textarea>';
256  }
257 }
‪TYPO3\CMS\Tstemplate\Controller\TemplateAnalyzerModuleFunctionController\main
‪string main()
Definition: TemplateAnalyzerModuleFunctionController.php:66
‪TYPO3\CMS\Tstemplate\Controller\TemplateAnalyzerModuleFunctionController\$templateRow
‪array null $templateRow
Definition: TemplateAnalyzerModuleFunctionController.php:39
‪TYPO3\CMS\Core\Utility\RootlineUtility
Definition: RootlineUtility.php:38
‪TYPO3\CMS\Tstemplate\Controller
Definition: TemplateAnalyzerModuleFunctionController.php:16
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:43
‪TYPO3\CMS\Tstemplate\Controller\TemplateAnalyzerModuleFunctionController\$templateService
‪ExtendedTemplateService $templateService
Definition: TemplateAnalyzerModuleFunctionController.php:43
‪TYPO3\CMS\Tstemplate\Controller\TemplateAnalyzerModuleFunctionController\initializeTemplates
‪initializeTemplates(int $pageId, int $templateUid=0)
Definition: TemplateAnalyzerModuleFunctionController.php:122
‪TYPO3\CMS\Tstemplate\Controller\TemplateAnalyzerModuleFunctionController
Definition: TemplateAnalyzerModuleFunctionController.php:31
‪TYPO3\CMS\Tstemplate\Controller\TemplateAnalyzerModuleFunctionController\getCodeMirrorMarkup
‪getCodeMirrorMarkup(string $label, int $lineOffset, int $lines, int $totalLines, int $highlightLine, string $content)
Definition: TemplateAnalyzerModuleFunctionController.php:192
‪TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateModuleController
Definition: TypoScriptTemplateModuleController.php:51
‪TYPO3\CMS\Tstemplate\Controller\TemplateAnalyzerModuleFunctionController\getTextareaMarkup
‪getTextareaMarkup(string $title, int $linesInTemplate, string $content)
Definition: TemplateAnalyzerModuleFunctionController.php:246
‪TYPO3\CMS\Tstemplate\Controller\TemplateAnalyzerModuleFunctionController\$request
‪ServerRequestInterface $request
Definition: TemplateAnalyzerModuleFunctionController.php:47
‪TYPO3\CMS\Fluid\View\StandaloneView
Definition: StandaloneView.php:31
‪TYPO3\CMS\Tstemplate\Controller\TemplateAnalyzerModuleFunctionController\init
‪init($pObj, ServerRequestInterface $request)
Definition: TemplateAnalyzerModuleFunctionController.php:55
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:50
‪TYPO3\CMS\Tstemplate\Controller\TemplateAnalyzerModuleFunctionController\renderTemplates
‪array renderTemplates(array $templates, string $selectedTemplate, bool $highlight, int $highlightLine)
Definition: TemplateAnalyzerModuleFunctionController.php:148
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isLoaded
‪static bool isLoaded($key)
Definition: ExtensionManagementUtility.php:114
‪TYPO3\CMS\Tstemplate\Controller\TemplateAnalyzerModuleFunctionController\$pObj
‪TypoScriptTemplateModuleController $pObj
Definition: TemplateAnalyzerModuleFunctionController.php:34