Cleanup/Bugfix #11838: Hardcoded labels in t3editor
[Packages/TYPO3.CMS.git] / typo3 / sysext / t3editor / class.tx_t3editor.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2007-2009 Tobias Liebig <mail_typo3@etobi.de>
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * [CLASS/FUNCTION INDEX of SCRIPT]
29 *
30 *
31 *
32 * 47: class tx_t3editor
33 * 85: public function __construct()
34 * 117: public function getJavascriptCode()
35 * 162: public function getCodeEditor($name, $class='', $content='', $additionalParams='', $alt='')
36 *
37 * TOTAL FUNCTIONS: 3
38 * (This index is automatically created/updated by the extension "extdeveval")
39 *
40 */
41
42 /**
43 * Provides a javascript-driven code editor with syntax highlighting for TS, HTML, CSS and more
44 *
45 * @author Tobias Liebig <mail_typo3@etobi.de>
46 */
47
48 $GLOBALS['LANG']->includeLLFile('EXT:t3editor/locallang.xml');
49
50 class tx_t3editor {
51
52 /**
53 * path to the main javascript-file
54 *
55 * @var string
56 */
57 protected $filepathEditorlib;
58
59 /**
60 * path to the main stylesheet
61 *
62 * @TODO: make it configurable
63 *
64 * @var string
65 */
66 protected $filepathEditorcss;
67
68 /**
69 * counts the editors on the current page
70 *
71 * @var int
72 */
73 protected $editorCounter;
74
75 /**
76 * flag to enable the t3editor
77 *
78 * @var bool
79 */
80 public $isEnabled;
81
82 /**
83 * Creates a new instance of the class
84 *
85 * @return void
86 */
87 public function __construct() {
88
89 $this->filepathEditorlib = 'jslib/t3editor.js';
90 $this->filepathEditorcss = 'css/t3editor.css';
91 $this->editorCounter = 0;
92 $this->isEnabled = true; //TODO add a method to switch to false and turn off the editor completly
93
94 // check BE user settings
95 //TODO give $state a more descriptive name / state of/for what?
96 $state = t3lib_div::_GP('t3editor_disableEditor') == 'true' ? true : $GLOBALS['BE_USER']->uc['disableT3Editor'];
97 $this->setBEUCdisableT3Editor($state);
98
99 // disable pmktextarea to avoid conflicts (thanks Peter Klein for this suggestion)
100 $GLOBALS["BE_USER"]->uc['disablePMKTextarea'] = 1;
101 }
102
103 /**
104 * Sets editor enabled/disabled state
105 *
106 * @param boolean $state <code>true</code> if editor is disabled
107 * @return void
108 */
109 public function setBEUCdisableT3Editor($state) { //TODO better descriptive name for $state
110 if ($GLOBALS['BE_USER']->uc['disableT3Editor'] != $state) {
111 $GLOBALS['BE_USER']->uc['disableT3Editor'] = $state;
112
113 $GLOBALS['BE_USER']->writeUC();
114 }
115 }
116
117 /**
118 * Retrieves JavaScript code for editor
119 *
120 * @param template $doc
121 * @return string JavaScript code
122 */
123 public function getJavascriptCode($doc) {
124 $code = ''; // TODO find a more descriptive name (low prio)
125
126 if ($this->isEnabled) {
127
128 $path_t3e = t3lib_extmgm::extRelPath('t3editor');
129
130 // include needed javascript-frameworks
131 /** @var $pageRenderer t3lib_PageRenderer */
132 $pageRenderer = $doc->getPageRenderer();
133 $pageRenderer->loadPrototype();
134 $pageRenderer->loadScriptaculous();
135
136 // include editor-css
137 $code.= '<link href="' .
138 $GLOBALS['BACK_PATH'] .
139 t3lib_extmgm::extRelPath('t3editor') .
140 $this->filepathEditorcss .
141 '" type="text/css" rel="stylesheet" />';
142
143 // include editor-js-lib
144 $doc->loadJavascriptLib($path_t3e . 'jslib/codemirror/codemirror.js');
145 $doc->loadJavascriptLib($path_t3e . 'jslib/t3editor.js');
146
147 $doc->loadJavascriptLib($path_t3e . 'jslib/ts_codecompletion/tsref.js');
148 $doc->loadJavascriptLib($path_t3e . 'jslib/ts_codecompletion/completionresult.js');
149 $doc->loadJavascriptLib($path_t3e . 'jslib/ts_codecompletion/tsparser.js');
150 $doc->loadJavascriptLib($path_t3e . 'jslib/ts_codecompletion/tscodecompletion.js');
151
152 // set correct path to the editor
153
154 $code.= t3lib_div::wrapJS(
155 'var T3editor = T3editor || {};' .
156 'T3editor.lang = ' . json_encode($this->getJavaScriptLabels()) .';' .
157 // TODO namespace all js vars (PATH_t3e, URL_typo3, ...)
158 'var PATH_t3e = "' . $GLOBALS['BACK_PATH'] . t3lib_extmgm::extRelPath('t3editor') . '"; ' .
159 'var URL_typo3 = "' . htmlspecialchars(t3lib_div::getIndpEnv('TYPO3_SITE_URL') . TYPO3_mainDir) . '"; '
160 );
161 }
162
163 return $code;
164 }
165
166 /**
167 * Gets the labels to be used in JavaScript in the Ext JS interface.
168 * TODO this method is copied from EXT:Recycler, maybe this should be refactored into a helper class
169 *
170 * @return array The labels to be used in JavaScript
171 */
172 protected function getJavaScriptLabels() {
173 $coreLabels = array(
174 );
175 $extensionLabels = $this->getJavaScriptLabelsFromLocallang('js.', 'label_');
176 return array_merge($coreLabels, $extensionLabels);
177 }
178
179 /**
180 * Gets labels to be used in JavaScript fetched from the current locallang file.
181 * TODO this method is copied from EXT:Recycler, maybe this should be refactored into a helper class
182 *
183 * @param string $selectionPrefix: Prefix to select the correct labels (default: 'js.')
184 * @param string $stripFromSelectionName: Sub-prefix to be removed from label names in the result (default: '')
185 * @return array Lables to be used in JavaScript of the current locallang file
186 * @todo Check, whether this method can be moved in a generic way to $GLOBALS['LANG']
187 */
188 protected function getJavaScriptLabelsFromLocallang($selectionPrefix = 'js.', $stripFromSelectionName = '') {
189 $extraction = array();
190 $labels = array_merge(
191 (array)$GLOBALS['LOCAL_LANG']['default'],
192 (array)$GLOBALS['LOCAL_LANG'][$GLOBALS['LANG']->lang]
193 );
194 // Regular expression to strip the selection prefix and possibly something from the label name:
195 $labelPattern = '#^' . preg_quote($selectionPrefix, '#') . '(' . preg_quote($stripFromSelectionName, '#') . ')?#';
196 // Iterate throuh all locallang lables:
197 foreach ($labels as $label => $value) {
198 if (strpos($label, $selectionPrefix) === 0) {
199 $key = preg_replace($labelPattern, '', $label);
200 $extraction[$key] = $value;
201 }
202 }
203 return $extraction;
204 }
205
206 /**
207 * Generates HTML with code editor
208 *
209 * @param string $name Name attribute of HTML tag
210 * @param string $class Class attribute of HTML tag
211 * @param string $content Content of the editor
212 * @param string $additionalParams Any additional editor parameters
213 * @param string $alt Alt attribute
214 * @return string Generated HTML code for editor
215 */
216 public function getCodeEditor($name, $class='', $content='', $additionalParams='', $alt='', array $hiddenfields = array()) {
217 $code = '';
218
219 if ($this->isEnabled) {
220 $this->editorCounter++;
221
222 $class .= ' t3editor';
223 if (!empty($alt)) {
224 $alt = ' alt="' . $alt . '"';
225 }
226
227 $code .= '<div>' .
228 '<textarea id="t3editor_' . $this->editorCounter . '" ' .
229 'name="' . $name . '" ' .
230 'class="' . $class . '" ' .
231 $additionalParams . ' ' .
232 $alt . '>' .
233 $content .
234 '</textarea></div>';
235
236 $checked = $GLOBALS['BE_USER']->uc['disableT3Editor'] ? 'checked="checked"' : '';
237
238 $code .= '<br /><br />' .
239 '<input type="checkbox" ' .
240 'class="checkbox" ' .
241 'onclick="t3editor_toggleEditor(this);" ' .
242 'name="t3editor_disableEditor" ' .
243 'value="true" ' .
244 'id="t3editor_disableEditor_' . $this->editorCounter.'_checkbox" ' .
245 $checked.' />&nbsp;' .
246 '<label for="t3editor_disableEditor_' . $this->editorCounter . '_checkbox">' .
247 $GLOBALS['LANG']->getLL('deactivate') .
248 '</label>' .
249 '<br /><br />';
250
251 if (count($hiddenfields)) {
252 foreach ($hiddenfields as $name => $value) {
253 $code.= '<input type="hidden" ' .
254 'name="' . $name . '" ' .
255 'value="' . $value .
256 '" />';
257 }
258 }
259
260 } else {
261 // fallback
262 if (!empty($class)) {
263 $class = 'class="' . $class . '" ';
264 }
265
266 $code .= '<textarea name="' . $name . '" ' .
267 $class . $additionalParams.'>' .
268 $content . '</textarea>';
269 }
270
271 return $code;
272 }
273
274
275 public function makeGlobalEditorInstance() {
276 if (!is_object($GLOBALS['T3_VAR']['t3editorObj'])) {
277 $GLOBALS['T3_VAR']['t3editorObj'] = t3lib_div::getUserObj('EXT:t3editor/class.tx_t3editor.php:&tx_t3editor');
278 }
279 }
280
281 /**
282 * Hook-function: inject t3editor JavaScript code before the page is compiled
283 * called in typo3/template.php:startPage
284 *
285 * @param array $parameters
286 * @param template $pObj
287 */
288 public function preStartPageHook($parameters, $pObj) {
289 // enable editor in Template-Modul
290 if (preg_match('/sysext\/tstemplate\/ts\/index\.php/', $_SERVER['SCRIPT_NAME'])) {
291
292 tx_t3editor::makeGlobalEditorInstance();
293
294 // insert javascript code in document header
295 $pObj->JScode .= $GLOBALS['T3_VAR']['t3editorObj']->getJavascriptCode($pObj);
296 }
297 }
298
299
300 /**
301 * Hook-function:
302 * called in typo3/sysext/tstemplate_info/class.tx_tstemplateinfo.php
303 *
304 * @param array $parameters
305 * @param tx_tstemplateinfo $pObj
306 */
307 public function postOutputProcessingHook($parameters, $pObj) {
308 tx_t3editor::makeGlobalEditorInstance();
309 if (!$GLOBALS['T3_VAR']['t3editorObj']->isEnabled) {
310 return;
311 }
312
313 // Template Constants
314 if ($parameters['e']['constants']) {
315 $attributes = 'rows="' . $parameters['numberOfRows'] . '" ' .
316 'wrap="off" ' .
317 $pObj->pObj->doc->formWidthText(48, 'width:98%;height:60%', 'off');
318
319 $title = $GLOBALS['LANG']->getLL('template') . ' ' .
320 htmlspecialchars($parameters['tplRow']['title']) .
321 $GLOBALS['LANG']->getLL('delimiter') . ' ' .
322 $GLOBALS['LANG']->getLL('constants');
323
324 $outCode = $GLOBALS['T3_VAR']['t3editorObj']->getCodeEditor(
325 'data[constants]',
326 'fixed-font enable-tab',
327 t3lib_div::formatForTextarea($parameters['tplRow']['constants']),
328 $attributes,
329 $title,
330 array(
331 'pageId' => intval($pObj->pObj->id),
332 't3editor_savetype' => 'tx_tstemplateinfo',
333 )
334 );
335 $parameters['theOutput'] = preg_replace(
336 '/\<textarea name="data\[constants\]".*\>([^\<]*)\<\/textarea\>/mi',
337 $outCode,
338 $parameters['theOutput']
339 );
340 }
341
342 // Template Setup
343 if ($parameters['e']['config']) {
344 $attributes = 'rows="' . $parameters['numberOfRows'] . '" ' .
345 'wrap="off" ' .
346 $pObj->pObj->doc->formWidthText(48, 'width:98%;height:60%', 'off');
347
348 $title = $GLOBALS['LANG']->getLL('template') . ' ' .
349 htmlspecialchars($parameters['tplRow']['title']) .
350 $GLOBALS['LANG']->getLL('delimiter') . ' ' .
351 $GLOBALS['LANG']->getLL('setup');
352
353 $outCode = $GLOBALS['T3_VAR']['t3editorObj']->getCodeEditor(
354 'data[config]',
355 'fixed-font enable-tab',
356 t3lib_div::formatForTextarea($parameters['tplRow']['config']),
357 $attributes,
358 $title,
359 array(
360 'pageId' => intval($pObj->pObj->id),
361 't3editor_savetype' => 'tx_tstemplateinfo',
362 )
363 );
364 $parameters['theOutput'] = preg_replace(
365 '/\<textarea name="data\[config\]".*\>([^\<]*)\<\/textarea\>/mi',
366 $outCode,
367 $parameters['theOutput']
368 );
369 }
370 }
371
372 /**
373 * Save the content from t3editor retrieved via Ajax
374 *
375 * new Ajax.Request('/dev/t3e/dummy/typo3/ajax.php', {
376 * parameters: {
377 * ajaxID: 'tx_t3editor::saveCode',
378 * t3editor_savetype: 'tx_tstemplateinfo'
379 * }
380 * });
381 *
382 * @param array params Parameters (not used yet)
383 * @param TYPO3AJAX ajaxObj AjaxObject to handle response
384 */
385 public function saveCode($params, $ajaxObj) {
386 // cancel if its not an Ajax request
387 if((TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX)) {
388 $ajaxObj->setContentFormat('json');
389 $codeType = t3lib_div::_GP('t3editor_savetype');
390 $savingsuccess = false;
391
392 switch ($codeType) {
393 case 'tx_tstemplateinfo':
394 $savingsuccess = $this->saveCodeTsTemplateInfo();
395 break;
396
397 // TODO: fileadmin, extmng, TCEform, ...
398
399 default:
400 $ajaxObj->setError($GLOBALS['LANG']->getLL('unknownContentType') . ' ' . $codeType);
401 }
402 $ajaxObj->setContent(array('result' => $savingsuccess));
403 }
404 }
405
406 /**
407 * Process saving request like in class.tstemplateinfo.php (TCE processing)
408 *
409 * @return boolean true if successful
410 */
411 public function saveCodeTsTemplateInfo() {
412 $savingsuccess = false;
413
414 $pageId = t3lib_div::_GP('pageId');
415
416 if (!is_numeric($pageId) || $pageId < 1) {
417 return false;
418 }
419
420 // if given use the requested template_uid
421 // if not, use the first template-record on the page (in this case there should only be one record!)
422 $set = t3lib_div::_GP('SET');
423 $template_uid = $set['templatesOnPage'] ? $set['templatesOnPage'] : 0;
424
425 $tmpl = t3lib_div::makeInstance('t3lib_tsparser_ext'); // Defined global here!
426 $tmpl->tt_track = 0; // Do not log time-performance information
427 $tmpl->init();
428
429 // Get the row of the first VISIBLE template of the page. whereclause like the frontend.
430 $tplRow = $tmpl->ext_getFirstTemplate($pageId, $template_uid);
431 $existTemplate = (is_array($tplRow) ? true : false);
432
433 if ($existTemplate) {
434 $saveId = ($tplRow['_ORIG_uid'] ? $tplRow['_ORIG_uid'] : $tplRow['uid']);
435
436 // Update template ?
437 $POST = t3lib_div::_POST();
438
439 if ($POST['submit']) {
440 require_once(PATH_t3lib . 'class.t3lib_tcemain.php');
441
442 // Set the data to be saved
443 $recData = array();
444
445 if (is_array($POST['data'])) {
446 foreach ($POST['data'] as $field => $val) {
447 switch ($field) {
448 case 'constants':
449 case 'config':
450 case 'title':
451 case 'sitetitle':
452 case 'description':
453 $recData['sys_template'][$saveId][$field] = $val;
454 break;
455 }
456 }
457 }
458 if (count($recData)) {
459 // Create new tce-object
460 $tce = t3lib_div::makeInstance('t3lib_TCEmain');
461 $tce->stripslashes_values = 0;
462
463 // Initialize
464 $tce->start($recData, array());
465
466 // Saved the stuff
467 $tce->process_datamap();
468
469 // Clear the cache (note: currently only admin-users can clear the
470 // cache in tce_main.php)
471 $tce->clear_cacheCmd('all');
472
473 $savingsuccess = true;
474 }
475 }
476 }
477 return $savingsuccess;
478 }
479
480 /**
481 * Gets plugins that are defined at $TYPO3_CONF_VARS['EXTCONF']['t3editor']['plugins']
482 * (called by typo3/ajax.php)
483 *
484 * @param array $params: additional parameters (not used here)
485 * @param TYPO3AJAX &$ajaxObj: the TYPO3AJAX object of this request
486 * @return void
487 * @author Oliver Hader <oliver@typo3.org>
488 */
489 public function getPlugins($params, TYPO3AJAX &$ajaxObj) {
490 $result = array();
491 $plugins =& $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['t3editor']['plugins'];
492
493 if (is_array($plugins)) {
494 $result = array_values($plugins);
495 }
496
497 $ajaxObj->setContent($result);
498 $ajaxObj->setContentFormat('jsonbody');
499 }
500 }
501
502
503
504 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/t3editor/class.tx_t3editor.php']) {
505 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/t3editor/class.tx_t3editor.php']);
506 }
507
508 ?>