[TASK] Simplify TypoScript Info Module
[Packages/TYPO3.CMS.git] / typo3 / sysext / tstemplate / Classes / Controller / TypoScriptTemplateInformationModuleFunctionController.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 TYPO3\CMS\Core\TypoScript\ExtendedTemplateService;
18 use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20 use TYPO3\CMS\Core\Utility\HttpUtility;
21 use TYPO3\CMS\Core\Utility\MathUtility;
22 use TYPO3\CMS\Backend\Module\AbstractFunctionModule;
23 use TYPO3\CMS\Backend\Utility\IconUtility;
24 use TYPO3\CMS\Backend\Utility\BackendUtility;
25 use TYPO3\CMS\Lang\LanguageService;
26
27 /**
28 * This class displays the Info/Modify screen of the Web > Template module
29 *
30 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
31 */
32 class TypoScriptTemplateInformationModuleFunctionController extends AbstractFunctionModule {
33
34 /**
35 * Indicator for t3editor, whether data is stored
36 *
37 * @var bool
38 */
39 public $tce_processed = FALSE;
40
41 /**
42 * @var TypoScriptTemplateModuleController
43 */
44 public $pObj;
45
46 /**
47 * Creates a row for a HTML table
48 *
49 * @param string $label The label to be shown (e.g. 'Title:', 'Sitetitle:')
50 * @param string $data The data/information to be shown (e.g. 'Template for my site')
51 * @param string $field The field/variable to be sent on clicking the edit icon (e.g. 'title', 'sitetitle')
52 * @param int $id The field/variable to be sent on clicking the edit icon (e.g. 'title', 'sitetitle')
53 * @return string A row for a HTML table
54 */
55 public function tableRow($label, $data, $field, $id) {
56 $lang = $this->getLanguageService();
57 $ret = '<tr><td>';
58 if ($field === 'config' || $field === 'constants') {
59 $urlParameters = array(
60 'id' => $this->pObj->id
61 );
62 $aHref = BackendUtility::getModuleUrl('web_ts', $urlParameters);
63 $ret .= '<a href="' . htmlspecialchars(($aHref . '&e[' . $field . ']=1')) . '">';
64 } else {
65 $params = '&columnsOnly=' . $field . '&createExtension=0' . '&edit[sys_template][' . $id . ']=edit';
66 $editOnClick = BackendUtility::editOnClick($params, $GLOBALS['BACK_PATH'], '');
67 $ret .= '<a href="#" onclick="' . $editOnClick . '">';
68 }
69 $ret .= IconUtility::getSpriteIcon(
70 'actions-document-open',
71 array('title' => $lang->sL('LLL:EXT:lang/locallang_common.xlf:editField', TRUE))
72 ) . '<strong>' . $label . '</strong></a>';
73 $ret .= '</td><td width="80%">' . $data . '&nbsp;</td></tr>';
74 return $ret;
75 }
76
77 /**
78 * Create an instance of \TYPO3\CMS\Core\TypoScript\ExtendedTemplateService in
79 * $GLOBALS['tmpl'] and looks for the first (visible) template
80 * record. If $template_uid was given and greater than zero, this record will be checked.
81 *
82 * @param int $pageId The uid of the current page
83 * @param int $template_uid: The uid of the template record to be rendered (only if more than one template on the current page)
84 * @return bool Returns TRUE if a template record was found, otherwise FALSE
85 */
86 public function initialize_editor($pageId, $template_uid = 0) {
87 // Initializes the module. Done in this function because we may need to re-initialize if data is submitted!
88 /** @var ExtendedTemplateService $tmpl */
89 $GLOBALS['tmpl'] = $tmpl = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\TypoScript\\ExtendedTemplateService');
90 // Do not log time-performance information
91 $tmpl->tt_track = 0;
92 $tmpl->init();
93 // Get the row of the first VISIBLE template of the page. where clause like the frontend.
94 $GLOBALS['tplRow'] = $tmpl->ext_getFirstTemplate($pageId, $template_uid);
95 if (is_array($GLOBALS['tplRow'])) {
96 $GLOBALS['tplRow'] = $this->processTemplateRowAfterLoading($GLOBALS['tplRow']);
97 return TRUE;
98 }
99 return FALSE;
100 }
101
102 /**
103 * Process template row after loading
104 *
105 * @param array $tplRow Template row
106 * @return array Preprocessed template row
107 */
108 public function processTemplateRowAfterLoading(array $tplRow) {
109 if ($this->pObj->MOD_SETTINGS['includeTypoScriptFileContent']) {
110 // Let the recursion detection counter start at 91, so that only 10 recursive calls will be resolved
111 // Otherwise the editor will be bloated with way to many lines making it hard the break the cyclic recursion.
112 $tplRow['config'] = TypoScriptParser::checkIncludeLines($tplRow['config'], 91);
113 $tplRow['constants'] = TypoScriptParser::checkIncludeLines($tplRow['constants'], 91);
114 }
115 return $tplRow;
116 }
117
118 /**
119 * Process template row before saving
120 *
121 * @param array $tplRow Template row
122 * @return array Preprocessed template row
123 */
124 public function processTemplateRowBeforeSaving(array $tplRow) {
125 if ($this->pObj->MOD_SETTINGS['includeTypoScriptFileContent']) {
126 $tplRow = TypoScriptParser::extractIncludes_array($tplRow);
127 }
128 return $tplRow;
129 }
130
131 /**
132 * @return LanguageService
133 */
134 protected function getLanguageService() {
135 return $GLOBALS['LANG'];
136 }
137
138 /**
139 * The main processing method if this class
140 *
141 * @return string Information of the template status or the taken actions as HTML string
142 */
143 public function main() {
144 $lang = $this->getLanguageService();
145 $lang->includeLLFile('EXT:tstemplate/Resources/Private/Language/locallang_info.xlf');
146 $this->pObj->MOD_MENU['includeTypoScriptFileContent'] = TRUE;
147 $e = $this->pObj->e;
148 // Checking for more than one template an if, set a menu...
149 $manyTemplatesMenu = $this->pObj->templateMenu();
150 $template_uid = 0;
151 if ($manyTemplatesMenu) {
152 $template_uid = $this->pObj->MOD_SETTINGS['templatesOnPage'];
153 }
154 // Initialize
155 $existTemplate = $this->initialize_editor($this->pObj->id, $template_uid);
156 $tplRow = $GLOBALS['tplRow'];
157 $saveId = 0;
158 if ($existTemplate) {
159 $saveId = $tplRow['_ORIG_uid'] ? $tplRow['_ORIG_uid'] : $tplRow['uid'];
160 }
161 // Create extension template
162 $newId = $this->pObj->createTemplate($this->pObj->id, $saveId);
163 if ($newId) {
164 // Switch to new template
165 $urlParameters = array(
166 'id' => $this->pObj->id,
167 'SET[templatesOnPage]' => $newId
168 );
169 $aHref = BackendUtility::getModuleUrl('web_ts', $urlParameters);
170 HttpUtility::redirect($aHref);
171 }
172 $tce = NULL;
173 $theOutput = '';
174 if ($existTemplate) {
175 // Update template ?
176 $POST = GeneralUtility::_POST();
177 if (
178 $POST['submit']
179 || MathUtility::canBeInterpretedAsInteger($POST['submit_x']) && MathUtility::canBeInterpretedAsInteger($POST['submit_y'])
180 || $POST['saveclose']
181 || MathUtility::canBeInterpretedAsInteger($POST['saveclose_x']) && MathUtility::canBeInterpretedAsInteger($POST['saveclose_y'])
182 ) {
183 // Set the data to be saved
184 $recData = array();
185 $alternativeFileName = array();
186 if (is_array($POST['data'])) {
187 foreach ($POST['data'] as $field => $val) {
188 switch ($field) {
189 case 'constants':
190 case 'config':
191 $recData['sys_template'][$saveId][$field] = $val;
192 break;
193 }
194 }
195 }
196 if (count($recData)) {
197 $recData['sys_template'][$saveId] = $this->processTemplateRowBeforeSaving($recData['sys_template'][$saveId]);
198 // Create new tce-object
199 $tce = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\DataHandling\\DataHandler');
200 $tce->stripslashes_values = 0;
201 $tce->alternativeFileName = $alternativeFileName;
202 // Initialize
203 $tce->start($recData, array());
204 // Saved the stuff
205 $tce->process_datamap();
206 // Clear the cache (note: currently only admin-users can clear the cache in tce_main.php)
207 $tce->clear_cacheCmd('all');
208 // tce were processed successfully
209 $this->tce_processed = TRUE;
210 // re-read the template ...
211 $this->initialize_editor($this->pObj->id, $template_uid);
212 // reload template menu
213 $manyTemplatesMenu = $this->pObj->templateMenu();
214 }
215 }
216 // Hook post updating template/TCE processing
217 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/tstemplate_info/class.tx_tstemplateinfo.php']['postTCEProcessingHook'])) {
218 $postTCEProcessingHook = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/tstemplate_info/class.tx_tstemplateinfo.php']['postTCEProcessingHook'];
219 if (is_array($postTCEProcessingHook)) {
220 $hookParameters = array(
221 'POST' => $POST,
222 'tce' => $tce
223 );
224 foreach ($postTCEProcessingHook as $hookFunction) {
225 GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
226 }
227 }
228 }
229 $content = IconUtility::getSpriteIconForRecord('sys_template', $tplRow, array('class' => 't3-js-clickmenutrigger', 'data-table' => 'sys_template', 'data-uid' => $tplRow['uid'], 'data-listframe' => 1)) . '<strong>' . htmlspecialchars($tplRow['title']) . '</strong>' . htmlspecialchars((trim($tplRow['sitetitle']) ? ' (' . $tplRow['sitetitle'] . ')' : ''));
230 $theOutput .= $this->pObj->doc->section($lang->getLL('templateInformation'), $content, 0, 1);
231 if ($manyTemplatesMenu) {
232 $theOutput .= $this->pObj->doc->section('', $manyTemplatesMenu);
233 }
234 $theOutput .= $this->pObj->doc->spacer(10);
235 $numberOfRows = 35;
236 // If abort pressed, nothing should be edited:
237 if ($POST['abort'] || MathUtility::canBeInterpretedAsInteger($POST['abort_x']) && MathUtility::canBeInterpretedAsInteger($POST['abort_y']) || $POST['saveclose'] || MathUtility::canBeInterpretedAsInteger($POST['saveclose_x']) && MathUtility::canBeInterpretedAsInteger($POST['saveclose_y'])) {
238 unset($e);
239 }
240 if (isset($e['constants'])) {
241 $outCode = '<textarea name="data[constants]" rows="' . $numberOfRows . '" wrap="off" class="fixed-font enable-tab"' . $this->pObj->doc->formWidth(48, TRUE, 'width:98%;height:70%') . ' class="fixed-font">' . GeneralUtility::formatForTextarea($tplRow['constants']) . '</textarea>';
242 $outCode .= '<input type="hidden" name="e[constants]" value="1">';
243 // Display "Include TypoScript file content?" checkbox
244 $outCode .= '<div class="checkbox"><label for="checkIncludeTypoScriptFileContent">' . BackendUtility::getFuncCheck($this->pObj->id, 'SET[includeTypoScriptFileContent]', $this->pObj->MOD_SETTINGS['includeTypoScriptFileContent'], '', '&e[constants]=1', 'id="checkIncludeTypoScriptFileContent"');
245 $outCode .= $lang->getLL('includeTypoScriptFileContent') . '</label></div><br />';
246 $theOutput .= $this->pObj->doc->spacer(15);
247 $theOutput .= $this->pObj->doc->section($lang->getLL('constants'), '', TRUE);
248 $theOutput .= $this->pObj->doc->sectionEnd() . $outCode;
249 }
250 if (isset($e['config'])) {
251 $outCode = '<textarea name="data[config]" rows="' . $numberOfRows . '" wrap="off" class="fixed-font enable-tab"' . $this->pObj->doc->formWidth(48, TRUE, 'width:98%;height:70%') . ' class="fixed-font">' . GeneralUtility::formatForTextarea($tplRow['config']) . '</textarea>';
252 $outCode .= '<input type="hidden" name="e[config]" value="1">';
253 // Display "Include TypoScript file content?" checkbox
254 $outCode .= '<div class="checkbox"><label for="checkIncludeTypoScriptFileContent">' . BackendUtility::getFuncCheck($this->pObj->id, 'SET[includeTypoScriptFileContent]', $this->pObj->MOD_SETTINGS['includeTypoScriptFileContent'], '', '&e[config]=1', 'id="checkIncludeTypoScriptFileContent"');
255 $outCode .= $lang->getLL('includeTypoScriptFileContent') . '</label></div><br />';
256 $theOutput .= $this->pObj->doc->spacer(15);
257 $theOutput .= $this->pObj->doc->section($lang->getLL('setup'), '', TRUE);
258 $theOutput .= $this->pObj->doc->sectionEnd() . $outCode;
259 }
260
261 // Processing:
262 $outCode = '';
263 $outCode .= $this->tableRow($lang->getLL('title'), htmlspecialchars($tplRow['title']), 'title', $tplRow['uid']);
264 $outCode .= $this->tableRow($lang->getLL('sitetitle'), htmlspecialchars($tplRow['sitetitle']), 'sitetitle', $tplRow['uid']);
265 $outCode .= $this->tableRow($lang->getLL('description'), nl2br(htmlspecialchars($tplRow['description'])), 'description', $tplRow['uid']);
266 $outCode .= $this->tableRow($lang->getLL('constants'), sprintf($lang->getLL('editToView'), trim($tplRow['constants']) ? count(explode(LF, $tplRow['constants'])) : 0), 'constants', $tplRow['uid']);
267 $outCode .= $this->tableRow($lang->getLL('setup'), sprintf($lang->getLL('editToView'), trim($tplRow['config']) ? count(explode(LF, $tplRow['config'])) : 0), 'config', $tplRow['uid']);
268 $outCode = '<table class="t3-table">' . $outCode . '</table>';
269
270 // Edit all icon:
271 $editOnClick = BackendUtility::editOnClick(rawurlencode('&createExtension=0') . '&amp;edit[sys_template][' . $tplRow['uid'] . ']=edit', $GLOBALS['BACK_PATH'], '');
272 $icon = IconUtility::getSpriteIcon('actions-document-open', array('title' => $lang->getLL('editTemplateRecord'))) . $lang->getLL('editTemplateRecord');
273 $outCode .= '<br /><a href="#" onclick="' . $editOnClick . '"><strong>' . $icon . '</strong></a>';
274 $theOutput .= $this->pObj->doc->section('', $outCode);
275
276 // hook after compiling the output
277 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/tstemplate_info/class.tx_tstemplateinfo.php']['postOutputProcessingHook'])) {
278 $postOutputProcessingHook = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/tstemplate_info/class.tx_tstemplateinfo.php']['postOutputProcessingHook'];
279 if (is_array($postOutputProcessingHook)) {
280 $hookParameters = array(
281 'theOutput' => &$theOutput,
282 'POST' => $POST,
283 'e' => $e,
284 'tplRow' => $tplRow,
285 'numberOfRows' => $numberOfRows
286 );
287 foreach ($postOutputProcessingHook as $hookFunction) {
288 GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
289 }
290 }
291 }
292 } else {
293 $theOutput .= $this->pObj->noTemplate(1);
294 }
295 return $theOutput;
296 }
297
298 }