[TASK] Deprecate t3editor->isEnabled()
[Packages/TYPO3.CMS.git] / typo3 / sysext / t3editor / Classes / T3editor.php
1 <?php
2 namespace TYPO3\CMS\T3editor;
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 use TYPO3\CMS\Core\Utility\GeneralUtility;
17
18 /**
19 * Provides a javascript-driven code editor with syntax highlighting for TS, HTML, CSS and more
20 *
21 * @author Tobias Liebig <mail_typo3@etobi.de>
22 */
23 class T3editor implements \TYPO3\CMS\Core\SingletonInterface {
24
25 const MODE_TYPOSCRIPT = 'typoscript';
26 const MODE_JAVASCRIPT = 'javascript';
27 const MODE_CSS = 'css';
28 const MODE_XML = 'xml';
29 const MODE_HTML = 'html';
30 const MODE_PHP = 'php';
31 const MODE_SPARQL = 'sparql';
32 const MODE_MIXED = 'mixed';
33 /**
34 * @var string
35 */
36 protected $mode = '';
37
38 /**
39 * @var string
40 */
41 protected $ajaxSaveType = '';
42
43 /**
44 * Counts the editors on the current page
45 *
46 * @var int
47 */
48 protected $editorCounter = 0;
49
50 /**
51 * sets the type of code to edit (::MODE_TYPOSCRIPT, ::MODE_JAVASCRIPT)
52 *
53 * @param $mode string Expects one of the predefined constants
54 * @return \TYPO3\CMS\T3editor\T3editor
55 */
56 public function setMode($mode) {
57 $this->mode = $mode;
58 return $this;
59 }
60
61 /**
62 * Set the AJAX save type
63 *
64 * @param string $ajaxSaveType
65 * @return \TYPO3\CMS\T3editor\T3editor
66 */
67 public function setAjaxSaveType($ajaxSaveType) {
68 $this->ajaxSaveType = $ajaxSaveType;
69 return $this;
70 }
71
72 /**
73 * Set mode by file
74 *
75 * @param string $file
76 * @return string
77 */
78 public function setModeByFile($file) {
79 $fileInfo = GeneralUtility::split_fileref($file);
80 return $this->setModeByType($fileInfo['fileext']);
81 }
82
83 /**
84 * Set mode by type
85 *
86 * @param string $type
87 * @return void
88 */
89 public function setModeByType($type) {
90 switch ($type) {
91 case 'html':
92
93 case 'htm':
94
95 case 'tmpl':
96 $mode = self::MODE_HTML;
97 break;
98 case 'js':
99 $mode = self::MODE_JAVASCRIPT;
100 break;
101 case 'xml':
102
103 case 'svg':
104 $mode = self::MODE_XML;
105 break;
106 case 'css':
107 $mode = self::MODE_CSS;
108 break;
109 case 'ts':
110 $mode = self::MODE_TYPOSCRIPT;
111 break;
112 case 'sparql':
113 $mode = self::MODE_SPARQL;
114 break;
115 case 'php':
116
117 case 'phpsh':
118
119 case 'inc':
120 $mode = self::MODE_PHP;
121 break;
122 default:
123 $mode = self::MODE_MIXED;
124 }
125 $this->setMode($mode);
126 }
127
128 /**
129 * Get mode
130 *
131 * @return string
132 */
133 public function getMode() {
134 return $this->mode;
135 }
136
137 /**
138 * @return bool TRUE if the t3editor is enabled
139 * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8
140 */
141 public function isEnabled() {
142 GeneralUtility::logDeprecatedFunction();
143 return TRUE;
144 }
145
146 /**
147 * Creates a new instance of the class
148 */
149 public function __construct() {
150 $GLOBALS['LANG']->includeLLFile('EXT:t3editor/locallang.xlf');
151 // Disable pmktextarea to avoid conflicts (thanks Peter Klein for this suggestion)
152 $GLOBALS['BE_USER']->uc['disablePMKTextarea'] = 1;
153 }
154
155 /**
156 * Retrieves JavaScript code (header part) for editor
157 *
158 * @param \TYPO3\CMS\Backend\Template\DocumentTemplate $doc
159 * @return string JavaScript code
160 */
161 public function getJavascriptCode($doc) {
162 $content = '';
163 $path_t3e = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath('t3editor');
164 $path_codemirror = 'contrib/codemirror/js/';
165 // Include needed javascript-frameworks
166 $pageRenderer = $doc->getPageRenderer();
167 /** @var $pageRenderer \TYPO3\CMS\Core\Page\PageRenderer */
168 $pageRenderer->loadPrototype();
169 $pageRenderer->loadScriptaculous();
170 // Include editor-css
171 $content .= '<link href="' . GeneralUtility::createVersionNumberedFilename(($GLOBALS['BACK_PATH'] . \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath('t3editor') . 'res/css/t3editor.css')) . '" type="text/css" rel="stylesheet" />';
172 // Include editor-js-lib
173 $doc->loadJavascriptLib($path_codemirror . 'codemirror.js');
174 $doc->loadJavascriptLib($path_t3e . 'res/jslib/t3editor.js');
175 $pageRenderer->loadRequireJsModule('TYPO3/CMS/T3editor/T3editor');
176
177 $content .= GeneralUtility::wrapJS(
178 'T3editor = T3editor || {};' .
179 'T3editor.lang = ' . json_encode($GLOBALS['LANG']->getLabelsWithPrefix('js.', 'label_')) . ';' . LF .
180 'T3editor.PATH_t3e = "' . $GLOBALS['BACK_PATH'] . $path_t3e . '"; ' . LF .
181 'T3editor.PATH_codemirror = "' . $GLOBALS['BACK_PATH'] . $path_codemirror . '"; ' . LF .
182 'T3editor.template = ' . $this->getPreparedTemplate() . ';' . LF .
183 'T3editor.ajaxSavetype = "' . $this->ajaxSaveType . '";' . LF
184 );
185 $content .= $this->getModeSpecificJavascriptCode();
186 return $content;
187 }
188
189 /**
190 * Get mode specific JavaScript code
191 *
192 * @return string
193 */
194 public function getModeSpecificJavascriptCode() {
195 if (empty($this->mode)) {
196 return '';
197 }
198 $path_t3e = $GLOBALS['BACK_PATH'] . \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath('t3editor');
199 $content = '';
200 if ($this->mode === self::MODE_TYPOSCRIPT) {
201 $content .= '<script type="text/javascript" src="' . $path_t3e . 'res/jslib/ts_codecompletion/tsref.js' . '"></script>';
202 $content .= '<script type="text/javascript" src="' . $path_t3e . 'res/jslib/ts_codecompletion/completionresult.js' . '"></script>';
203 $content .= '<script type="text/javascript" src="' . $path_t3e . 'res/jslib/ts_codecompletion/tsparser.js' . '"></script>';
204 $content .= '<script type="text/javascript" src="' . $path_t3e . 'res/jslib/ts_codecompletion/tscodecompletion.js' . '"></script>';
205 }
206 $content .= GeneralUtility::wrapJS('T3editor.parserfile = ' . $this->getParserfileByMode($this->mode) . ';' . LF . 'T3editor.stylesheet = ' . $this->getStylesheetByMode($this->mode) . ';');
207 return $content;
208 }
209
210 /**
211 * Get the template code, prepared for javascript (no line breaks, quoted in single quotes)
212 *
213 * @return string The template code, prepared to use in javascript
214 */
215 protected function getPreparedTemplate() {
216 $T3editor_template = GeneralUtility::getUrl(GeneralUtility::getFileAbsFileName('EXT:t3editor/res/templates/t3editor.html'));
217 $T3editor_template = addslashes($T3editor_template);
218 $T3editor_template = str_replace(array(CR, LF), array('', '\' + \''), $T3editor_template);
219 return '\'' . $T3editor_template . '\'';
220 }
221
222 /**
223 * Determine the correct parser js file for given mode
224 *
225 * @param string $mode
226 * @return string Parser file name
227 */
228 protected function getParserfileByMode($mode) {
229 switch ($mode) {
230 case self::MODE_TYPOSCRIPT:
231 $relPath = ($GLOBALS['BACK_PATH'] ? $GLOBALS['BACK_PATH'] : '../../../') . \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath('t3editor') . 'res/jslib/parse_typoscript/';
232 $parserfile = '["' . $relPath . 'tokenizetyposcript.js", "' . $relPath . 'parsetyposcript.js"]';
233 break;
234 case self::MODE_JAVASCRIPT:
235 $parserfile = '["tokenizejavascript.js", "parsejavascript.js"]';
236 break;
237 case self::MODE_CSS:
238 $parserfile = '"parsecss.js"';
239 break;
240 case self::MODE_XML:
241 $parserfile = '"parsexml.js"';
242 break;
243 case self::MODE_SPARQL:
244 $parserfile = '"parsesparql.js"';
245 break;
246 case self::MODE_HTML:
247 $parserfile = '["tokenizejavascript.js", "parsejavascript.js", "parsecss.js", "parsexml.js", "parsehtmlmixed.js"]';
248 break;
249 case self::MODE_PHP:
250
251 case self::MODE_MIXED:
252 $parserfile = '[' . '"tokenizejavascript.js", ' . '"parsejavascript.js", ' . '"parsecss.js", ' . '"parsexml.js", ' . '"../contrib/php/js/tokenizephp.js", ' . '"../contrib/php/js/parsephp.js", ' . '"../contrib/php/js/parsephphtmlmixed.js"' . ']';
253 break;
254 }
255 return $parserfile;
256 }
257
258 /**
259 * Determine the correct css file for given mode
260 *
261 * @param string $mode
262 * @return string css file name
263 */
264 protected function getStylesheetByMode($mode) {
265 switch ($mode) {
266 case self::MODE_TYPOSCRIPT:
267 $stylesheet = 'T3editor.PATH_t3e + "res/css/typoscriptcolors.css"';
268 break;
269 case self::MODE_JAVASCRIPT:
270 $stylesheet = 'T3editor.PATH_codemirror + "../css/jscolors.css"';
271 break;
272 case self::MODE_CSS:
273 $stylesheet = 'T3editor.PATH_codemirror + "../css/csscolors.css"';
274 break;
275 case self::MODE_XML:
276 $stylesheet = 'T3editor.PATH_codemirror + "../css/xmlcolors.css"';
277 break;
278 case self::MODE_HTML:
279 $stylesheet = 'T3editor.PATH_codemirror + "../css/xmlcolors.css", ' . 'T3editor.PATH_codemirror + "../css/jscolors.css", ' . 'T3editor.PATH_codemirror + "../css/csscolors.css"';
280 break;
281 case self::MODE_SPARQL:
282 $stylesheet = 'T3editor.PATH_codemirror + "../css/sparqlcolors.css"';
283 break;
284 case self::MODE_PHP:
285 $stylesheet = 'T3editor.PATH_codemirror + "../contrib/php/css/phpcolors.css"';
286 break;
287 case self::MODE_MIXED:
288 $stylesheet = 'T3editor.PATH_codemirror + "../css/xmlcolors.css", ' . 'T3editor.PATH_codemirror + "../css/jscolors.css", ' . 'T3editor.PATH_codemirror + "../css/csscolors.css", ' . 'T3editor.PATH_codemirror + "../contrib/php/css/phpcolors.css"';
289 break;
290 }
291 if ($stylesheet != '') {
292 $stylesheet = '' . $stylesheet . ', ';
293 }
294 return '[' . $stylesheet . 'T3editor.PATH_t3e + "res/css/t3editor_inner.css"]';
295 }
296
297 /**
298 * Generates HTML with code editor
299 *
300 * @param string $name Name attribute of HTML tag
301 * @param string $class Class attribute of HTML tag
302 * @param string $content Content of the editor
303 * @param string $additionalParams Any additional editor parameters
304 * @param string $alt Alt attribute
305 * @param array $hiddenfields
306 * @return string Generated HTML code for editor
307 */
308 public function getCodeEditor($name, $class = '', $content = '', $additionalParams = '', $alt = '', array $hiddenfields = array()) {
309 $code = '';
310 $this->editorCounter++;
311 $class .= ' t3editor';
312 $alt = htmlspecialchars($alt);
313 if (!empty($alt)) {
314 $alt = ' alt="' . $alt . '"';
315 }
316 $code .= '<div>' . '<textarea id="t3editor_' . $this->editorCounter . '" ' . 'name="' . $name . '" ' . 'class="' . $class . '" ' . $additionalParams . ' ' . $alt . '>' . htmlspecialchars($content) . '</textarea></div>';
317 $checked = $GLOBALS['BE_USER']->uc['disableT3Editor'] ? 'checked="checked"' : '';
318 $code .= '<br /><br />' . '<div class="checkbox"><label for="t3editor_disableEditor_' . $this->editorCounter . '_checkbox"><input type="checkbox" class="checkbox t3editor_disableEditor" onclick="T3editor.toggleEditor(this);" name="t3editor_disableEditor" value="true" id="t3editor_disableEditor_' . $this->editorCounter . '_checkbox" ' . $checked . ' />' . $GLOBALS['LANG']->getLL('deactivate') . '</label></div><br /><br />';
319 if (count($hiddenfields)) {
320 foreach ($hiddenfields as $name => $value) {
321 $code .= '<input type="hidden" ' . 'name="' . $name . '" ' . 'value="' . $value . '" />';
322 }
323 }
324 return $code;
325 }
326
327 /**
328 * Save the content from t3editor retrieved via Ajax
329 *
330 * new Ajax.Request('/dev/t3e/dummy/typo3/ajax.php', {
331 * parameters: {
332 * ajaxID: 'T3editor::saveCode',
333 * t3editor_savetype: 'TypoScriptTemplateInformationModuleFunctionController'
334 * }
335 * });
336 *
337 * @param array $params Parameters (not used yet)
338 * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj AjaxRequestHandler to handle response
339 */
340 public function ajaxSaveCode($params, $ajaxObj) {
341 // cancel if its not an Ajax request
342 if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX) {
343 $ajaxObj->setContentFormat('json');
344 $codeType = GeneralUtility::_GP('t3editor_savetype');
345 $savingsuccess = FALSE;
346 try {
347 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/t3editor/classes/class.tx_t3editor.php']['ajaxSaveCode'])) {
348 $_params = array(
349 'pObj' => &$this,
350 'type' => $codeType,
351 'ajaxObj' => &$ajaxObj
352 );
353 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/t3editor/classes/class.tx_t3editor.php']['ajaxSaveCode'] as $key => $_funcRef) {
354 $savingsuccess = GeneralUtility::callUserFunction($_funcRef, $_params, $this) || $savingsuccess;
355 }
356 }
357 } catch (\Exception $e) {
358 $ajaxObj->setContent(array('result' => FALSE, 'exceptionMessage' => htmlspecialchars($e->getMessage()), 'exceptionCode' => $e->getCode()));
359 return;
360 }
361 $ajaxObj->setContent(array('result' => $savingsuccess));
362 }
363 }
364
365 /**
366 * Gets plugins that are defined at $TYPO3_CONF_VARS['EXTCONF']['t3editor']['plugins']
367 * (called by typo3/ajax.php)
368 *
369 * @param array $params additional parameters (not used here)
370 * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler &$ajaxObj The AjaxRequestHandler object of this request
371 * @return void
372 * @author Oliver Hader <oliver@typo3.org>
373 */
374 public function getPlugins($params, \TYPO3\CMS\Core\Http\AjaxRequestHandler &$ajaxObj) {
375 $result = array();
376 $plugins = &$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['t3editor']['plugins'];
377 if (is_array($plugins)) {
378 $result = array_values($plugins);
379 }
380 $ajaxObj->setContent($result);
381 $ajaxObj->setContentFormat('jsonbody');
382 }
383
384 }