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 TYPO3\CMS\Backend\Module\BaseScriptClass
;
18 use TYPO3\CMS\Backend\Template\DocumentTemplate
;
19 use TYPO3\CMS\Core\DataHandling\DataHandler
;
20 use TYPO3\CMS\Core\Messaging\FlashMessage
;
21 use TYPO3\CMS\Core\TypoScript\ExtendedTemplateService
;
22 use TYPO3\CMS\Core\Utility\GeneralUtility
;
23 use TYPO3\CMS\Backend\Utility\BackendUtility
;
24 use TYPO3\CMS\Backend\Utility\IconUtility
;
25 use TYPO3\CMS\Core\Utility\MathUtility
;
26 use TYPO3\CMS\Extbase\
Object\ObjectManager
;
27 use TYPO3\CMS\Fluid\View\StandaloneView
;
28 use TYPO3\CMS\Fluid\ViewHelpers\Be\InfoboxViewHelper
;
31 * Module: TypoScript Tools
33 * $TYPO3_CONF_VARS["MODS"]["web_ts"]["onlineResourceDir"] = Directory of default resources. Eg. "fileadmin/res/" or so.
35 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
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';
99 public function __construct() {
100 $this->getLanguageService()->includeLLFile('EXT:tstemplate/ts/locallang.xlf');
102 $this->MCONF
= array(
103 'name' => $this->moduleName
112 public function init() {
114 $this->id
= (int)GeneralUtility
::_GP('id');
115 $this->e
= GeneralUtility
::_GP('e');
116 $this->sObj
= GeneralUtility
::_GP('sObj');
117 $this->edit
= GeneralUtility
::_GP('edit');
118 $this->perms_clause
= $this->getBackendUser()->getPagePermsClause(1);
126 public function clearCache() {
127 if (GeneralUtility
::_GP('clear_all_cache')) {
128 /** @var DataHandler $tce */
129 $tce = GeneralUtility
::makeInstance(DataHandler
::class);
130 $tce->stripslashes_values
= FALSE;
131 $tce->start(array(), array());
132 $tce->clear_cacheCmd('all');
141 public function main() {
150 // The page will show only if there is a valid page and if this page may be viewed by the user
151 $this->pageinfo
= BackendUtility
::readPageAccess($this->id
, $this->perms_clause
);
152 $this->access
= is_array($this->pageinfo
);
154 /** @var DocumentTemplate doc */
155 $this->doc
= GeneralUtility
::makeInstance(DocumentTemplate
::class);
156 $this->doc
->backPath
= $GLOBALS['BACK_PATH'];
157 $this->doc
->setModuleTemplate('EXT:tstemplate/Resources/Private/Templates/tstemplate.html');
158 $this->doc
->addStyleSheet('module', 'sysext/tstemplate/Resources/Public/Styles/styles.css');
160 $lang = $this->getLanguageService();
162 if ($this->id
&& $this->access
) {
163 $urlParameters = array(
167 $aHref = BackendUtility
::getModuleUrl('web_ts', $urlParameters);
168 $this->doc
->form
= '<form action="' . htmlspecialchars($aHref) . '" method="post" enctype="' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'] . '" name="editForm">';
171 $this->doc
->JScode
= '
172 <script language="javascript" type="text/javascript">
173 function uFormUrl(aname) {
174 document.forms[0].action = ' . GeneralUtility
::quoteJSvalue(($aHref . '#'), TRUE) . '+aname;
176 function brPoint(lnumber,t) {
177 window.location.href = ' . GeneralUtility
::quoteJSvalue(($aHref . '&SET[function]=TYPO3\\CMS\\Tstemplate\\Controller\\TypoScriptTemplateObjectBrowserModuleFunctionController&SET[ts_browser_type]='), TRUE) . '+(t?"setup":"const")+"&breakPointLN="+lnumber;
182 $this->doc
->postCode
= '
183 <script language="javascript" type="text/javascript">
184 if (top.fsMod) top.fsMod.recentIds["web"] = ' . $this->id
. ';
187 $this->doc
->inDocStylesArray
[] = '
188 TABLE#typo3-objectBrowser { width: 100%; margin-bottom: 24px; }
189 TABLE#typo3-objectBrowser A { text-decoration: none; }
190 TABLE#typo3-objectBrowser .comment { color: maroon; font-weight: bold; }
191 .ts-typoscript { width: 100%; }
192 .tsob-menu-row2 {margin-top: 10px;}
193 .tsob-search-submit {margin-left: 3px; margin-right: 3px;}
194 .tst-analyzer-options { margin:5px 0; }
196 // Setting up the context sensitive menu:
197 $this->doc
->getContextMenuCode();
198 // Build the modulle content
199 $this->content
= $this->doc
->header($lang->getLL('moduleTitle'));
200 $this->extObjContent();
201 // Setting up the buttons and markers for docheader
202 $docHeaderButtons = $this->getButtons();
203 $markers['FUNC_MENU'] = BackendUtility
::getFuncMenu($this->id
, 'SET[function]', $this->MOD_SETTINGS
['function'], $this->MOD_MENU
['function']);
204 $markers['CONTENT'] = $this->content
;
207 $records = $this->getDatabaseConnection()->exec_SELECTgetRows(
208 'pages.uid, count(*) AS count, max(sys_template.root) AS root_max_val, min(sys_template.root) AS root_min_val',
209 'pages,sys_template',
210 'pages.uid=sys_template.pid'
211 . BackendUtility
::deleteClause('pages')
212 . BackendUtility
::versioningPlaceholderClause('pages')
213 . BackendUtility
::deleteClause('sys_template')
214 . BackendUtility
::versioningPlaceholderClause('sys_template'),
216 'pages.pid, pages.sorting'
219 foreach ($records as $record) {
220 $this->setInPageArray($pArray, BackendUtility
::BEgetRootLine($record['uid'], 'AND 1=1'), $record);
223 $table = '<div class="table-fit"><table class="table table-striped table-hover" id="ts-overview">' .
226 '<th>' . $lang->getLL('pageName') . '</th>' .
227 '<th>' . $lang->getLL('templates') . '</th>' .
228 '<th>' . $lang->getLL('isRoot') . '</th>' .
229 '<th>' . $lang->getLL('isExt') . '</th>' .
232 '<tbody>' . implode('', $this->renderList($pArray)) . '</tbody>' .
235 $this->content
= $this->doc
->header($lang->getLL('moduleTitle'));
236 $this->content
.= $this->doc
->section('', '<p class="lead">' . $lang->getLL('overview') . '</p>' . $table);
238 // RENDER LIST of pages with templates, END
239 // Setting up the buttons and markers for docheader
240 $docHeaderButtons = $this->getButtons();
241 $markers['CONTENT'] = $this->content
;
244 // Build the <body> for the module
245 $this->content
= $this->doc
->moduleBody($this->pageinfo
, $docHeaderButtons, $markers);
246 // Renders the module page
247 $this->content
= $this->doc
->render('Template Tools', $this->content
);
255 public function printContent() {
260 * Create the panel of buttons for submitting the form or otherwise perform operations.
262 * @return array All available buttons as an assoc. array
264 protected function getButtons() {
275 $lang = $this->getLanguageService();
277 if ($this->id
&& $this->access
) {
279 $buttons['view'] = '<a href="#" onclick="' . htmlspecialchars(BackendUtility
::viewOnClick($this->pageinfo
['uid'], $GLOBALS['BACK_PATH'], BackendUtility
::BEgetRootLine($this->pageinfo
['uid']))) . '" title="' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.showPage', TRUE) . '">' . IconUtility
::getSpriteIcon('actions-document-view') . '</a>';
280 if ($this->extClassConf
['name'] == TypoScriptTemplateInformationModuleFunctionController
::class) {
282 $urlParameters = array(
285 'createExtension' => 'new'
287 $buttons['new'] = '<a href="' . htmlspecialchars(BackendUtility
::getModuleUrl('web_ts', $urlParameters)) . '" title="' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:db_new.php.pagetitle', TRUE) . '">' . IconUtility
::getSpriteIcon('actions-document-new') . '</a>';
288 if (!empty($this->e
) && !GeneralUtility
::_POST('saveclose')) {
289 // no NEW-button while edit
290 $buttons['new'] = '';
292 $buttons['save'] = IconUtility
::getSpriteIcon('actions-document-save', array(
293 'html' => '<input type="image" class="c-inputButton" name="submit" src="clear.gif" ' . 'title="' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveDoc', TRUE) . '" ' . 'value="' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveDoc', TRUE) . '" ' . '/>'
295 // SAVE AND CLOSE button
296 $buttons['save_close'] = IconUtility
::getSpriteIcon('actions-document-save-close', array(
297 'html' => '<input type="image" class="c-inputButton" name="saveclose" src="clear.gif" ' . 'title="' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveCloseDoc', TRUE) . '" ' . 'value="' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveCloseDoc', TRUE) . '" ' . '/>'
300 $url = BackendUtility
::getModuleUrl('web_ts', array('id' => $this->id
));
301 $buttons['close'] = '<a href="' . htmlspecialchars($url) . '" title="' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:rm.closeDoc', TRUE) . '">' . IconUtility
::getSpriteIcon('actions-document-close') .'</a>';
303 } elseif ($this->extClassConf
['name'] === TypoScriptTemplateConstantEditorModuleFunctionController
::class && count($this->MOD_MENU
['constant_editor_cat'])) {
305 $buttons['save'] = IconUtility
::getSpriteIcon('actions-document-save', array('html' => '<input type="image" class="c-inputButton" name="submit" src="clear.gif" ' . 'title="' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveDoc', TRUE) . '" ' . 'value="' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveDoc', TRUE) . '" ' . '/>'));
306 } elseif ($this->extClassConf
['name'] === TypoScriptTemplateObjectBrowserModuleFunctionController
::class) {
307 if (!empty($this->sObj
)) {
309 $urlParameters = array(
312 $aHref = BackendUtility
::getModuleUrl('web_ts', $urlParameters);
313 $buttons['back'] = '<a href="' . htmlspecialchars($aHref) . '" class="typo3-goBack" title="' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.goBack', TRUE) . '">' . IconUtility
::getSpriteIcon('actions-view-go-back') . '</a>';
317 if ($this->getBackendUser()->mayMakeShortcut()) {
318 $buttons['shortcut'] = $this->doc
->makeShortcutIcon('id, edit_record, pointer, new_unique_uid, search_field, search_levels, showLimit', implode(',', array_keys($this->MOD_MENU
)), $this->MCONF
['name']);
322 if ($this->getBackendUser()->mayMakeShortcut()) {
323 $buttons['shortcut'] = $this->doc
->makeShortcutIcon('id', '', $this->MCONF
['name']);
331 * Wrap title for link in template
333 * @param string $title
334 * @param string $onlyKey
337 public function linkWrapTemplateTitle($title, $onlyKey = '') {
338 $urlParameters = array(
341 $aHref = BackendUtility
::getModuleUrl('web_ts', $urlParameters);
343 $title = '<a href="' . htmlspecialchars(($aHref . '&e[' . $onlyKey . ']=1&SET[function]=TYPO3\\CMS\\Tstemplate\\Controller\\TypoScriptTemplateInformationModuleFunctionController')) . '">' . htmlspecialchars($title) . '</a>';
345 $title = '<a href="' . htmlspecialchars(($aHref . '&e[constants]=1&e[config]=1&SET[function]=TYPO3\\CMS\\Tstemplate\\Controller\\TypoScriptTemplateInformationModuleFunctionController')) . '">' . htmlspecialchars($title) . '</a>';
353 * @param int $newStandardTemplate
356 public function noTemplate($newStandardTemplate = 0) {
357 // Defined global here!
358 /** @var ExtendedTemplateService $tmpl */
359 $tmpl = GeneralUtility
::makeInstance(ExtendedTemplateService
::class);
360 $GLOBALS['tmpl'] = $tmpl;
362 // Do not log time-performance information
363 $tmpl->tt_track
= FALSE;
366 $lang = $this->getLanguageService();
368 $title = $lang->getLL('noTemplate');
369 $message = '<p>' . $lang->getLL('noTemplateDescription') . '<br />' . $lang->getLL('createTemplateToEditConfiguration') . '</p>';
371 $view = GeneralUtility
::makeInstance(StandaloneView
::class);
372 $view->setTemplatePathAndFilename(GeneralUtility
::getFileAbsFileName('EXT:tstemplate/Resources/Private/Templates/InfoBox.html'));
373 $view->assignMultiple(array(
375 'message' => $message,
376 'state' => InfoboxViewHelper
::STATE_INFO
378 $theOutput = $view->render();
381 if ($newStandardTemplate) {
382 // Hook to change output, implemented for statictemplates
384 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][TypoScriptTemplateModuleController
::class]['newStandardTemplateView']
389 'selectorHtml' => &$selector,
390 'staticsText' => &$staticsText
392 GeneralUtility
::callUserFunction(
393 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][TypoScriptTemplateModuleController
::class]['newStandardTemplateView'],
397 $selector = $reference['selectorHtml'];
398 $staticsText = $reference['staticsText'];
400 $selector = '<input type="hidden" name="createStandard" value="" />';
404 $theOutput .= $this->doc
->section(
405 $lang->getLL('newWebsite') . $staticsText,
406 '<p>' . $lang->getLL('newWebsiteDescription') . '</p>' . $selector . '<input class="btn btn-primary" type="submit" name="newWebsite" value="' . $lang->getLL('newWebsiteAction') . '" />',
410 $theOutput .= $this->doc
->section(
411 $lang->getLL('extTemplate'),
412 '<p>' . $lang->getLL('extTemplateDescription') . '</p>' . '<input class="btn btn-default" type="submit" name="createExtension" value="' . $lang->getLL('extTemplateAction') . '" />',
414 // Go to first appearing...
415 $first = $tmpl->ext_prevPageWithTemplate($this->id
, $this->perms_clause
);
417 $urlParameters = array(
418 'id' => $first['uid']
420 $aHref = BackendUtility
::getModuleUrl('web_ts', $urlParameters);
421 $theOutput .= $this->doc
->section(
422 $lang->getLL('goToClosest'),
423 sprintf('<p>' . $lang->getLL('goToClosestDescription') . '</p>%s' . $lang->getLL('goToClosestAction') . '%s', htmlspecialchars($first['title']), $first['uid'], '<a class="btn btn-default" href="' . htmlspecialchars($aHref) . '">', '</a>'),
430 * Render template menu
434 public function templateMenu() {
435 /** @var ExtendedTemplateService $tmpl */
436 $tmpl = GeneralUtility
::makeInstance(ExtendedTemplateService
::class);
437 $GLOBALS['tmpl'] = $tmpl;
439 // Do not log time-performance information
440 $tmpl->tt_track
= FALSE;
443 $all = $tmpl->ext_getAllTemplates($this->id
, $this->perms_clause
);
444 if (count($all) > 1) {
445 $this->MOD_MENU
['templatesOnPage'] = array();
446 foreach ($all as $d) {
447 $this->MOD_MENU
['templatesOnPage'][$d['uid']] = $d['title'];
450 $this->MOD_SETTINGS
= BackendUtility
::getModuleData($this->MOD_MENU
, GeneralUtility
::_GP('SET'), $this->MCONF
['name'], $this->modMenu_type
, $this->modMenu_dontValidateList
, $this->modMenu_setDefaultList
);
451 return BackendUtility
::getFuncMenu($this->id
, 'SET[templatesOnPage]', $this->MOD_SETTINGS
['templatesOnPage'], $this->MOD_MENU
['templatesOnPage']);
458 * @param int $actTemplateId
461 public function createTemplate($id, $actTemplateId = 0) {
463 /** @var DataHandler $tce */
464 $tce = GeneralUtility
::makeInstance(DataHandler
::class);
465 $tce->stripslashes_values
= FALSE;
467 if (GeneralUtility
::_GP('createExtension') || GeneralUtility
::_GP('createExtension_x')) {
468 $recData['sys_template']['NEW'] = array(
469 'pid' => $actTemplateId ?
-1 * $actTemplateId : $id,
472 $tce->start($recData, array());
473 $tce->process_datamap();
474 } elseif (GeneralUtility
::_GP('newWebsite')) {
475 // Hook to handle row data, implemented for statictemplates
477 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][TypoScriptTemplateModuleController
::class]['newStandardTemplateHandler']
480 'recData' => &$recData,
483 GeneralUtility
::callUserFunction(
484 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][TypoScriptTemplateModuleController
::class]['newStandardTemplateHandler'],
488 $recData = $reference['recData'];
490 $recData['sys_template']['NEW'] = array(
492 'title' => $this->getLanguageService()->getLL('titleNewSite'),
497 # Default PAGE object:
500 page.10.value = HELLO WORLD!
504 $tce->start($recData, array());
505 $tce->process_datamap();
506 $tce->clear_cacheCmd('all');
508 return $tce->substNEWwithIDs
['NEW'];
511 // RENDER LIST of pages with templates, BEGIN
515 * @param array $pArray
516 * @param array $rlArr
520 public function setInPageArray(&$pArray, $rlArr, $row) {
523 if (!$rlArr[0]['uid']) {
526 $cEl = current($rlArr);
527 $pArray[$cEl['uid']] = htmlspecialchars($cEl['title']);
530 if (!isset($pArray[($cEl['uid'] . '.')])) {
531 $pArray[$cEl['uid'] . '.'] = array();
533 $this->setInPageArray($pArray[$cEl['uid'] . '.'], $rlArr, $row);
535 $pArray[$cEl['uid'] . '_'] = $row;
542 * @param array $pArray
543 * @param array $lines
547 public function renderList($pArray, $lines = array(), $c = 0) {
550 if (!is_array($pArray)) {
554 foreach ($pArray as $k => $v) {
555 if (MathUtility
::canBeInterpretedAsInteger($k)) {
556 if (isset($pArray[$k . '_'])) {
557 $lines[] = '<tr class="' . ($i++ %
2 == 0 ?
'bgColor4' : 'bgColor6') . '">
558 <td nowrap><img src="clear.gif" width="1" height="1" hspace=' . $c * 10 . ' align="top">' . '<a href="' . htmlspecialchars(GeneralUtility
::linkThisScript(array('id' => $k))) . '">' . IconUtility
::getSpriteIconForRecord('pages', BackendUtility
::getRecordWSOL('pages', $k), array('title' => ('ID: ' . $k))) . GeneralUtility
::fixed_lgd_cs($pArray[$k], 30) . '</a></td>
559 <td>' . $pArray[($k . '_')]['count'] . '</td>
560 <td>' . ($pArray[$k . '_']['root_max_val'] > 0 ? IconUtility
::getSpriteIcon('status-status-checked') : ' ') . '</td>
561 <td>' . ($pArray[$k . '_']['root_min_val'] == 0 ? IconUtility
::getSpriteIcon('status-status-checked') : ' ') . '</td>
564 $lines[] = '<tr class="' . ($i++ %
2 == 0 ?
'bgColor4' : 'bgColor6') . '">
565 <td nowrap ><img src="clear.gif" width="1" height="1" hspace=' . $c * 10 . ' align=top>' . IconUtility
::getSpriteIconForRecord('pages', BackendUtility
::getRecordWSOL('pages', $k)) . GeneralUtility
::fixed_lgd_cs($pArray[$k], 30) . '</td>
571 $lines = $this->renderList($pArray[$k . '.'], $lines, $c +
1);