[TASK] Remove dummy files in typo3/classes/
[Packages/TYPO3.CMS.git] / typo3 / sysext / t3editor / Classes / T3Editor.php
1 <?php
2 namespace TYPO3\CMS\T3Editor;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2007-2013 Tobias Liebig <mail_typo3@etobi.de>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29
30 /**
31 * Provides a javascript-driven code editor with syntax highlighting for TS, HTML, CSS and more
32 *
33 * @author Tobias Liebig <mail_typo3@etobi.de>
34 */
35 class T3Editor implements \TYPO3\CMS\Core\SingletonInterface {
36
37 const MODE_TYPOSCRIPT = 'typoscript';
38 const MODE_JAVASCRIPT = 'javascript';
39 const MODE_CSS = 'css';
40 const MODE_XML = 'xml';
41 const MODE_HTML = 'html';
42 const MODE_PHP = 'php';
43 const MODE_SPARQL = 'sparql';
44 const MODE_MIXED = 'mixed';
45 /**
46 * @var string
47 */
48 protected $mode = '';
49
50 /**
51 * @var string
52 */
53 protected $ajaxSaveType = '';
54
55 /**
56 * Counts the editors on the current page
57 *
58 * @var integer
59 */
60 protected $editorCounter = 0;
61
62 /**
63 * Flag to enable the t3editor
64 *
65 * @var boolean
66 */
67 protected $_isEnabled = TRUE;
68
69 /**
70 * sets the type of code to edit (::MODE_TYPOSCRIPT, ::MODE_JAVASCRIPT)
71 *
72 * @param $mode string Expects one of the predefined constants
73 * @return \TYPO3\CMS\T3Editor\T3Editor
74 */
75 public function setMode($mode) {
76 $this->mode = $mode;
77 return $this;
78 }
79
80 /**
81 * Set the AJAX save type
82 *
83 * @param string $ajaxSaveType
84 * @return \TYPO3\CMS\T3Editor\T3Editor
85 */
86 public function setAjaxSaveType($ajaxSaveType) {
87 $this->ajaxSaveType = $ajaxSaveType;
88 return $this;
89 }
90
91 /**
92 * Set mode by file
93 *
94 * @param string $file
95 * @return string
96 */
97 public function setModeByFile($file) {
98 $fileInfo = \TYPO3\CMS\Core\Utility\GeneralUtility::split_fileref($file);
99 return $this->setModeByType($fileInfo['fileext']);
100 }
101
102 /**
103 * Set mode by type
104 *
105 * @param string $type
106 * @return void
107 */
108 public function setModeByType($type) {
109 switch ($type) {
110 case 'html':
111
112 case 'htm':
113
114 case 'tmpl':
115 $mode = self::MODE_HTML;
116 break;
117 case 'js':
118 $mode = self::MODE_JAVASCRIPT;
119 break;
120 case 'xml':
121
122 case 'svg':
123 $mode = self::MODE_XML;
124 break;
125 case 'css':
126 $mode = self::MODE_CSS;
127 break;
128 case 'ts':
129 $mode = self::MODE_TYPOSCRIPT;
130 break;
131 case 'sparql':
132 $mode = self::MODE_SPARQL;
133 break;
134 case 'php':
135
136 case 'phpsh':
137
138 case 'inc':
139 $mode = self::MODE_PHP;
140 break;
141 default:
142 $mode = self::MODE_MIXED;
143 }
144 $this->setMode($mode);
145 }
146
147 /**
148 * Get mode
149 *
150 * @return string
151 */
152 public function getMode() {
153 return $this->mode;
154 }
155
156 /**
157 * @return boolean TRUE if the t3editor is enabled
158 */
159 public function isEnabled() {
160 return $this->_isEnabled;
161 }
162
163 /**
164 * Creates a new instance of the class
165 */
166 public function __construct() {
167 // Disable pmktextarea to avoid conflicts (thanks Peter Klein for this suggestion)
168 $GLOBALS['BE_USER']->uc['disablePMKTextarea'] = 1;
169 }
170
171 /**
172 * Retrieves JavaScript code (header part) for editor
173 *
174 * @param \TYPO3\CMS\Backend\Template\DocumentTemplate $doc
175 * @return string JavaScript code
176 */
177 public function getJavascriptCode($doc) {
178 $content = '';
179 if ($this->isEnabled()) {
180 $path_t3e = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath('t3editor');
181 $path_codemirror = 'contrib/codemirror/js/';
182 // Include needed javascript-frameworks
183 $pageRenderer = $doc->getPageRenderer();
184 /** @var $pageRenderer \TYPO3\CMS\Core\Page\PageRenderer */
185 $pageRenderer->loadPrototype();
186 $pageRenderer->loadScriptaculous();
187 // Include editor-css
188 $content .= '<link href="' . \TYPO3\CMS\Core\Utility\GeneralUtility::createVersionNumberedFilename(($GLOBALS['BACK_PATH'] . \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath('t3editor') . 'res/css/t3editor.css')) . '" type="text/css" rel="stylesheet" />';
189 // Include editor-js-lib
190 $doc->loadJavascriptLib($path_codemirror . 'codemirror.js');
191 $doc->loadJavascriptLib($path_t3e . 'res/jslib/t3editor.js');
192
193 $content .= \TYPO3\CMS\Core\Utility\GeneralUtility::wrapJS(
194 'T3editor = T3editor || {};' .
195 'T3editor.lang = ' . json_encode($this->getJavaScriptLabels()) . ';' . LF .
196 'T3editor.PATH_t3e = "' . $GLOBALS['BACK_PATH'] . $path_t3e . '"; ' . LF .
197 'T3editor.PATH_codemirror = "' . $GLOBALS['BACK_PATH'] . $path_codemirror . '"; ' . LF .
198 'T3editor.URL_typo3 = "' . htmlspecialchars(\TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . TYPO3_mainDir) . '"; ' . LF .
199 'T3editor.template = ' . $this->getPreparedTemplate() . ';' . LF .
200 'T3editor.ajaxSavetype = "' . $this->ajaxSaveType . '";' . LF
201 );
202 $content .= $this->getModeSpecificJavascriptCode();
203 }
204 return $content;
205 }
206
207 /**
208 * Get mode specific JavaScript code
209 *
210 * @return string
211 */
212 public function getModeSpecificJavascriptCode() {
213 if (empty($this->mode)) {
214 return '';
215 }
216 $path_t3e = $GLOBALS['BACK_PATH'] . \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath('t3editor');
217 $content = '';
218 if ($this->mode === self::MODE_TYPOSCRIPT) {
219 $content .= '<script type="text/javascript" src="' . $path_t3e . 'res/jslib/ts_codecompletion/tsref.js' . '"></script>';
220 $content .= '<script type="text/javascript" src="' . $path_t3e . 'res/jslib/ts_codecompletion/completionresult.js' . '"></script>';
221 $content .= '<script type="text/javascript" src="' . $path_t3e . 'res/jslib/ts_codecompletion/tsparser.js' . '"></script>';
222 $content .= '<script type="text/javascript" src="' . $path_t3e . 'res/jslib/ts_codecompletion/tscodecompletion.js' . '"></script>';
223 }
224 $content .= \TYPO3\CMS\Core\Utility\GeneralUtility::wrapJS('T3editor.parserfile = ' . $this->getParserfileByMode($this->mode) . ';' . LF . 'T3editor.stylesheet = ' . $this->getStylesheetByMode($this->mode) . ';');
225 return $content;
226 }
227
228 /**
229 * Get the template code, prepared for javascript (no line breaks, quoted in single quotes)
230 *
231 * @return string The template code, prepared to use in javascript
232 */
233 protected function getPreparedTemplate() {
234 $T3Editor_template = \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl(\TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName('EXT:t3editor/res/templates/t3editor.html'));
235 $T3Editor_template = addslashes($T3Editor_template);
236 $T3Editor_template = str_replace(array(CR, LF), array('', '\' + \''), $T3Editor_template);
237 return '\'' . $T3Editor_template . '\'';
238 }
239
240 /**
241 * Determine the correct parser js file for given mode
242 *
243 * @param string $mode
244 * @return string Parser file name
245 */
246 protected function getParserfileByMode($mode) {
247 switch ($mode) {
248 case self::MODE_TYPOSCRIPT:
249 $relPath = ($GLOBALS['BACK_PATH'] ? $GLOBALS['BACK_PATH'] : '../../../') . \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath('t3editor') . 'res/jslib/parse_typoscript/';
250 $parserfile = '["' . $relPath . 'tokenizetyposcript.js", "' . $relPath . 'parsetyposcript.js"]';
251 break;
252 case self::MODE_JAVASCRIPT:
253 $parserfile = '["tokenizejavascript.js", "parsejavascript.js"]';
254 break;
255 case self::MODE_CSS:
256 $parserfile = '"parsecss.js"';
257 break;
258 case self::MODE_XML:
259 $parserfile = '"parsexml.js"';
260 break;
261 case self::MODE_SPARQL:
262 $parserfile = '"parsesparql.js"';
263 break;
264 case self::MODE_HTML:
265 $parserfile = '["tokenizejavascript.js", "parsejavascript.js", "parsecss.js", "parsexml.js", "parsehtmlmixed.js"]';
266 break;
267 case self::MODE_PHP:
268
269 case self::MODE_MIXED:
270 $parserfile = '[' . '"tokenizejavascript.js", ' . '"parsejavascript.js", ' . '"parsecss.js", ' . '"parsexml.js", ' . '"../contrib/php/js/tokenizephp.js", ' . '"../contrib/php/js/parsephp.js", ' . '"../contrib/php/js/parsephphtmlmixed.js"' . ']';
271 break;
272 }
273 return $parserfile;
274 }
275
276 /**
277 * Determine the correct css file for given mode
278 *
279 * @param string $mode
280 * @return string css file name
281 */
282 protected function getStylesheetByMode($mode) {
283 switch ($mode) {
284 case self::MODE_TYPOSCRIPT:
285 $stylesheet = 'T3editor.PATH_t3e + "res/css/typoscriptcolors.css"';
286 break;
287 case self::MODE_JAVASCRIPT:
288 $stylesheet = 'T3editor.PATH_codemirror + "../css/jscolors.css"';
289 break;
290 case self::MODE_CSS:
291 $stylesheet = 'T3editor.PATH_codemirror + "../css/csscolors.css"';
292 break;
293 case self::MODE_XML:
294 $stylesheet = 'T3editor.PATH_codemirror + "../css/xmlcolors.css"';
295 break;
296 case self::MODE_HTML:
297 $stylesheet = 'T3editor.PATH_codemirror + "../css/xmlcolors.css", ' . 'T3editor.PATH_codemirror + "../css/jscolors.css", ' . 'T3editor.PATH_codemirror + "../css/csscolors.css"';
298 break;
299 case self::MODE_SPARQL:
300 $stylesheet = 'T3editor.PATH_codemirror + "../css/sparqlcolors.css"';
301 break;
302 case self::MODE_PHP:
303 $stylesheet = 'T3editor.PATH_codemirror + "../contrib/php/css/phpcolors.css"';
304 break;
305 case self::MODE_MIXED:
306 $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"';
307 break;
308 }
309 if ($stylesheet != '') {
310 $stylesheet = '' . $stylesheet . ', ';
311 }
312 return '[' . $stylesheet . 'T3editor.PATH_t3e + "res/css/t3editor_inner.css"]';
313 }
314
315 /**
316 * Gets the labels to be used in JavaScript in the Ext JS interface.
317 * TODO this method is copied from EXT:Recycler, maybe this should be refactored into a helper class
318 *
319 * @return array The labels to be used in JavaScript
320 */
321 protected function getJavaScriptLabels() {
322 $coreLabels = array();
323 $extensionLabels = $this->getJavaScriptLabelsFromLocallang('js.', 'label_');
324 return array_merge($coreLabels, $extensionLabels);
325 }
326
327 /**
328 * Gets labels to be used in JavaScript fetched from the current locallang file.
329 * TODO this method is copied from EXT:Recycler, maybe this should be refactored into a helper class
330 *
331 * @param string $selectionPrefix Prefix to select the correct labels (default: 'js.')
332 * @param string $stripFromSelectionName Sub-prefix to be removed from label names in the result (default: '')
333 * @return array Lables to be used in JavaScript of the current locallang file
334 * @todo Check, whether this method can be moved in a generic way to $GLOBALS['LANG']
335 */
336 protected function getJavaScriptLabelsFromLocallang($selectionPrefix = 'js.', $stripFromSelectionName = '') {
337 $extraction = array();
338 $labels = array_merge((array) $GLOBALS['LOCAL_LANG']['default'], (array) $GLOBALS['LOCAL_LANG'][$GLOBALS['LANG']->lang]);
339 // Regular expression to strip the selection prefix and possibly something from the label name:
340 $labelPattern = '#^' . preg_quote($selectionPrefix, '#') . '(' . preg_quote($stripFromSelectionName, '#') . ')?#';
341 // Iterate throuh all locallang lables:
342 foreach ($labels as $label => $value) {
343 if (strpos($label, $selectionPrefix) === 0) {
344 $key = preg_replace($labelPattern, '', $label);
345 $extraction[$key] = $value;
346 }
347 }
348 return $extraction;
349 }
350
351 /**
352 * Generates HTML with code editor
353 *
354 * @param string $name Name attribute of HTML tag
355 * @param string $class Class attribute of HTML tag
356 * @param string $content Content of the editor
357 * @param string $additionalParams Any additional editor parameters
358 * @param string $alt Alt attribute
359 * @param array $hiddenfields
360 * @return string Generated HTML code for editor
361 */
362 public function getCodeEditor($name, $class = '', $content = '', $additionalParams = '', $alt = '', array $hiddenfields = array()) {
363 $code = '';
364 if ($this->isEnabled()) {
365 $this->editorCounter++;
366 $class .= ' t3editor';
367 $alt = htmlspecialchars($alt);
368 if (!empty($alt)) {
369 $alt = ' alt="' . $alt . '"';
370 }
371 $code .= '<div>' . '<textarea id="t3editor_' . $this->editorCounter . '" ' . 'name="' . $name . '" ' . 'class="' . $class . '" ' . $additionalParams . ' ' . $alt . '>' . htmlspecialchars($content) . '</textarea></div>';
372 $checked = $GLOBALS['BE_USER']->uc['disableT3Editor'] ? 'checked="checked"' : '';
373 $code .= '<br /><br />' . '<input type="checkbox" ' . 'class="checkbox t3editor_disableEditor" ' . 'onclick="T3editor.toggleEditor(this);" ' . 'name="t3editor_disableEditor" ' . 'value="true" ' . 'id="t3editor_disableEditor_' . $this->editorCounter . '_checkbox" ' . $checked . ' />&nbsp;' . '<label for="t3editor_disableEditor_' . $this->editorCounter . '_checkbox">' . $GLOBALS['LANG']->getLL('deactivate') . '</label>' . '<br /><br />';
374 if (count($hiddenfields)) {
375 foreach ($hiddenfields as $name => $value) {
376 $code .= '<input type="hidden" ' . 'name="' . $name . '" ' . 'value="' . $value . '" />';
377 }
378 }
379 } else {
380 // Fallback
381 if (!empty($class)) {
382 $class = 'class="' . $class . '" ';
383 }
384 $code .= '<textarea name="' . $name . '" ' . $class . $additionalParams . '>' . $content . '</textarea>';
385 }
386 return $code;
387 }
388
389 /**
390 * Save the content from t3editor retrieved via Ajax
391 *
392 * new Ajax.Request('/dev/t3e/dummy/typo3/ajax.php', {
393 * parameters: {
394 * ajaxID: 'T3Editor::saveCode',
395 * t3editor_savetype: 'tx_tstemplateinfo'
396 * }
397 * });
398 *
399 * @param array $params Parameters (not used yet)
400 * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxObj AjaxRequestHandler to handle response
401 */
402 public function ajaxSaveCode($params, $ajaxObj) {
403 // cancel if its not an Ajax request
404 if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX) {
405 $ajaxObj->setContentFormat('json');
406 $codeType = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('t3editor_savetype');
407 $savingsuccess = FALSE;
408 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/t3editor/classes/class.tx_t3editor.php']['ajaxSaveCode'])) {
409 $_params = array(
410 'pObj' => &$this,
411 'type' => $codeType,
412 'ajaxObj' => &$ajaxObj
413 );
414 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/t3editor/classes/class.tx_t3editor.php']['ajaxSaveCode'] as $key => $_funcRef) {
415 $savingsuccess = \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction($_funcRef, $_params, $this) || $savingsuccess;
416 }
417 }
418 $ajaxObj->setContent(array('result' => $savingsuccess));
419 }
420 }
421
422 /**
423 * Gets plugins that are defined at $TYPO3_CONF_VARS['EXTCONF']['t3editor']['plugins']
424 * (called by typo3/ajax.php)
425 *
426 * @param array $params additional parameters (not used here)
427 * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler &$ajaxObj The AjaxRequestHandler object of this request
428 * @return void
429 * @author Oliver Hader <oliver@typo3.org>
430 */
431 public function getPlugins($params, \TYPO3\CMS\Core\Http\AjaxRequestHandler &$ajaxObj) {
432 $result = array();
433 $plugins = &$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['t3editor']['plugins'];
434 if (is_array($plugins)) {
435 $result = array_values($plugins);
436 }
437 $ajaxObj->setContent($result);
438 $ajaxObj->setContentFormat('jsonbody');
439 }
440
441 }
442
443 ?>