2 namespace TYPO3\CMS\Tstemplate\Controller
;
5 * This file is part of the TYPO3 CMS project.
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.
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
14 * The TYPO3 project - inspiring people to share!
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\Imaging\Icon
;
28 use TYPO3\CMS\Core\TypoScript\ExtendedTemplateService
;
29 use TYPO3\CMS\Core\Utility\GeneralUtility
;
30 use TYPO3\CMS\Core\Utility\MathUtility
;
31 use TYPO3\CMS\Fluid\View\StandaloneView
;
32 use TYPO3\CMS\Fluid\ViewHelpers\Be\InfoboxViewHelper
;
35 * Module: TypoScript Tools
37 class TypoScriptTemplateModuleController
extends BaseScriptClass
62 public $textExtensions = 'html,htm,txt,css,tmpl,inc,js';
67 public $modMenu_type = '';
72 public $modMenu_dontValidateList = '';
77 public $modMenu_setDefaultList = '';
82 public $pageinfo = array();
87 public $access = false;
90 * The name of the module
94 protected $moduleName = 'web_ts';
97 * ModuleTemplate Container
101 protected $moduleTemplate;
106 public function __construct()
108 $this->moduleTemplate
= GeneralUtility
::makeInstance(ModuleTemplate
::class);
109 $this->getLanguageService()->includeLLFile('EXT:tstemplate/Resources/Private/Language/locallang.xlf');
111 $this->MCONF
= array(
112 'name' => $this->moduleName
114 $this->moduleTemplate
->addJavaScriptCode(
117 function jumpToUrl(URL) {
118 window.location.href = URL;
130 public function init()
133 $this->id
= (int)GeneralUtility
::_GP('id');
134 $this->e
= GeneralUtility
::_GP('e');
135 $this->sObj
= GeneralUtility
::_GP('sObj');
136 $this->edit
= GeneralUtility
::_GP('edit');
137 $this->perms_clause
= $this->getBackendUser()->getPagePermsClause(1);
145 public function clearCache()
147 if (GeneralUtility
::_GP('clear_all_cache')) {
148 /** @var DataHandler $tce */
149 $tce = GeneralUtility
::makeInstance(DataHandler
::class);
150 $tce->start(array(), array());
151 $tce->clear_cacheCmd('all');
160 public function main()
163 // The page will show only if there is a valid page and if this page may be viewed by the user
164 $this->pageinfo
= BackendUtility
::readPageAccess($this->id
, $this->perms_clause
);
165 $this->access
= is_array($this->pageinfo
);
166 $view = $this->getFluidTemplateObject('tstemplate');
168 if ($this->id
&& $this->access
) {
169 $urlParameters = array(
173 $aHref = BackendUtility
::getModuleUrl('web_ts', $urlParameters);
176 $this->moduleTemplate
->addJavaScriptCode(
177 'TSTemplateInlineJS',
178 'function uFormUrl(aname) {
179 document.forms[0].action = ' . GeneralUtility
::quoteJSvalue($aHref . '#') . '+aname;
181 function brPoint(lnumber,t) {
182 window.location.href = '
183 . GeneralUtility
::quoteJSvalue(
184 $aHref . '&SET[function]=TYPO3\\CMS\\Tstemplate\\Controller\\'
185 . 'TypoScriptTemplateObjectBrowserModuleFunctionController&SET[ts_browser_type]='
186 ) . '+(t?"setup":"const")+"&breakPointLN="+lnumber;
189 if (top.fsMod) top.fsMod.recentIds["web"] = ' . $this->id
. ';'
191 $this->moduleTemplate
->getPageRenderer()->addCssInlineBlock(
192 'TSTemplateInlineStyle',
193 'TABLE#typo3-objectBrowser { width: 100%; margin-bottom: 24px; }
194 TABLE#typo3-objectBrowser A { text-decoration: none; }
195 TABLE#typo3-objectBrowser .comment { color: maroon; font-weight: bold; }
196 .ts-typoscript { width: 100%; }
197 .tsob-search-submit {margin-left: 3px; margin-right: 3px;}
198 .tst-analyzer-options { margin:5px 0; }'
200 // Setting up the context sensitive menu:
201 $this->moduleTemplate
->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ClickMenu');
202 // Build the module content
203 $view->assign('actionName', $aHref);
204 $view->assign('typoscriptTemplateModuleContent', $this->getExtObjContent());
205 // Setting up the buttons and markers for docheader
207 $this->generateMenu();
209 $queryBuilder = GeneralUtility
::makeInstance(ConnectionPool
::class)->getQueryBuilderForTable('pages');
210 $queryBuilder->getRestrictions()
212 ->add(GeneralUtility
::makeInstance(DeletedRestriction
::class))
213 ->add(GeneralUtility
::makeInstance(BackendWorkspaceRestriction
::class));
215 $result = $queryBuilder->select('pages.uid')
217 $queryBuilder->expr()->count('*', 'count'),
218 $queryBuilder->expr()->max('sys_template.root', 'root_max_val'),
219 $queryBuilder->expr()->min('sys_template.root', 'root_min_val')
222 ->from('sys_template')
223 ->where($queryBuilder->expr()->eq('pages.uid', $queryBuilder->quoteIdentifier('sys_template.pid')))
224 ->groupBy('pages.uid')
225 ->orderBy('pages.pid')
226 ->addOrderBy('pages.sorting')
230 while ($record = $result->fetch()) {
231 $this->setInPageArray($pArray, BackendUtility
::BEgetRootLine($record['uid'], 'AND 1=1'), $record);
234 $view->getRenderingContext()->setControllerAction('PageZero');
235 $view->assign('templateList', $this->renderList($pArray));
237 // RENDER LIST of pages with templates, END
238 // Setting up the buttons and markers for docheader
241 $this->content
= $view->render();
245 * Generates the menu based on $this->MOD_MENU
248 * @throws \InvalidArgumentException
250 protected function generateMenu()
252 $menu = $this->moduleTemplate
->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
253 $menu->setIdentifier('WebFuncJumpMenu');
254 foreach ($this->MOD_MENU
['function'] as $controller => $title) {
258 BackendUtility
::getModuleUrl(
263 'function' => $controller
269 if ($controller === $this->MOD_SETTINGS
['function']) {
270 $item->setActive(true);
272 $menu->addMenuItem($item);
274 $this->moduleTemplate
->getDocHeaderComponent()->getMenuRegistry()->addMenu($menu);
278 * Injects the request object for the current request or subrequest
279 * Then checks for module functions that have hooked in, and renders menu etc.
281 * @param ServerRequestInterface $request the current request
282 * @param ResponseInterface $response
283 * @return ResponseInterface the response with the content
285 public function mainAction(ServerRequestInterface
$request, ResponseInterface
$response)
287 $GLOBALS['SOBE'] = $this;
290 // Checking for first level external objects
291 $this->checkExtObj();
296 $this->moduleTemplate
->setContent($this->content
);
297 $response->getBody()->write($this->moduleTemplate
->renderContent());
302 * Create the panel of buttons for submitting the form or otherwise perform operations.
304 * @return array All available buttons as an assoc. array
306 protected function getButtons()
308 $buttonBar = $this->moduleTemplate
->getDocHeaderComponent()->getButtonBar();
309 $lang = $this->getLanguageService();
311 if ($this->id
&& $this->access
) {
313 $viewButton = $buttonBar->makeLinkButton()
315 ->setOnClick(BackendUtility
::viewOnClick(
316 $this->pageinfo
['uid'],
318 BackendUtility
::BEgetRootLine($this->pageinfo
['uid'])
320 ->setTitle($lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.showPage'))
321 ->setIcon($this->moduleTemplate
->getIconFactory()->getIcon('actions-document-view', Icon
::SIZE_SMALL
));
322 $buttonBar->addButton($viewButton, ButtonBar
::BUTTON_POSITION_LEFT
, 99);
323 if ($this->extClassConf
['name'] === TypoScriptTemplateInformationModuleFunctionController
::class) {
325 $urlParameters = array(
328 'createExtension' => 'new'
331 if (!empty($this->e
) && !GeneralUtility
::_POST('_saveandclosedok')) {
332 $saveButton = $buttonBar->makeInputButton()
333 ->setName('_savedok')
335 ->setForm('TypoScriptTemplateModuleController')
336 ->setIcon($this->moduleTemplate
->getIconFactory()->getIcon(
337 'actions-document-save',
340 ->setTitle($lang->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveDoc'));
342 $saveAndCloseButton = $buttonBar->makeInputButton()
343 ->setName('_saveandclosedok')
345 ->setForm('TypoScriptTemplateModuleController')
346 ->setTitle($lang->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveCloseDoc'))
347 ->setIcon($this->moduleTemplate
->getIconFactory()->getIcon(
348 'actions-document-save-close',
352 $splitButtonElement = $buttonBar->makeSplitButton()
353 ->addItem($saveButton)
354 ->addItem($saveAndCloseButton);
356 $buttonBar->addButton($splitButtonElement, ButtonBar
::BUTTON_POSITION_LEFT
, 3);
359 $closeButton = $buttonBar->makeLinkButton()
360 ->setHref(BackendUtility
::getModuleUrl('web_ts', array('id' => $this->id
)))
361 ->setTitle($lang->sL('LLL:EXT:lang/locallang_core.xlf:rm.closeDoc'))
362 ->setIcon($this->moduleTemplate
->getIconFactory()->getIcon(
363 'actions-document-close',
366 $buttonBar->addButton($closeButton);
368 $newButton = $buttonBar->makeLinkButton()
369 ->setHref(BackendUtility
::getModuleUrl('web_ts', $urlParameters))
370 ->setTitle($lang->sL('LLL:EXT:lang/locallang_core.xlf:db_new.php.pagetitle'))
371 ->setIcon($this->moduleTemplate
->getIconFactory()->getIcon(
372 'actions-document-new',
375 $buttonBar->addButton($newButton);
377 } elseif ($this->extClassConf
['name'] === TypoScriptTemplateConstantEditorModuleFunctionController
::class
378 && !empty($this->MOD_MENU
['constant_editor_cat'])) {
380 $saveButton = $buttonBar->makeInputButton()
381 ->setName('_savedok')
383 ->setForm('TypoScriptTemplateModuleController')
384 ->setTitle($lang->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveDoc'))
385 ->setIcon($this->moduleTemplate
->getIconFactory()->getIcon(
386 'actions-document-save',
389 ->setShowLabelText(true);
390 $buttonBar->addButton($saveButton);
391 } elseif ($this->extClassConf
['name'] === TypoScriptTemplateObjectBrowserModuleFunctionController
::class) {
392 if (!empty($this->sObj
)) {
394 $urlParameters = array(
397 $backButton = $buttonBar->makeLinkButton()
398 ->setHref(BackendUtility
::getModuleUrl('web_ts', $urlParameters))
399 ->setClasses('typo3-goBack')
400 ->setTitle($lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.goBack'))
401 ->setIcon($this->moduleTemplate
->getIconFactory()->getIcon(
402 'actions-view-go-back',
405 $buttonBar->addButton($backButton);
410 $shortcutButton = $buttonBar->makeShortcutButton()
411 ->setModuleName($this->MCONF
['name'])
412 ->setGetVariables(['id', 'M']);
413 $buttonBar->addButton($shortcutButton);
418 * Wrap title for link in template
420 * @param string $title
421 * @param string $onlyKey
424 public function linkWrapTemplateTitle($title, $onlyKey = '')
426 $urlParameters = array(
429 $aHref = BackendUtility
::getModuleUrl('web_ts', $urlParameters);
431 $title = '<a href="' . htmlspecialchars(($aHref . '&e[' . $onlyKey . ']=1&SET[function]=TYPO3\\CMS\\Tstemplate\\Controller\\TypoScriptTemplateInformationModuleFunctionController')) . '">' . htmlspecialchars($title) . '</a>';
433 $title = '<a href="' . htmlspecialchars(($aHref . '&e[constants]=1&e[config]=1&SET[function]=TYPO3\\CMS\\Tstemplate\\Controller\\TypoScriptTemplateInformationModuleFunctionController')) . '">' . htmlspecialchars($title) . '</a>';
441 * @param int $newStandardTemplate
444 public function noTemplate($newStandardTemplate = 0)
446 // Defined global here!
447 /** @var ExtendedTemplateService $tmpl */
448 $tmpl = GeneralUtility
::makeInstance(ExtendedTemplateService
::class);
449 $GLOBALS['tmpl'] = $tmpl;
452 $moduleContent['state'] = InfoboxViewHelper
::STATE_INFO
;
455 if ($newStandardTemplate) {
458 // Hook to change output, implemented for statictemplates
459 $hookObject = $this->getHookObjectForAction('newStandardTemplateView');
460 if (!empty($hookObject)) {
462 'selectorHtml' => &$selector,
463 'staticsText' => &$staticsText
465 GeneralUtility
::callUserFunction(
470 $selector = $reference['selectorHtml'];
471 $staticsText = $reference['staticsText'];
474 $moduleContent['staticsText'] = $staticsText;
475 $moduleContent['selector'] = $selector;
477 // Go to previous Page with Template...
478 $previousPage = $tmpl->ext_prevPageWithTemplate($this->id
, $this->perms_clause
);
481 'id' => $previousPage['uid']
483 $previousPage['aHref'] = BackendUtility
::getModuleUrl('web_ts', $urlParameters);
484 $moduleContent['previousPage'] = $previousPage;
486 $view = $this->getFluidTemplateObject('tstemplate', 'NoTemplate');
487 $view->assign('partialName', 'NoTemplate');
488 $view->assign('content', $moduleContent);
489 return $view->render();
493 * Render template menu
497 public function templateMenu()
499 /** @var ExtendedTemplateService $tmpl */
500 $tmpl = GeneralUtility
::makeInstance(ExtendedTemplateService
::class);
501 $GLOBALS['tmpl'] = $tmpl;
504 $all = $tmpl->ext_getAllTemplates($this->id
, $this->perms_clause
);
505 if (count($all) > 1) {
506 $this->MOD_MENU
['templatesOnPage'] = array();
507 foreach ($all as $d) {
508 $this->MOD_MENU
['templatesOnPage'][$d['uid']] = $d['title'];
511 $this->MOD_SETTINGS
= BackendUtility
::getModuleData(
513 GeneralUtility
::_GP('SET'),
514 $this->MCONF
['name'],
516 $this->modMenu_dontValidateList
,
517 $this->modMenu_setDefaultList
519 return BackendUtility
::getFuncMenu(
521 'SET[templatesOnPage]',
522 $this->MOD_SETTINGS
['templatesOnPage'],
523 $this->MOD_MENU
['templatesOnPage']
531 * @param int $actTemplateId
534 public function createTemplate($id, $actTemplateId = 0)
537 /** @var DataHandler $tce */
538 $tce = GeneralUtility
::makeInstance(DataHandler
::class);
540 if (GeneralUtility
::_GP('createExtension')) {
541 $recData['sys_template']['NEW'] = array(
542 'pid' => $actTemplateId ?
-1 * $actTemplateId : $id,
545 $tce->start($recData, array());
546 $tce->process_datamap();
547 } elseif (GeneralUtility
::_GP('newWebsite')) {
548 // Hook to handle row data, implemented for statictemplates
549 $hookObject = $this->getHookObjectForAction('newStandardTemplateHandler');
550 if (!empty($hookObject)) {
552 'recData' => &$recData,
555 GeneralUtility
::callUserFunction(
560 $recData = $reference['recData'];
562 $recData['sys_template']['NEW'] = array(
564 'title' => $this->getLanguageService()->getLL('titleNewSite'),
569 # Default PAGE object:
572 page.10.value = HELLO WORLD!
576 $tce->start($recData, array());
577 $tce->process_datamap();
578 $tce->clear_cacheCmd('all');
580 return $tce->substNEWwithIDs
['NEW'];
583 // RENDER LIST of pages with templates, BEGIN
587 * @param array $pArray
588 * @param array $rlArr
592 public function setInPageArray(&$pArray, $rlArr, $row)
596 if (!$rlArr[0]['uid']) {
599 $cEl = current($rlArr);
600 $pArray[$cEl['uid']] = htmlspecialchars($cEl['title']);
602 if (!empty($rlArr)) {
603 $key = $cEl['uid'] . '.';
604 if (empty($pArray[$key])) {
605 $pArray[$key] = array();
607 $this->setInPageArray($pArray[$key], $rlArr, $row);
609 $key = $cEl['uid'] . '_';
610 $pArray[$key] = $row;
617 * @param array $pArray
618 * @param array $lines
622 public function renderList($pArray, $lines = array(), $c = 0)
624 if (!is_array($pArray)) {
628 $statusCheckedIcon = $this->moduleTemplate
->getIconFactory()
629 ->getIcon('status-status-checked', Icon
::SIZE_SMALL
)->render();
631 foreach ($pArray as $k => $v) {
632 if (MathUtility
::canBeInterpretedAsInteger($k)) {
635 $line['marginLeft'] = $c * 20;
636 $line['class'] = ($i++ %
2 === 0 ?
'bgColor4' : 'bgColor6');
637 $line['pageTitle'] = GeneralUtility
::fixed_lgd_cs($pArray[$k], 30);
638 $line['icon'] = $this->moduleTemplate
->getIconFactory()
641 BackendUtility
::getRecordWSOL('pages', $k),
644 if (!empty($pArray[$key])) {
645 $line['href'] = GeneralUtility
::linkThisScript(array('id' => (int)$k));
646 $line['title'] = 'ID: ' . (int)$k;
647 $line['count'] = $pArray[$k . '_']['count'];
648 $line['root_max_val'] = ($pArray[$key]['root_max_val'] > 0 ?
$statusCheckedIcon : ' ');
649 $line['root_min_val'] = ($pArray[$key]['root_min_val'] === 0 ?
$statusCheckedIcon : ' ');
654 $line['root_max_val'] = '';
655 $line['root_min_val'] = '';
658 $lines = $this->renderList($pArray[$k . '.'], $lines, $c +
1);
665 * Returns a new standalone view, shorthand function
667 * @param string $extensionName
668 * @param string $templateName
669 * @return StandaloneView
671 protected function getFluidTemplateObject($extensionName, $templateName = 'Main')
673 /** @var StandaloneView $view */
674 $view = GeneralUtility
::makeInstance(StandaloneView
::class);
675 $view->getRenderingContext()->getTemplatePaths()->fillDefaultsByPackageName($extensionName);
676 $view->getRenderingContext()->setControllerAction($templateName);
677 // @TODO: not sure this should stay; this value should in any case be a *proper* extension name!
678 $view->getRequest()->setControllerExtensionName('web_ts');
683 * @param string $action
686 protected function getHookObjectForAction($action)
688 if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][TypoScriptTemplateModuleController
::class][$action])) {
689 return $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][TypoScriptTemplateModuleController
::class][$action];