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