Total Complexity | 68 |
Total Lines | 735 |
Duplicated Lines | 0 % |
Changes | 1 | ||
Bugs | 0 | Features | 0 |
Complex classes like TypoScriptTemplateModuleController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use TypoScriptTemplateModuleController, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
48 | class TypoScriptTemplateModuleController |
||
49 | { |
||
50 | |||
51 | /** |
||
52 | * @var string |
||
53 | */ |
||
54 | protected $perms_clause; |
||
55 | |||
56 | /** |
||
57 | * @var string |
||
58 | */ |
||
59 | public $modMenu_dontValidateList = ''; |
||
60 | |||
61 | /** |
||
62 | * @var string Written by client classes |
||
63 | */ |
||
64 | public $modMenu_setDefaultList = ''; |
||
65 | |||
66 | /** |
||
67 | * @var array |
||
68 | */ |
||
69 | protected $pageinfo = []; |
||
70 | |||
71 | /** |
||
72 | * @var bool |
||
73 | */ |
||
74 | protected $access = false; |
||
75 | |||
76 | /** |
||
77 | * The name of the module |
||
78 | * |
||
79 | * @var string |
||
80 | */ |
||
81 | protected $moduleName = 'web_ts'; |
||
82 | |||
83 | /** |
||
84 | * ModuleTemplate Container |
||
85 | * |
||
86 | * @var ModuleTemplate |
||
87 | */ |
||
88 | protected $moduleTemplate; |
||
89 | |||
90 | /** |
||
91 | * @var ExtendedTemplateService |
||
92 | */ |
||
93 | protected $templateService; |
||
94 | |||
95 | /** |
||
96 | * @var int GET/POST var 'id' |
||
97 | */ |
||
98 | protected $id; |
||
99 | |||
100 | /** |
||
101 | * The module menu items array. Each key represents a key for which values can range between the items in the array of that key. |
||
102 | * Written by client classes. |
||
103 | * |
||
104 | * @var array |
||
105 | */ |
||
106 | public $MOD_MENU = [ |
||
107 | 'function' => [] |
||
108 | ]; |
||
109 | |||
110 | /** |
||
111 | * Current settings for the keys of the MOD_MENU array, used in client classes |
||
112 | * |
||
113 | * @var array |
||
114 | */ |
||
115 | public $MOD_SETTINGS = []; |
||
116 | |||
117 | /** |
||
118 | * Module TSconfig based on PAGE TSconfig / USER TSconfig |
||
119 | * |
||
120 | * @var array |
||
121 | */ |
||
122 | protected $modTSconfig; |
||
123 | |||
124 | /** |
||
125 | * Contains module configuration parts from TBE_MODULES_EXT if found |
||
126 | * |
||
127 | * @var array |
||
128 | */ |
||
129 | protected $extClassConf; |
||
130 | |||
131 | /** |
||
132 | * May contain an instance of a 'Function menu module' which connects to this backend module. |
||
133 | * |
||
134 | * @see checkExtObj() |
||
135 | * @var object |
||
136 | */ |
||
137 | protected $extObj; |
||
138 | |||
139 | /** |
||
140 | * @var ServerRequestInterface |
||
141 | */ |
||
142 | protected $request; |
||
143 | |||
144 | /** |
||
145 | * Constructor |
||
146 | */ |
||
147 | public function __construct() |
||
148 | { |
||
149 | $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class); |
||
150 | $this->getLanguageService()->includeLLFile('EXT:tstemplate/Resources/Private/Language/locallang.xlf'); |
||
151 | } |
||
152 | |||
153 | /** |
||
154 | * Generates the menu based on $this->MOD_MENU |
||
155 | * |
||
156 | * @throws \InvalidArgumentException |
||
157 | */ |
||
158 | protected function generateMenu() |
||
159 | { |
||
160 | $menu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu(); |
||
161 | $menu->setIdentifier('WebFuncJumpMenu'); |
||
162 | $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); |
||
163 | foreach ($this->MOD_MENU['function'] as $controller => $title) { |
||
164 | $item = $menu |
||
165 | ->makeMenuItem() |
||
166 | ->setHref( |
||
167 | (string)$uriBuilder->buildUriFromRoute( |
||
168 | $this->moduleName, |
||
169 | [ |
||
170 | 'id' => $this->id, |
||
171 | 'SET' => [ |
||
172 | 'function' => $controller |
||
173 | ] |
||
174 | ] |
||
175 | ) |
||
176 | ) |
||
177 | ->setTitle($title); |
||
178 | if ($controller === $this->MOD_SETTINGS['function']) { |
||
179 | $item->setActive(true); |
||
180 | } |
||
181 | $menu->addMenuItem($item); |
||
182 | } |
||
183 | $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($menu); |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * Injects the request object for the current request or subrequest |
||
188 | * Then checks for module functions that have hooked in, and renders menu etc. |
||
189 | * |
||
190 | * @param ServerRequestInterface $request the current request |
||
191 | * @return ResponseInterface the response with the content |
||
192 | */ |
||
193 | public function mainAction(ServerRequestInterface $request): ResponseInterface |
||
194 | { |
||
195 | $this->request = $request; |
||
196 | $this->id = (int)($request->getParsedBody()['id'] ?? $request->getQueryParams()['id'] ?? 0); |
||
197 | $changedMenuSettings = $request->getParsedBody()['SET'] ?? $request->getQueryParams()['SET'] ?? []; |
||
198 | $changedMenuSettings = is_array($changedMenuSettings) ? $changedMenuSettings : []; |
||
199 | $this->menuConfig($changedMenuSettings); |
||
200 | // Loads $this->extClassConf with the configuration for the CURRENT function of the menu. |
||
201 | $this->extClassConf = $this->getExternalItemConfig('web_ts', 'function', $this->MOD_SETTINGS['function']); |
||
202 | $this->perms_clause = $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW); |
||
203 | |||
204 | // Checking for first level external objects |
||
205 | $this->checkExtObj($changedMenuSettings, $request); |
||
206 | |||
207 | // Access check... |
||
208 | // The page will show only if there is a valid page and if this page may be viewed by the user |
||
209 | $this->pageinfo = BackendUtility::readPageAccess($this->id, $this->perms_clause); |
||
|
|||
210 | $this->access = is_array($this->pageinfo); |
||
211 | $view = $this->getFluidTemplateObject('tstemplate'); |
||
212 | $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); |
||
213 | if ($this->id && $this->access) { |
||
214 | $urlParameters = [ |
||
215 | 'id' => $this->id, |
||
216 | 'template' => 'all' |
||
217 | ]; |
||
218 | $aHref = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters); |
||
219 | |||
220 | // JavaScript |
||
221 | $this->moduleTemplate->addJavaScriptCode( |
||
222 | 'TSTemplateInlineJS', |
||
223 | 'function uFormUrl(aname) { |
||
224 | document.forms[0].action = ' . GeneralUtility::quoteJSvalue($aHref . '#') . '+aname; |
||
225 | } |
||
226 | function brPoint(lnumber,t) { |
||
227 | window.location.href = ' |
||
228 | . GeneralUtility::quoteJSvalue( |
||
229 | $aHref . '&SET[function]=TYPO3\\CMS\\Tstemplate\\Controller\\' |
||
230 | . 'TypoScriptTemplateObjectBrowserModuleFunctionController&SET[ts_browser_type]=' |
||
231 | ) . '+(t?"setup":"const")+"&breakPointLN="+lnumber; |
||
232 | return false; |
||
233 | } |
||
234 | if (top.fsMod) top.fsMod.recentIds["web"] = ' . $this->id . ';' |
||
235 | ); |
||
236 | $this->moduleTemplate->getPageRenderer()->addCssInlineBlock( |
||
237 | 'TSTemplateInlineStyle', |
||
238 | 'TABLE#typo3-objectBrowser { width: 100%; margin-bottom: 24px; } |
||
239 | TABLE#typo3-objectBrowser A { text-decoration: none; } |
||
240 | TABLE#typo3-objectBrowser .comment { color: maroon; font-weight: bold; } |
||
241 | .ts-typoscript { width: 100%; } |
||
242 | .tsob-search-submit {margin-left: 3px; margin-right: 3px;} |
||
243 | .tst-analyzer-options { margin:5px 0; }' |
||
244 | ); |
||
245 | // Setting up the context sensitive menu: |
||
246 | $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ContextMenu'); |
||
247 | // Build the module content |
||
248 | $view->assign('actionName', $aHref); |
||
249 | $view->assign('typoscriptTemplateModuleContent', $this->getExtObjContent()); |
||
250 | // Setting up the buttons and markers for docheader |
||
251 | $this->getButtons(); |
||
252 | $this->generateMenu(); |
||
253 | } else { |
||
254 | $workspaceId = $this->getBackendUser()->workspace; |
||
255 | $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) |
||
256 | ->getQueryBuilderForTable('sys_template'); |
||
257 | $queryBuilder->getRestrictions() |
||
258 | ->removeAll() |
||
259 | ->add(GeneralUtility::makeInstance(DeletedRestriction::class)); |
||
260 | $this->applyWorkspaceConstraint( |
||
261 | $queryBuilder, |
||
262 | 'sys_template', |
||
263 | $workspaceId |
||
264 | ); |
||
265 | $result = $queryBuilder |
||
266 | ->select( |
||
267 | 'uid', |
||
268 | 'pid', |
||
269 | 'title', |
||
270 | 'root', |
||
271 | 'hidden', |
||
272 | 'starttime', |
||
273 | 'endtime', |
||
274 | 't3ver_oid', |
||
275 | 't3ver_wsid', |
||
276 | 't3ver_state' |
||
277 | ) |
||
278 | ->from('sys_template') |
||
279 | ->orderBy('sys_template.pid') |
||
280 | ->addOrderBy('sys_template.sorting') |
||
281 | ->execute(); |
||
282 | $pArray = []; |
||
283 | while ($record = $result->fetch()) { |
||
284 | BackendUtility::workspaceOL('sys_template', $record, $workspaceId, true); |
||
285 | if (empty($record) || VersionState::cast($record['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) { |
||
286 | continue; |
||
287 | } |
||
288 | $additionalFieldsForRootline = ['sorting', 'shortcut']; |
||
289 | $rootline = BackendUtility::BEgetRootLine($record['pid'], '', true, $additionalFieldsForRootline); |
||
290 | $this->setInPageArray($pArray, $rootline, $record); |
||
291 | } |
||
292 | |||
293 | $view->getRenderingContext()->setControllerAction('PageZero'); |
||
294 | $view->assign('pageTree', $pArray); |
||
295 | |||
296 | // RENDER LIST of pages with templates, END |
||
297 | // Setting up the buttons and markers for docheader |
||
298 | $this->getButtons(); |
||
299 | } |
||
300 | $this->moduleTemplate->setContent($view->render()); |
||
301 | return new HtmlResponse($this->moduleTemplate->renderContent()); |
||
302 | } |
||
303 | |||
304 | /** |
||
305 | * Create the panel of buttons for submitting the form or otherwise perform operations. |
||
306 | */ |
||
307 | protected function getButtons() |
||
308 | { |
||
309 | $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar(); |
||
310 | $lang = $this->getLanguageService(); |
||
311 | |||
312 | if ($this->id && $this->access) { |
||
313 | // View page |
||
314 | $previewDataAttributes = PreviewUriBuilder::create((int)$this->pageinfo['uid']) |
||
315 | ->withRootLine(BackendUtility::BEgetRootLine($this->pageinfo['uid'])) |
||
316 | ->buildDispatcherDataAttributes(); |
||
317 | $viewButton = $buttonBar->makeLinkButton() |
||
318 | ->setHref('#') |
||
319 | ->setDataAttributes($previewDataAttributes ?? []) |
||
320 | ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage')) |
||
321 | ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-view-page', Icon::SIZE_SMALL)); |
||
322 | $buttonBar->addButton($viewButton, ButtonBar::BUTTON_POSITION_LEFT, 99); |
||
323 | |||
324 | $sObj = $this->request->getParsedBody()['sObj'] ?? $this->request->getQueryParams()['sObj'] ?? null; |
||
325 | if ($this->extClassConf['name'] === TypoScriptTemplateInformationModuleFunctionController::class) { |
||
326 | // NEW button |
||
327 | $urlParameters = [ |
||
328 | 'id' => $this->id, |
||
329 | 'template' => 'all', |
||
330 | 'createExtension' => 'new' |
||
331 | ]; |
||
332 | $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); |
||
333 | $newButton = $buttonBar->makeLinkButton() |
||
334 | ->setHref((string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters)) |
||
335 | ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:db_new.php.pagetitle')) |
||
336 | ->setIcon($this->moduleTemplate->getIconFactory()->getIcon( |
||
337 | 'actions-add', |
||
338 | Icon::SIZE_SMALL |
||
339 | )); |
||
340 | $buttonBar->addButton($newButton); |
||
341 | } elseif ($this->extClassConf['name'] === TypoScriptTemplateConstantEditorModuleFunctionController::class |
||
342 | && !empty($this->MOD_MENU['constant_editor_cat'])) { |
||
343 | // SAVE button |
||
344 | $saveButton = $buttonBar->makeInputButton() |
||
345 | ->setName('_savedok') |
||
346 | ->setValue('1') |
||
347 | ->setForm('TypoScriptTemplateModuleController') |
||
348 | ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.saveDoc')) |
||
349 | ->setIcon($this->moduleTemplate->getIconFactory()->getIcon( |
||
350 | 'actions-document-save', |
||
351 | Icon::SIZE_SMALL |
||
352 | )) |
||
353 | ->setShowLabelText(true); |
||
354 | $buttonBar->addButton($saveButton); |
||
355 | } elseif ($this->extClassConf['name'] === TypoScriptTemplateObjectBrowserModuleFunctionController::class |
||
356 | && !empty($sObj) |
||
357 | ) { |
||
358 | // back button in edit mode of object browser. "sObj" is set by ExtendedTemplateService |
||
359 | $urlParameters = [ |
||
360 | 'id' => $this->id |
||
361 | ]; |
||
362 | $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); |
||
363 | $backButton = $buttonBar->makeLinkButton() |
||
364 | ->setHref((string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters)) |
||
365 | ->setClasses('typo3-goBack') |
||
366 | ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.goBack')) |
||
367 | ->setIcon($this->moduleTemplate->getIconFactory()->getIcon( |
||
368 | 'actions-view-go-back', |
||
369 | Icon::SIZE_SMALL |
||
370 | )); |
||
371 | $buttonBar->addButton($backButton); |
||
372 | } |
||
373 | } |
||
374 | // Shortcut |
||
375 | $shortcutButton = $buttonBar->makeShortcutButton() |
||
376 | ->setModuleName('web_ts') |
||
377 | ->setDisplayName($this->getShortcutTitle()) |
||
378 | ->setArguments([ |
||
379 | 'route' => $this->request->getQueryParams()['route'], |
||
380 | 'id' => (int)$this->id |
||
381 | ]); |
||
382 | $buttonBar->addButton($shortcutButton); |
||
383 | } |
||
384 | |||
385 | /** |
||
386 | * Wrap title for link in template, called from client classes. |
||
387 | * |
||
388 | * @param string $title |
||
389 | * @param string $onlyKey |
||
390 | * @return string |
||
391 | */ |
||
392 | public function linkWrapTemplateTitle($title, $onlyKey = '') |
||
393 | { |
||
394 | $urlParameters = [ |
||
395 | 'id' => $this->id |
||
396 | ]; |
||
397 | if ($onlyKey) { |
||
398 | $urlParameters['e'] = [$onlyKey => 1]; |
||
399 | } else { |
||
400 | $urlParameters['e'] = ['constants' => 1]; |
||
401 | } |
||
402 | $urlParameters['SET'] = ['function' => TypoScriptTemplateInformationModuleFunctionController::class]; |
||
403 | $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); |
||
404 | $url = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters); |
||
405 | return '<a href="' . htmlspecialchars($url) . '">' . htmlspecialchars($title) . '</a>'; |
||
406 | } |
||
407 | |||
408 | /** |
||
409 | * No template, called from client classes. |
||
410 | * |
||
411 | * @param int $newStandardTemplate |
||
412 | * @return string |
||
413 | */ |
||
414 | public function noTemplate($newStandardTemplate = 0) |
||
415 | { |
||
416 | $this->templateService = GeneralUtility::makeInstance(ExtendedTemplateService::class); |
||
417 | |||
418 | $moduleContent = []; |
||
419 | $moduleContent['state'] = InfoboxViewHelper::STATE_INFO; |
||
420 | |||
421 | // New standard? |
||
422 | if ($newStandardTemplate) { |
||
423 | $selector = ''; |
||
424 | $staticsText = ''; |
||
425 | // Hook to change output, implemented for statictemplates |
||
426 | $hookObject = $this->getHookObjectForAction('newStandardTemplateView'); |
||
427 | if (!empty($hookObject)) { |
||
428 | $reference = [ |
||
429 | 'selectorHtml' => &$selector, |
||
430 | 'staticsText' => &$staticsText |
||
431 | ]; |
||
432 | GeneralUtility::callUserFunction( |
||
433 | $hookObject, |
||
434 | $reference, |
||
435 | $this |
||
436 | ); |
||
437 | $selector = $reference['selectorHtml']; |
||
438 | $staticsText = $reference['staticsText']; |
||
439 | } |
||
440 | // Extension? |
||
441 | $moduleContent['staticsText'] = $staticsText; |
||
442 | $moduleContent['selector'] = $selector; |
||
443 | } |
||
444 | // Go to previous Page with Template... |
||
445 | $previousPage = $this->templateService->ext_prevPageWithTemplate($this->id, $this->perms_clause); |
||
446 | if ($previousPage) { |
||
447 | $urlParameters = [ |
||
448 | 'id' => $previousPage['uid'] |
||
449 | ]; |
||
450 | $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); |
||
451 | $previousPage['aHref'] = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters); |
||
452 | $moduleContent['previousPage'] = $previousPage; |
||
453 | } |
||
454 | $view = $this->getFluidTemplateObject('tstemplate', 'NoTemplate'); |
||
455 | $view->assign('content', $moduleContent); |
||
456 | return $view->render(); |
||
457 | } |
||
458 | |||
459 | /** |
||
460 | * Render template menu, called from client classes. |
||
461 | * |
||
462 | * @param ServerRequestInterface $request |
||
463 | * @return string |
||
464 | */ |
||
465 | public function templateMenu(ServerRequestInterface $request) |
||
466 | { |
||
467 | $this->templateService = GeneralUtility::makeInstance(ExtendedTemplateService::class); |
||
468 | |||
469 | $all = $this->templateService->ext_getAllTemplates($this->id); |
||
470 | if (count($all) > 1) { |
||
471 | $this->MOD_MENU['templatesOnPage'] = []; |
||
472 | foreach ($all as $d) { |
||
473 | $this->MOD_MENU['templatesOnPage'][$d['uid']] = $d['title']; |
||
474 | } |
||
475 | } |
||
476 | $this->MOD_SETTINGS = BackendUtility::getModuleData( |
||
477 | $this->MOD_MENU, |
||
478 | $request->getParsedBody()['SET'] ?? $request->getQueryParams()['SET'] ?? [], |
||
479 | 'web_ts', |
||
480 | '', |
||
481 | $this->modMenu_dontValidateList, |
||
482 | $this->modMenu_setDefaultList |
||
483 | ); |
||
484 | return BackendUtility::getFuncMenu( |
||
485 | $this->id, |
||
486 | 'SET[templatesOnPage]', |
||
487 | $this->MOD_SETTINGS['templatesOnPage'], |
||
488 | $this->MOD_MENU['templatesOnPage'] |
||
489 | ); |
||
490 | } |
||
491 | |||
492 | /** |
||
493 | * Create template, called from client classes. |
||
494 | * |
||
495 | * @param int $id |
||
496 | * @param int $actTemplateId |
||
497 | * @return string |
||
498 | */ |
||
499 | public function createTemplate($id, $actTemplateId = 0) |
||
500 | { |
||
501 | $recData = []; |
||
502 | $tce = GeneralUtility::makeInstance(DataHandler::class); |
||
503 | |||
504 | if ($this->request->getParsedBody()['createExtension'] ?? $this->request->getQueryParams()['createExtension'] ?? false) { |
||
505 | $recData['sys_template']['NEW'] = [ |
||
506 | 'pid' => $actTemplateId ? -1 * $actTemplateId : $id, |
||
507 | 'title' => '+ext' |
||
508 | ]; |
||
509 | $tce->start($recData, []); |
||
510 | $tce->process_datamap(); |
||
511 | } elseif ($this->request->getParsedBody()['newWebsite'] ?? $this->request->getQueryParams()['newWebsite'] ?? false) { |
||
512 | // Hook to handle row data, implemented for statictemplates |
||
513 | $hookObject = $this->getHookObjectForAction('newStandardTemplateHandler'); |
||
514 | if (!empty($hookObject)) { |
||
515 | $reference = [ |
||
516 | 'recData' => &$recData, |
||
517 | 'id' => $id, |
||
518 | ]; |
||
519 | GeneralUtility::callUserFunction( |
||
520 | $hookObject, |
||
521 | $reference, |
||
522 | $this |
||
523 | ); |
||
524 | $recData = $reference['recData']; |
||
525 | } else { |
||
526 | $recData['sys_template']['NEW'] = [ |
||
527 | 'pid' => $id, |
||
528 | 'title' => $this->getLanguageService()->getLL('titleNewSite'), |
||
529 | 'sorting' => 0, |
||
530 | 'root' => 1, |
||
531 | 'clear' => 3, |
||
532 | 'config' => ' |
||
533 | # Default PAGE object: |
||
534 | page = PAGE |
||
535 | page.10 = TEXT |
||
536 | page.10.value = HELLO WORLD! |
||
537 | ' |
||
538 | ]; |
||
539 | } |
||
540 | $tce->start($recData, []); |
||
541 | $tce->process_datamap(); |
||
542 | } |
||
543 | return $tce->substNEWwithIDs['NEW']; |
||
544 | } |
||
545 | |||
546 | /** |
||
547 | * Set page in array |
||
548 | * To render list of page tree with templates |
||
549 | * |
||
550 | * @param array $pArray Multidimensional array of page tree with template records |
||
551 | * @param array $rlArr Rootline array |
||
552 | * @param array $row Record of sys_template |
||
553 | */ |
||
554 | protected function setInPageArray(&$pArray, $rlArr, $row) |
||
555 | { |
||
556 | ksort($rlArr); |
||
557 | reset($rlArr); |
||
558 | if (!$rlArr[0]['uid']) { |
||
559 | array_shift($rlArr); |
||
560 | } |
||
561 | $cEl = current($rlArr); |
||
562 | if (empty($pArray[$cEl['uid']])) { |
||
563 | $pArray[$cEl['uid']] = $cEl; |
||
564 | } |
||
565 | array_shift($rlArr); |
||
566 | if (!empty($rlArr)) { |
||
567 | if (empty($pArray[$cEl['uid']]['_nodes'])) { |
||
568 | $pArray[$cEl['uid']]['_nodes'] = []; |
||
569 | } |
||
570 | $this->setInPageArray($pArray[$cEl['uid']]['_nodes'], $rlArr, $row); |
||
571 | } else { |
||
572 | $pArray[$cEl['uid']]['_templates'][] = $row; |
||
573 | } |
||
574 | uasort($pArray, function ($a, $b) { |
||
575 | return $a['sorting'] - $b['sorting']; |
||
576 | }); |
||
577 | } |
||
578 | |||
579 | /** |
||
580 | * Returns a new standalone view, shorthand function |
||
581 | * |
||
582 | * @param string $extensionName |
||
583 | * @param string $templateName |
||
584 | * @return StandaloneView |
||
585 | */ |
||
586 | protected function getFluidTemplateObject($extensionName, $templateName = 'Main') |
||
587 | { |
||
588 | $view = GeneralUtility::makeInstance(StandaloneView::class); |
||
589 | $view->getRenderingContext()->getTemplatePaths()->fillDefaultsByPackageName($extensionName); |
||
590 | $view->getRenderingContext()->setControllerAction($templateName); |
||
591 | $view->getRequest()->setControllerExtensionName('tstemplate'); |
||
592 | return $view; |
||
593 | } |
||
594 | |||
595 | /** |
||
596 | * Fetching all live records, and versioned records that do not have a "online ID" counterpart, |
||
597 | * as this is then handled via the BackendUtility::workspaceOL(). |
||
598 | * |
||
599 | * @param QueryBuilder $queryBuilder |
||
600 | * @param string $tableName |
||
601 | * @param int $workspaceId |
||
602 | */ |
||
603 | protected function applyWorkspaceConstraint( |
||
604 | QueryBuilder $queryBuilder, |
||
605 | string $tableName, |
||
606 | int $workspaceId |
||
607 | ) { |
||
608 | if (!BackendUtility::isTableWorkspaceEnabled($tableName)) { |
||
609 | return; |
||
610 | } |
||
611 | |||
612 | $queryBuilder->getRestrictions()->add( |
||
613 | GeneralUtility::makeInstance(WorkspaceRestriction::class, $workspaceId) |
||
614 | ); |
||
615 | } |
||
616 | |||
617 | /** |
||
618 | * @param string $action |
||
619 | * @return string |
||
620 | */ |
||
621 | protected function getHookObjectForAction($action) |
||
622 | { |
||
623 | if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][self::class][$action])) { |
||
624 | return $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][self::class][$action]; |
||
625 | } |
||
626 | return null; |
||
627 | } |
||
628 | |||
629 | /** |
||
630 | * Initializes the internal MOD_MENU array setting and unsetting items based on various conditions. It also merges in external menu items from the global array TBE_MODULES_EXT (see mergeExternalItems()) |
||
631 | * Then MOD_SETTINGS array is cleaned up (see \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleData()) so it contains only valid values. It's also updated with any SET[] values submitted. |
||
632 | * Also loads the modTSconfig internal variable. |
||
633 | * |
||
634 | * @param array $changedSettings can be anything |
||
635 | * @see mainAction() |
||
636 | * @see \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleData() |
||
637 | * @see mergeExternalItems() |
||
638 | */ |
||
639 | protected function menuConfig($changedSettings) |
||
640 | { |
||
641 | // Page / user TSconfig settings and blinding of menu-items |
||
642 | $this->modTSconfig['properties'] = BackendUtility::getPagesTSconfig($this->id)['mod.']['web_ts.'] ?? []; |
||
643 | $this->MOD_MENU['function'] = $this->mergeExternalItems('web_ts', 'function', $this->MOD_MENU['function']); |
||
644 | $blindActions = $this->modTSconfig['properties']['menu.']['function.'] ?? []; |
||
645 | foreach ($blindActions as $key => $value) { |
||
646 | if (!$value && array_key_exists($key, $this->MOD_MENU['function'])) { |
||
647 | unset($this->MOD_MENU['function'][$key]); |
||
648 | } |
||
649 | } |
||
650 | $this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, $changedSettings, 'web_ts', '', $this->modMenu_dontValidateList, $this->modMenu_setDefaultList); |
||
651 | } |
||
652 | |||
653 | /** |
||
654 | * Merges menu items from global array $TBE_MODULES_EXT |
||
655 | * |
||
656 | * @param string $modName Module name for which to find value |
||
657 | * @param string $menuKey Menu key, eg. 'function' for the function menu. |
||
658 | * @param array $menuArr The part of a MOD_MENU array to work on. |
||
659 | * @return array Modified array part. |
||
660 | * @internal |
||
661 | * @see \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::insertModuleFunction() |
||
662 | * @see menuConfig() |
||
663 | */ |
||
664 | protected function mergeExternalItems($modName, $menuKey, $menuArr) |
||
665 | { |
||
666 | $mergeArray = $GLOBALS['TBE_MODULES_EXT'][$modName]['MOD_MENU'][$menuKey]; |
||
667 | if (is_array($mergeArray)) { |
||
668 | foreach ($mergeArray as $k => $v) { |
||
669 | if (((string)$v['ws'] === '' || ($this->getBackendUser()->workspace === 0 && GeneralUtility::inList($v['ws'], 'online'))) |
||
670 | || ($this->getBackendUser()->workspace > 0 && GeneralUtility::inList($v['ws'], 'custom')) |
||
671 | ) { |
||
672 | $menuArr[$k] = $this->getLanguageService()->sL($v['title']); |
||
673 | } |
||
674 | } |
||
675 | } |
||
676 | return $menuArr; |
||
677 | } |
||
678 | |||
679 | /** |
||
680 | * Returns configuration values from the global variable $TBE_MODULES_EXT for the module given. |
||
681 | * For example if the module is named "web_info" and the "function" key ($menuKey) of MOD_SETTINGS is "stat" ($value) then you will have the values of $TBE_MODULES_EXT['webinfo']['MOD_MENU']['function']['stat'] returned. |
||
682 | * |
||
683 | * @param string $modName Module name |
||
684 | * @param string $menuKey Menu key, eg. "function" for the function menu. See $this->MOD_MENU |
||
685 | * @param string $value Optionally the value-key to fetch from the array that would otherwise have been returned if this value was not set. Look source... |
||
686 | * @return mixed The value from the TBE_MODULES_EXT array. |
||
687 | */ |
||
688 | protected function getExternalItemConfig($modName, $menuKey, $value = '') |
||
689 | { |
||
690 | if (isset($GLOBALS['TBE_MODULES_EXT'][$modName])) { |
||
691 | return (string)$value !== '' |
||
692 | ? $GLOBALS['TBE_MODULES_EXT'][$modName]['MOD_MENU'][$menuKey][$value] |
||
693 | : $GLOBALS['TBE_MODULES_EXT'][$modName]['MOD_MENU'][$menuKey]; |
||
694 | } |
||
695 | return null; |
||
696 | } |
||
697 | |||
698 | /** |
||
699 | * Creates an instance of the class found in $this->extClassConf['name'] in $this->extObj if any (this should hold three keys, "name", "path" and "title" if a "Function menu module" tries to connect...) |
||
700 | * This value in extClassConf might be set by an extension (in an ext_tables/ext_localconf file) which thus "connects" to a module. |
||
701 | * The array $this->extClassConf is set based on the value of MOD_SETTINGS[function] |
||
702 | * If an instance is created it is initiated with $this passed as value and $this->extClassConf as second argument. Further the $this->MOD_SETTING is cleaned up again after calling the init function. |
||
703 | * |
||
704 | * @see \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::insertModuleFunction() |
||
705 | * @param array $changedSettings |
||
706 | * @param ServerRequestInterface $request |
||
707 | */ |
||
708 | protected function checkExtObj($changedSettings, ServerRequestInterface $request) |
||
709 | { |
||
710 | if (is_array($this->extClassConf) && $this->extClassConf['name']) { |
||
711 | $this->extObj = GeneralUtility::makeInstance($this->extClassConf['name']); |
||
712 | $this->extObj->init($this, $request); |
||
713 | // Re-write: |
||
714 | $this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, $changedSettings, 'web_ts', '', $this->modMenu_dontValidateList, $this->modMenu_setDefaultList); |
||
715 | } |
||
716 | } |
||
717 | |||
718 | /** |
||
719 | * Return the content of the 'main' function inside the "Function menu module" if present |
||
720 | * |
||
721 | * @return string|null |
||
722 | */ |
||
723 | protected function getExtObjContent() |
||
724 | { |
||
725 | // Calls the 'main' function inside the "Function menu module" if present |
||
726 | if ($this->extObj === null) { |
||
727 | $flashMessage = GeneralUtility::makeInstance( |
||
728 | FlashMessage::class, |
||
729 | $this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang.xlf:no_modules_registered'), |
||
730 | $this->getLanguageService()->getLL('title'), |
||
731 | FlashMessage::ERROR |
||
732 | ); |
||
733 | $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); |
||
734 | /** @var \TYPO3\CMS\Core\Messaging\FlashMessageQueue $defaultFlashMessageQueue */ |
||
735 | $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); |
||
736 | $defaultFlashMessageQueue->enqueue($flashMessage); |
||
737 | } elseif (is_callable([$this->extObj, 'main'])) { |
||
738 | return $this->extObj->main(); |
||
739 | } |
||
740 | |||
741 | return null; |
||
742 | } |
||
743 | |||
744 | /** |
||
745 | * Returns the shortcut title for the current page |
||
746 | * |
||
747 | * @return string |
||
748 | */ |
||
749 | protected function getShortcutTitle(): string |
||
750 | { |
||
751 | return sprintf( |
||
752 | '%s: %s [%d]', |
||
753 | $this->getLanguageService()->sL('LLL:EXT:tstemplate/Resources/Private/Language/locallang_mod.xlf:mlang_labels_tablabel'), |
||
754 | BackendUtility::getRecordTitle('pages', $this->pageinfo), |
||
755 | $this->id |
||
756 | ); |
||
757 | } |
||
758 | |||
759 | /** |
||
760 | * Returns the Language Service |
||
761 | * @return LanguageService |
||
762 | */ |
||
763 | protected function getLanguageService(): LanguageService |
||
764 | { |
||
765 | return $GLOBALS['LANG']; |
||
766 | } |
||
767 | |||
768 | /** |
||
769 | * Returns the Backend User |
||
770 | * @return BackendUserAuthentication |
||
771 | */ |
||
772 | protected function getBackendUser(): BackendUserAuthentication |
||
773 | { |
||
774 | return $GLOBALS['BE_USER']; |
||
775 | } |
||
776 | |||
777 | /** |
||
778 | * @return PageRenderer |
||
779 | */ |
||
780 | protected function getPageRenderer(): PageRenderer |
||
783 | } |
||
784 | } |
||
785 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.