60fc9db58bfae1dd2cbb04e82974ff6a4668166d
[Packages/TYPO3.CMS.git] / typo3 / sysext / tstemplate / Classes / Controller / TypoScriptTemplateModuleController.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 Psr\Http\Message\ResponseInterface;
18 use Psr\Http\Message\ServerRequestInterface;
19 use TYPO3\CMS\Backend\Module\BaseScriptClass;
20 use TYPO3\CMS\Backend\Template\Components\ButtonBar;
21 use TYPO3\CMS\Backend\Template\ModuleTemplate;
22 use TYPO3\CMS\Backend\Utility\BackendUtility;
23 use TYPO3\CMS\Core\Database\ConnectionPool;
24 use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
25 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
26 use TYPO3\CMS\Core\DataHandling\DataHandler;
27 use TYPO3\CMS\Core\Http\HtmlResponse;
28 use TYPO3\CMS\Core\Imaging\Icon;
29 use TYPO3\CMS\Core\Type\Bitmask\Permission;
30 use TYPO3\CMS\Core\TypoScript\ExtendedTemplateService;
31 use TYPO3\CMS\Core\Utility\GeneralUtility;
32 use TYPO3\CMS\Core\Utility\MathUtility;
33 use TYPO3\CMS\Fluid\View\StandaloneView;
34 use TYPO3\CMS\Fluid\ViewHelpers\Be\InfoboxViewHelper;
35
36 /**
37 * Module: TypoScript Tools
38 */
39 class TypoScriptTemplateModuleController extends BaseScriptClass
40 {
41 /**
42 * @var string
43 */
44 public $perms_clause;
45
46 /**
47 * @var string
48 */
49 public $sObj;
50
51 /**
52 * @var string
53 */
54 public $edit;
55
56 /**
57 * @var string
58 */
59 public $textExtensions = 'html,htm,txt,css,tmpl,inc,js';
60
61 /**
62 * @var string
63 */
64 public $modMenu_type = '';
65
66 /**
67 * @var string
68 */
69 public $modMenu_dontValidateList = '';
70
71 /**
72 * @var string
73 */
74 public $modMenu_setDefaultList = '';
75
76 /**
77 * @var array
78 */
79 public $pageinfo = [];
80
81 /**
82 * @var bool
83 */
84 public $access = false;
85
86 /**
87 * The name of the module
88 *
89 * @var string
90 */
91 protected $moduleName = 'web_ts';
92
93 /**
94 * ModuleTemplate Container
95 *
96 * @var ModuleTemplate
97 */
98 protected $moduleTemplate;
99
100 /**
101 * @var ExtendedTemplateService
102 */
103 protected $templateService;
104
105 /**
106 * Constructor
107 */
108 public function __construct()
109 {
110 $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
111 $this->getLanguageService()->includeLLFile('EXT:tstemplate/Resources/Private/Language/locallang.xlf');
112
113 $this->MCONF = [
114 'name' => $this->moduleName
115 ];
116 $this->moduleTemplate->addJavaScriptCode(
117 'jumpToUrl',
118 '
119 function jumpToUrl(URL) {
120 window.location.href = URL;
121 return false;
122 }
123 '
124 );
125 }
126
127 /**
128 * Init
129 */
130 public function init()
131 {
132 parent::init();
133 $this->id = (int)GeneralUtility::_GP('id');
134 $this->sObj = GeneralUtility::_GP('sObj');
135 $this->edit = GeneralUtility::_GP('edit');
136 $this->perms_clause = $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW);
137 }
138
139 /**
140 * Clear cache
141 */
142 public function clearCache()
143 {
144 if (GeneralUtility::_GP('clear_all_cache')) {
145 /** @var DataHandler $tce */
146 $tce = GeneralUtility::makeInstance(DataHandler::class);
147 $tce->start([], []);
148 $tce->clear_cacheCmd('all');
149 }
150 }
151
152 /**
153 * Main
154 */
155 public function main()
156 {
157 // Access check...
158 // The page will show only if there is a valid page and if this page may be viewed by the user
159 $this->pageinfo = BackendUtility::readPageAccess($this->id, $this->perms_clause);
160 $this->access = is_array($this->pageinfo);
161 $view = $this->getFluidTemplateObject('tstemplate');
162 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
163 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
164 if ($this->id && $this->access) {
165 $urlParameters = [
166 'id' => $this->id,
167 'template' => 'all'
168 ];
169 $aHref = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters);
170
171 // JavaScript
172 $this->moduleTemplate->addJavaScriptCode(
173 'TSTemplateInlineJS',
174 'function uFormUrl(aname) {
175 document.forms[0].action = ' . GeneralUtility::quoteJSvalue($aHref . '#') . '+aname;
176 }
177 function brPoint(lnumber,t) {
178 window.location.href = '
179 . GeneralUtility::quoteJSvalue(
180 $aHref . '&SET[function]=TYPO3\\CMS\\Tstemplate\\Controller\\'
181 . 'TypoScriptTemplateObjectBrowserModuleFunctionController&SET[ts_browser_type]='
182 ) . '+(t?"setup":"const")+"&breakPointLN="+lnumber;
183 return false;
184 }
185 if (top.fsMod) top.fsMod.recentIds["web"] = ' . $this->id . ';'
186 );
187 $this->moduleTemplate->getPageRenderer()->addCssInlineBlock(
188 'TSTemplateInlineStyle',
189 'TABLE#typo3-objectBrowser { width: 100%; margin-bottom: 24px; }
190 TABLE#typo3-objectBrowser A { text-decoration: none; }
191 TABLE#typo3-objectBrowser .comment { color: maroon; font-weight: bold; }
192 .ts-typoscript { width: 100%; }
193 .tsob-search-submit {margin-left: 3px; margin-right: 3px;}
194 .tst-analyzer-options { margin:5px 0; }'
195 );
196 // Setting up the context sensitive menu:
197 $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ContextMenu');
198 // Build the module content
199 $view->assign('actionName', $aHref);
200 $view->assign('typoscriptTemplateModuleContent', $this->getExtObjContent());
201 // Setting up the buttons and markers for docheader
202 $this->getButtons();
203 $this->generateMenu();
204 } else {
205 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
206 $queryBuilder->getRestrictions()
207 ->removeAll()
208 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
209 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
210
211 $result = $queryBuilder->select('sys_template.uid')
212 ->addSelect(
213 'sys_template.pid',
214 'sys_template.title',
215 'sys_template.sitetitle',
216 'sys_template.root',
217 'sys_template.hidden',
218 'sys_template.starttime',
219 'sys_template.endtime'
220 )
221 ->from('sys_template')
222 ->orderBy('sys_template.pid')
223 ->addOrderBy('sys_template.sorting')
224 ->execute();
225 $pArray = [];
226 while ($record = $result->fetch()) {
227 $additionalFieldsForRootline = ['sorting', 'hidden', 'fe_group', 'starttime', 'endtime', 'shortcut', 'nav_hide', 'module', 'content_from_pid'];
228 $rootline = BackendUtility::BEgetRootLine($record['pid'], '', true, $additionalFieldsForRootline);
229 $this->setInPageArray($pArray, $rootline, $record);
230 }
231
232 $view->getRenderingContext()->setControllerAction('PageZero');
233 $view->assign('pageTree', $pArray);
234
235 // RENDER LIST of pages with templates, END
236 // Setting up the buttons and markers for docheader
237 $this->getButtons();
238 }
239 $this->content = $view->render();
240 }
241
242 /**
243 * Generates the menu based on $this->MOD_MENU
244 *
245 * @throws \InvalidArgumentException
246 */
247 protected function generateMenu()
248 {
249 $menu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
250 $menu->setIdentifier('WebFuncJumpMenu');
251 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
252 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
253 foreach ($this->MOD_MENU['function'] as $controller => $title) {
254 $item = $menu
255 ->makeMenuItem()
256 ->setHref(
257 (string)$uriBuilder->buildUriFromRoute(
258 $this->moduleName,
259 [
260 'id' => $this->id,
261 'SET' => [
262 'function' => $controller
263 ]
264 ]
265 )
266 )
267 ->setTitle($title);
268 if ($controller === $this->MOD_SETTINGS['function']) {
269 $item->setActive(true);
270 }
271 $menu->addMenuItem($item);
272 }
273 $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($menu);
274 }
275
276 /**
277 * Injects the request object for the current request or subrequest
278 * Then checks for module functions that have hooked in, and renders menu etc.
279 *
280 * @param ServerRequestInterface $request the current request
281 * @return ResponseInterface the response with the content
282 */
283 public function mainAction(ServerRequestInterface $request): ResponseInterface
284 {
285 $GLOBALS['SOBE'] = $this;
286 $this->init();
287
288 // Checking for first level external objects
289 $this->checkExtObj();
290
291 $this->clearCache();
292 $this->main();
293
294 $this->moduleTemplate->setContent($this->content);
295 return new HtmlResponse($this->moduleTemplate->renderContent());
296 }
297
298 /**
299 * Create the panel of buttons for submitting the form or otherwise perform operations.
300 */
301 protected function getButtons()
302 {
303 $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
304 $lang = $this->getLanguageService();
305
306 if ($this->id && $this->access) {
307 // View page
308 $viewButton = $buttonBar->makeLinkButton()
309 ->setHref('#')
310 ->setOnClick(BackendUtility::viewOnClick(
311 $this->pageinfo['uid'],
312 '',
313 BackendUtility::BEgetRootLine($this->pageinfo['uid'])
314 ))
315 ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.showPage'))
316 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-view-page', Icon::SIZE_SMALL));
317 $buttonBar->addButton($viewButton, ButtonBar::BUTTON_POSITION_LEFT, 99);
318
319 if ($this->extClassConf['name'] === TypoScriptTemplateInformationModuleFunctionController::class) {
320 // NEW button
321 $urlParameters = [
322 'id' => $this->id,
323 'template' => 'all',
324 'createExtension' => 'new'
325 ];
326 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
327 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
328 $newButton = $buttonBar->makeLinkButton()
329 ->setHref((string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters))
330 ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:db_new.php.pagetitle'))
331 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
332 'actions-add',
333 Icon::SIZE_SMALL
334 ));
335 $buttonBar->addButton($newButton);
336 } elseif ($this->extClassConf['name'] === TypoScriptTemplateConstantEditorModuleFunctionController::class
337 && !empty($this->MOD_MENU['constant_editor_cat'])) {
338 // SAVE button
339 $saveButton = $buttonBar->makeInputButton()
340 ->setName('_savedok')
341 ->setValue('1')
342 ->setForm('TypoScriptTemplateModuleController')
343 ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.saveDoc'))
344 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
345 'actions-document-save',
346 Icon::SIZE_SMALL
347 ))
348 ->setShowLabelText(true);
349 $buttonBar->addButton($saveButton);
350 } elseif ($this->extClassConf['name'] === TypoScriptTemplateObjectBrowserModuleFunctionController::class) {
351 if (!empty($this->sObj)) {
352 // BACK
353 $urlParameters = [
354 'id' => $this->id
355 ];
356 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
357 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
358 $backButton = $buttonBar->makeLinkButton()
359 ->setHref((string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters))
360 ->setClasses('typo3-goBack')
361 ->setTitle($lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.goBack'))
362 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
363 'actions-view-go-back',
364 Icon::SIZE_SMALL
365 ));
366 $buttonBar->addButton($backButton);
367 }
368 }
369 }
370 // Shortcut
371 $shortcutButton = $buttonBar->makeShortcutButton()
372 ->setModuleName($this->MCONF['name'])
373 ->setGetVariables(['id', 'route']);
374 $buttonBar->addButton($shortcutButton);
375 }
376
377 // OTHER FUNCTIONS:
378 /**
379 * Wrap title for link in template
380 *
381 * @param string $title
382 * @param string $onlyKey
383 * @return string
384 */
385 public function linkWrapTemplateTitle($title, $onlyKey = '')
386 {
387 $urlParameters = [
388 'id' => $this->id
389 ];
390 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
391 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
392 $aHref = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters);
393 if ($onlyKey) {
394 $title = '<a href="' . htmlspecialchars($aHref . '&e[' . $onlyKey . ']=1&SET[function]=TYPO3\\CMS\\Tstemplate\\Controller\\TypoScriptTemplateInformationModuleFunctionController') . '">' . htmlspecialchars($title) . '</a>';
395 } else {
396 $title = '<a href="' . htmlspecialchars($aHref . '&e[constants]=1&e[config]=1&SET[function]=TYPO3\\CMS\\Tstemplate\\Controller\\TypoScriptTemplateInformationModuleFunctionController') . '">' . htmlspecialchars($title) . '</a>';
397 }
398 return $title;
399 }
400
401 /**
402 * No template
403 *
404 * @param int $newStandardTemplate
405 * @return string
406 */
407 public function noTemplate($newStandardTemplate = 0)
408 {
409 $this->templateService = GeneralUtility::makeInstance(ExtendedTemplateService::class);
410
411 $moduleContent['state'] = InfoboxViewHelper::STATE_INFO;
412
413 // New standard?
414 if ($newStandardTemplate) {
415 $selector = '';
416 $staticsText = '';
417 // Hook to change output, implemented for statictemplates
418 $hookObject = $this->getHookObjectForAction('newStandardTemplateView');
419 if (!empty($hookObject)) {
420 $reference = [
421 'selectorHtml' => &$selector,
422 'staticsText' => &$staticsText
423 ];
424 GeneralUtility::callUserFunction(
425 $hookObject,
426 $reference,
427 $this
428 );
429 $selector = $reference['selectorHtml'];
430 $staticsText = $reference['staticsText'];
431 }
432 // Extension?
433 $moduleContent['staticsText'] = $staticsText;
434 $moduleContent['selector'] = $selector;
435 }
436 // Go to previous Page with Template...
437 $previousPage = $this->templateService->ext_prevPageWithTemplate($this->id, $this->perms_clause);
438 if ($previousPage) {
439 $urlParameters = [
440 'id' => $previousPage['uid']
441 ];
442 /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
443 $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
444 $previousPage['aHref'] = (string)$uriBuilder->buildUriFromRoute('web_ts', $urlParameters);
445 $moduleContent['previousPage'] = $previousPage;
446 }
447 $view = $this->getFluidTemplateObject('tstemplate', 'NoTemplate');
448 $view->assign('content', $moduleContent);
449 return $view->render();
450 }
451
452 /**
453 * Render template menu
454 *
455 * @return string
456 */
457 public function templateMenu()
458 {
459 $this->templateService = GeneralUtility::makeInstance(ExtendedTemplateService::class);
460
461 $all = $this->templateService->ext_getAllTemplates($this->id);
462 if (count($all) > 1) {
463 $this->MOD_MENU['templatesOnPage'] = [];
464 foreach ($all as $d) {
465 $this->MOD_MENU['templatesOnPage'][$d['uid']] = $d['title'];
466 }
467 }
468 $this->MOD_SETTINGS = BackendUtility::getModuleData(
469 $this->MOD_MENU,
470 GeneralUtility::_GP('SET'),
471 $this->MCONF['name'],
472 $this->modMenu_type,
473 $this->modMenu_dontValidateList,
474 $this->modMenu_setDefaultList
475 );
476 return BackendUtility::getFuncMenu(
477 $this->id,
478 'SET[templatesOnPage]',
479 $this->MOD_SETTINGS['templatesOnPage'],
480 $this->MOD_MENU['templatesOnPage']
481 );
482 }
483
484 /**
485 * Create template
486 *
487 * @param int $id
488 * @param int $actTemplateId
489 * @return string
490 */
491 public function createTemplate($id, $actTemplateId = 0)
492 {
493 $recData = [];
494 /** @var DataHandler $tce */
495 $tce = GeneralUtility::makeInstance(DataHandler::class);
496
497 if (GeneralUtility::_GP('createExtension')) {
498 $recData['sys_template']['NEW'] = [
499 'pid' => $actTemplateId ? -1 * $actTemplateId : $id,
500 'title' => '+ext'
501 ];
502 $tce->start($recData, []);
503 $tce->process_datamap();
504 } elseif (GeneralUtility::_GP('newWebsite')) {
505 // Hook to handle row data, implemented for statictemplates
506 $hookObject = $this->getHookObjectForAction('newStandardTemplateHandler');
507 if (!empty($hookObject)) {
508 $reference = [
509 'recData' => &$recData,
510 'id' => $id,
511 ];
512 GeneralUtility::callUserFunction(
513 $hookObject,
514 $reference,
515 $this
516 );
517 $recData = $reference['recData'];
518 } else {
519 $recData['sys_template']['NEW'] = [
520 'pid' => $id,
521 'title' => $this->getLanguageService()->getLL('titleNewSite'),
522 'sorting' => 0,
523 'root' => 1,
524 'clear' => 3,
525 'config' => '
526 # Default PAGE object:
527 page = PAGE
528 page.10 = TEXT
529 page.10.value = HELLO WORLD!
530 '
531 ];
532 }
533 $tce->start($recData, []);
534 $tce->process_datamap();
535 $tce->clear_cacheCmd('all');
536 }
537 return $tce->substNEWwithIDs['NEW'];
538 }
539
540 /**
541 * Set page in array
542 * To render list of page tree with templates
543 *
544 * @param array $pArray Multidimensional array of page tree with template records
545 * @param array $rlArr Rootline array
546 * @param array $row Record of sys_template
547 */
548 public function setInPageArray(&$pArray, $rlArr, $row)
549 {
550 ksort($rlArr);
551 reset($rlArr);
552 if (!$rlArr[0]['uid']) {
553 array_shift($rlArr);
554 }
555 $cEl = current($rlArr);
556 if (empty($pArray[$cEl['uid']])) {
557 $pArray[$cEl['uid']] = $cEl;
558 }
559 array_shift($rlArr);
560 if (!empty($rlArr)) {
561 if (empty($pArray[$cEl['uid']]['_nodes'])) {
562 $pArray[$cEl['uid']]['_nodes'] = [];
563 }
564 $this->setInPageArray($pArray[$cEl['uid']]['_nodes'], $rlArr, $row);
565 } else {
566 $pArray[$cEl['uid']]['_templates'][] = $row;
567 }
568 uasort($pArray, function ($a, $b) {
569 return $a['sorting'] - $b['sorting'];
570 });
571 }
572
573 /**
574 * Get the list
575 *
576 * @param array $pArray
577 * @param array $lines
578 * @param int $c
579 * @return array
580 * @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0
581 */
582 public function renderList($pArray, $lines = [], $c = 0)
583 {
584 trigger_error(
585 'The method `TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateModuleController::renderList` has been deprecated and should not be used any longer, this method will be removed in TYPO3 v10.0',
586 E_USER_DEPRECATED
587 );
588
589 if (!is_array($pArray)) {
590 return $lines;
591 }
592
593 $statusCheckedIcon = $this->moduleTemplate->getIconFactory()
594 ->getIcon('status-status-checked', Icon::SIZE_SMALL)->render();
595 foreach ($pArray as $k => $v) {
596 if (MathUtility::canBeInterpretedAsInteger($k)) {
597 $line = [];
598 $key = $k . '_';
599 $line['marginLeft'] = $c * 20;
600 $line['pageTitle'] = GeneralUtility::fixed_lgd_cs($pArray[$k], 30);
601 $line['icon'] = $this->moduleTemplate->getIconFactory()
602 ->getIconForRecord(
603 'pages',
604 BackendUtility::getRecordWSOL('pages', $k),
605 Icon::SIZE_SMALL
606 )->render();
607 if (!empty($pArray[$key])) {
608 $line['href'] = GeneralUtility::linkThisScript(['id' => (int)$k]);
609 $line['title'] = 'ID: ' . (int)$k;
610 $line['count'] = $pArray[$k . '_']['count'];
611 $line['root_max_val'] = ($pArray[$key]['root_max_val'] > 0 ? $statusCheckedIcon : '&nbsp;');
612 $line['root_min_val'] = ($pArray[$key]['root_min_val'] === 0 ? $statusCheckedIcon : '&nbsp;');
613 } else {
614 $line['href'] = '';
615 $line['title'] = '';
616 $line['count'] = '';
617 $line['root_max_val'] = '';
618 $line['root_min_val'] = '';
619 }
620 $lines[] = $line;
621 $lines = $this->renderList($pArray[$k . '.'], $lines, $c + 1);
622 }
623 }
624 return $lines;
625 }
626
627 /**
628 * Returns a new standalone view, shorthand function
629 *
630 * @param string $extensionName
631 * @param string $templateName
632 * @return StandaloneView
633 */
634 protected function getFluidTemplateObject($extensionName, $templateName = 'Main')
635 {
636 /** @var StandaloneView $view */
637 $view = GeneralUtility::makeInstance(StandaloneView::class);
638 $view->getRenderingContext()->getTemplatePaths()->fillDefaultsByPackageName($extensionName);
639 $view->getRenderingContext()->setControllerAction($templateName);
640 $view->getRequest()->setControllerExtensionName('tstemplate');
641 return $view;
642 }
643
644 /**
645 * @param string $action
646 * @return string
647 */
648 protected function getHookObjectForAction($action)
649 {
650 if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][self::class][$action])) {
651 return $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][self::class][$action];
652 }
653 return null;
654 }
655 }