[TASK] Set a flash msg if no subpages available
[Packages/TYPO3.CMS.git] / typo3 / sysext / rtehtmlarea / Classes / RteHtmlAreaBase.php
1 <?php
2 namespace TYPO3\CMS\Rtehtmlarea;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2004-2011 Kasper Skårhøj (kasper@typo3.com)
8 * (c) 2004-2011 Philipp Borgmann <philipp.borgmann@gmx.de>
9 * (c) 2004-2012 Stanislas Rolland <typo3(arobas)sjbr.ca>
10 * All rights reserved
11 *
12 * This script is part of the TYPO3 project. The TYPO3 project is
13 * free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * The GNU General Public License can be found at
19 * http://www.gnu.org/copyleft/gpl.html.
20 * A copy is found in the textfile GPL.txt and important notices to the license
21 * from the author is found in LICENSE.txt distributed with these scripts.
22 *
23 *
24 * This script is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * This copyright notice MUST APPEAR in all copies of the script!
30 ***************************************************************/
31 /**
32 * A RTE using the htmlArea editor
33 *
34 * @author Philipp Borgmann <philipp.borgmann@gmx.de>
35 * @author Stanislas Rolland <typo3(arobas)sjbr.ca>
36 */
37 class RteHtmlAreaBase extends \TYPO3\CMS\Backend\Rte\AbstractRte {
38
39 // Configuration of supported browsers
40 /**
41 * @todo Define visibility
42 */
43 public $conf_supported_browser = array(
44 'msie' => array(
45 array(
46 'version' => 6.0,
47 'system' => array(
48 'allowed' => array(
49 'winNT',
50 'win98',
51 'win95'
52 )
53 )
54 )
55 ),
56 'gecko' => array(
57 array(
58 'version' => 1.8
59 )
60 ),
61 'webkit' => array(
62 array(
63 'version' => 523,
64 'system' => array(
65 'disallowed' => array(
66 'iOS',
67 'android'
68 )
69 )
70 )
71 ),
72 'opera' => array(
73 array(
74 'version' => 9.62,
75 'system' => array(
76 'disallowed' => array(
77 'iOS',
78 'android'
79 )
80 )
81 )
82 )
83 );
84
85 // Always hide these toolbar buttons (TYPO3 button name)
86 /**
87 * @todo Define visibility
88 */
89 public $conf_toolbar_hide = array(
90 'showhelp'
91 );
92
93 // The order of the toolbar: the name is the TYPO3-button name
94 /**
95 * @todo Define visibility
96 */
97 public $defaultToolbarOrder;
98
99 // Conversion array: TYPO3 button names to htmlArea button names
100 /**
101 * @todo Define visibility
102 */
103 public $convertToolbarForHtmlAreaArray = array(
104 'showhelp' => 'ShowHelp',
105 'space' => 'space',
106 'bar' => 'separator',
107 'linebreak' => 'linebreak'
108 );
109
110 /**
111 * @todo Define visibility
112 */
113 public $pluginButton = array();
114
115 /**
116 * @todo Define visibility
117 */
118 public $pluginLabel = array();
119
120 // Alternative style for RTE <div> tag.
121 public $RTEdivStyle;
122
123 // Relative path to this extension. It ends with "/"
124 public $extHttpPath;
125
126 public $backPath = '';
127
128 // TYPO3 site url
129 public $siteURL;
130
131 // TYPO3 host url
132 public $hostURL;
133
134 // Typo3 version
135 public $typoVersion;
136
137 // Identifies the RTE as being the one from the "rtehtmlarea" extension if any external code needs to know
138 /**
139 * @todo Define visibility
140 */
141 public $ID = 'rtehtmlarea';
142
143 // If set, the content goes into a regular TEXT area field - for developing testing of transformations.
144 /**
145 * @todo Define visibility
146 */
147 public $debugMode = FALSE;
148
149 // For the editor
150 /**
151 * @todo Define visibility
152 */
153 public $client;
154
155 /**
156 * Reference to parent object, which is an instance of the TCEforms
157 *
158 * @var \TYPO3\CMS\Backend\Form\FormEngine
159 * @todo Define visibility
160 */
161 public $TCEform;
162
163 /**
164 * @todo Define visibility
165 */
166 public $elementId;
167
168 /**
169 * @todo Define visibility
170 */
171 public $elementParts;
172
173 /**
174 * @todo Define visibility
175 */
176 public $tscPID;
177
178 /**
179 * @todo Define visibility
180 */
181 public $typeVal;
182
183 /**
184 * @todo Define visibility
185 */
186 public $thePid;
187
188 /**
189 * @todo Define visibility
190 */
191 public $RTEsetup;
192
193 /**
194 * @todo Define visibility
195 */
196 public $thisConfig;
197
198 /**
199 * @todo Define visibility
200 */
201 public $confValues;
202
203 public $language;
204
205 public $contentTypo3Language;
206
207 public $contentISOLanguage;
208
209 public $charset = 'utf-8';
210
211 public $contentCharset = 'utf-8';
212
213 public $OutputCharset = 'utf-8';
214
215 /**
216 * @todo Define visibility
217 */
218 public $editorCSS;
219
220 /**
221 * @todo Define visibility
222 */
223 public $specConf;
224
225 /**
226 * @todo Define visibility
227 */
228 public $toolbar = array();
229
230 // Save the buttons for the toolbar
231 /**
232 * @todo Define visibility
233 */
234 public $toolbarOrderArray = array();
235
236 protected $pluginEnabledArray = array();
237
238 // Array of plugin id's enabled in the current RTE editing area
239 protected $pluginEnabledCumulativeArray = array();
240
241 // Cumulative array of plugin id's enabled so far in any of the RTE editing areas of the form
242 public $registeredPlugins = array();
243
244 // Array of registered plugins indexed by their plugin Id's
245 protected $fullScreen = FALSE;
246
247 protected $pageRenderer;
248
249 /**
250 * Returns TRUE if the RTE is available. Here you check if the browser requirements are met.
251 * If there are reasons why the RTE cannot be displayed you simply enter them as text in ->errorLog
252 *
253 * @return boolean TRUE if this RTE object offers an RTE in the current browser environment
254 * @todo Define visibility
255 */
256 public function isAvailable() {
257 $this->client = $this->clientInfo();
258 $this->errorLog = array();
259 if (!$this->debugMode) {
260 // If debug-mode, let any browser through
261 $rteIsAvailable = FALSE;
262 $rteConfBrowser = $this->conf_supported_browser;
263 if (is_array($rteConfBrowser)) {
264 foreach ($rteConfBrowser as $browser => $browserConf) {
265 if ($browser == $this->client['browser']) {
266 // Config for Browser found, check it:
267 if (is_array($browserConf)) {
268 foreach ($browserConf as $browserConfSub) {
269 if ($browserConfSub['version'] <= $this->client['version'] || empty($browserConfSub['version'])) {
270 // Version is supported
271 if (is_array($browserConfSub['system'])) {
272 // Check against allowed systems
273 if (is_array($browserConfSub['system']['allowed'])) {
274 foreach ($browserConfSub['system']['allowed'] as $system) {
275 if (in_array($system, $this->client['all_systems'])) {
276 $rteIsAvailable = TRUE;
277 break;
278 }
279 }
280 } else {
281 // All allowed
282 $rteIsAvailable = TRUE;
283 }
284 // Check against disallowed systems
285 if (is_array($browserConfSub['system']['disallowed'])) {
286 foreach ($browserConfSub['system']['disallowed'] as $system) {
287 if (in_array($system, $this->client['all_systems'])) {
288 $rteIsAvailable = FALSE;
289 break;
290 }
291 }
292 }
293 } else {
294 // No system config: system is supported
295 $rteIsAvailable = TRUE;
296 break;
297 }
298 }
299 }
300 } else {
301 // no config for this browser found, so all versions or system with this browsers are allow
302 $rteIsAvailable = TRUE;
303 break;
304 }
305 }
306 }
307 } else {
308
309 }
310 if (!$rteIsAvailable) {
311 $this->errorLog[] = 'RTE: Browser not supported.';
312 }
313 if (\TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionNumberToInteger(TYPO3_version) < 4000000) {
314 $rteIsAvailable = FALSE;
315 $this->errorLog[] = 'rte: This version of htmlArea RTE cannot run under this version of TYPO3.';
316 }
317 }
318 return $rteIsAvailable;
319 }
320
321 /**
322 * Draws the RTE as an iframe
323 *
324 * @param object Reference to parent object, which is an instance of the TCEforms.
325 * @param string The table name
326 * @param string The field name
327 * @param array The current row from which field is being rendered
328 * @param array Array of standard content for rendering form fields from TCEforms. See TCEforms for details on this. Includes for instance the value and the form field name, java script actions and more.
329 * @param array "special" configuration - what is found at position 4 in the types configuration of a field from record, parsed into an array.
330 * @param array Configuration for RTEs; A mix between TSconfig and otherwise. Contains configuration for display, which buttons are enabled, additional transformation information etc.
331 * @param string Record "type" field value.
332 * @param string Relative path for images/links in RTE; this is used when the RTE edits content from static files where the path of such media has to be transformed forth and back!
333 * @param integer PID value of record (true parent page id)
334 * @return string HTML code for RTE!
335 * @todo Define visibility
336 */
337 public function drawRTE(&$parentObject, $table, $field, $row, $PA, $specConf, $thisConfig, $RTEtypeVal, $RTErelPath, $thePidValue) {
338 global $LANG, $TYPO3_DB, $TYPO3_CONF_VARS;
339 $this->TCEform = $parentObject;
340 $inline = $this->TCEform->inline;
341 $LANG->includeLLFile('EXT:' . $this->ID . '/locallang.xml');
342 $this->client = $this->clientInfo();
343 $this->typoVersion = \TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionNumberToInteger(TYPO3_version);
344 $this->userUid = 'BE_' . $GLOBALS['BE_USER']->user['uid'];
345 // Draw form element:
346 if ($this->debugMode) {
347 // Draws regular text area (debug mode)
348 $item = parent::drawRTE($this->TCEform, $table, $field, $row, $PA, $specConf, $thisConfig, $RTEtypeVal, $RTErelPath, $thePidValue);
349 } else {
350 // Draw real RTE
351 /* =======================================
352 * INIT THE EDITOR-SETTINGS
353 * =======================================
354 */
355 // Set backPath
356 $this->backPath = $this->TCEform->backPath;
357 // Get the path to this extension:
358 $this->extHttpPath = $this->backPath . \TYPO3\CMS\Core\Extension\ExtensionManager::extRelPath($this->ID);
359 // Get the site URL
360 $this->siteURL = \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_URL');
361 // Get the host URL
362 $this->hostURL = $this->siteURL . TYPO3_mainDir;
363 // Element ID + pid
364 $this->elementId = $PA['itemFormElName'];
365 // Form element name
366 $this->elementParts = explode('][', preg_replace('/\\]$/', '', preg_replace('/^(TSFE_EDIT\\[data\\]\\[|data\\[)/', '', $this->elementId)));
367 // Find the page PIDs:
368 list($this->tscPID, $this->thePid) = \TYPO3\CMS\Backend\Utility\BackendUtility::getTSCpid(trim($this->elementParts[0]), trim($this->elementParts[1]), $thePidValue);
369 // Record "types" field value:
370 $this->typeVal = $RTEtypeVal;
371 // TCA "types" value for record
372 // Find "thisConfig" for record/editor:
373 unset($this->RTEsetup);
374 $this->RTEsetup = $GLOBALS['BE_USER']->getTSConfig('RTE', \TYPO3\CMS\Backend\Utility\BackendUtility::getPagesTSconfig($this->tscPID));
375 $this->thisConfig = $thisConfig;
376 // Special configuration and default extras:
377 $this->specConf = $specConf;
378 if ($this->thisConfig['forceHTTPS']) {
379 $this->extHttpPath = preg_replace('/^(http|https)/', 'https', $this->extHttpPath);
380 $this->siteURL = preg_replace('/^(http|https)/', 'https', $this->siteURL);
381 $this->hostURL = preg_replace('/^(http|https)/', 'https', $this->hostURL);
382 }
383 // Register RTE windows
384 $this->TCEform->RTEwindows[] = $PA['itemFormElName'];
385 $textAreaId = preg_replace('/[^a-zA-Z0-9_:.-]/', '_', $PA['itemFormElName']);
386 $textAreaId = htmlspecialchars(preg_replace('/^[^a-zA-Z]/', 'x', $textAreaId));
387 /* =======================================
388 * LANGUAGES & CHARACTER SETS
389 * =======================================
390 */
391 // Languages: interface and content
392 $this->language = $LANG->lang;
393 if ($this->language == 'default' || !$this->language) {
394 $this->language = 'en';
395 }
396 $this->contentTypo3Language = $this->language == 'en' ? 'default' : $this->language;
397 $this->contentISOLanguage = 'en';
398 $this->contentLanguageUid = $row['sys_language_uid'] > 0 ? $row['sys_language_uid'] : 0;
399 if (\TYPO3\CMS\Core\Extension\ExtensionManager::isLoaded('static_info_tables')) {
400 if ($this->contentLanguageUid) {
401 $tableA = 'sys_language';
402 $tableB = 'static_languages';
403 $languagesUidsList = $this->contentLanguageUid;
404 $selectFields = $tableA . '.uid,' . $tableB . '.lg_iso_2,' . $tableB . '.lg_country_iso_2,' . $tableB . '.lg_typo3';
405 $tableAB = $tableA . ' LEFT JOIN ' . $tableB . ' ON ' . $tableA . '.static_lang_isocode=' . $tableB . '.uid';
406 $whereClause = $tableA . '.uid IN (' . $languagesUidsList . ') ';
407 $whereClause .= \TYPO3\CMS\Backend\Utility\BackendUtility::BEenableFields($tableA);
408 $whereClause .= \TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause($tableA);
409 $res = $TYPO3_DB->exec_SELECTquery($selectFields, $tableAB, $whereClause);
410 while ($languageRow = $TYPO3_DB->sql_fetch_assoc($res)) {
411 $this->contentISOLanguage = strtolower(trim($languageRow['lg_iso_2']) . (trim($languageRow['lg_country_iso_2']) ? '_' . trim($languageRow['lg_country_iso_2']) : ''));
412 $this->contentTypo3Language = trim($languageRow['lg_typo3']) ? strtolower(trim($languageRow['lg_typo3'])) : 'default';
413 }
414 } else {
415 $this->contentISOLanguage = trim($this->thisConfig['defaultContentLanguage']) ? trim($this->thisConfig['defaultContentLanguage']) : 'en';
416 $selectFields = 'lg_iso_2, lg_typo3';
417 $tableAB = 'static_languages';
418 $whereClause = 'lg_iso_2 = ' . $TYPO3_DB->fullQuoteStr(strtoupper($this->contentISOLanguage), $tableAB);
419 $res = $TYPO3_DB->exec_SELECTquery($selectFields, $tableAB, $whereClause);
420 while ($languageRow = $TYPO3_DB->sql_fetch_assoc($res)) {
421 $this->contentTypo3Language = trim($languageRow['lg_typo3']) ? strtolower(trim($languageRow['lg_typo3'])) : 'default';
422 }
423 }
424 }
425 /* =======================================
426 * TOOLBAR CONFIGURATION
427 * =======================================
428 */
429 $this->initializeToolbarConfiguration();
430 /* =======================================
431 * SET STYLES
432 * =======================================
433 */
434 // Check if wizard_rte called this for fullscreen edtition
435 if (basename(PATH_thisScript) == 'wizard_rte.php') {
436 $this->fullScreen = TRUE;
437 $RTEWidth = '100%';
438 $RTEHeight = '100%';
439 $RTEPaddingRight = '0';
440 $editorWrapWidth = '100%';
441 } else {
442 $RTEWidth = isset($GLOBALS['BE_USER']->userTS['options.']['RTESmallWidth']) ? $GLOBALS['BE_USER']->userTS['options.']['RTESmallWidth'] : '530';
443 $RTEHeight = isset($GLOBALS['BE_USER']->userTS['options.']['RTESmallHeight']) ? $GLOBALS['BE_USER']->userTS['options.']['RTESmallHeight'] : '380';
444 $RTEWidth = $RTEWidth + ($this->TCEform->docLarge ? (isset($GLOBALS['BE_USER']->userTS['options.']['RTELargeWidthIncrement']) ? $GLOBALS['BE_USER']->userTS['options.']['RTELargeWidthIncrement'] : '150') : 0);
445 $RTEWidth -= $inline->getStructureDepth() > 0 ? ($inline->getStructureDepth() + 1) * $inline->getLevelMargin() : 0;
446 $RTEWidthOverride = is_object($GLOBALS['BE_USER']) && isset($GLOBALS['BE_USER']->uc['rteWidth']) && trim($GLOBALS['BE_USER']->uc['rteWidth']) ? trim($GLOBALS['BE_USER']->uc['rteWidth']) : trim($this->thisConfig['RTEWidthOverride']);
447 if ($RTEWidthOverride) {
448 if (strstr($RTEWidthOverride, '%')) {
449 if ($this->client['browser'] != 'msie') {
450 $RTEWidth = intval($RTEWidthOverride) > 0 ? $RTEWidthOverride : '100%';
451 }
452 } else {
453 $RTEWidth = intval($RTEWidthOverride) > 0 ? intval($RTEWidthOverride) : $RTEWidth;
454 }
455 }
456 $RTEWidth = strstr($RTEWidth, '%') ? $RTEWidth : $RTEWidth . 'px';
457 $RTEHeight = $RTEHeight + ($this->TCEform->docLarge ? (isset($GLOBALS['BE_USER']->userTS['options.']['RTELargeHeightIncrement']) ? $GLOBALS['BE_USER']->userTS['options.']['RTELargeHeightIncrement'] : 0) : 0);
458 $RTEHeightOverride = is_object($GLOBALS['BE_USER']) && isset($GLOBALS['BE_USER']->uc['rteHeight']) && intval($GLOBALS['BE_USER']->uc['rteHeight']) ? intval($GLOBALS['BE_USER']->uc['rteHeight']) : intval($this->thisConfig['RTEHeightOverride']);
459 $RTEHeight = $RTEHeightOverride > 0 ? $RTEHeightOverride : $RTEHeight;
460 $RTEPaddingRight = '2px';
461 $editorWrapWidth = '99%';
462 }
463 $editorWrapHeight = '100%';
464 $this->RTEdivStyle = 'position:relative; left:0px; top:0px; height:' . $RTEHeight . 'px; width:' . $RTEWidth . '; border: 1px solid black; padding: 2px ' . $RTEPaddingRight . ' 2px 2px;';
465 /* =======================================
466 * LOAD CSS AND JAVASCRIPT
467 * =======================================
468 */
469 $this->pageRenderer = $GLOBALS['SOBE']->doc->getPageRenderer();
470 // Preloading the pageStyle and including RTE skin stylesheets
471 $this->addPageStyle();
472 $this->addSkin();
473 // Register RTE in JS
474 $this->TCEform->additionalJS_post[] = $this->registerRTEinJS($this->TCEform->RTEcounter, $table, $row['uid'], $field, $textAreaId);
475 // Set the save option for the RTE
476 $this->TCEform->additionalJS_submit[] = $this->setSaveRTE($this->TCEform->RTEcounter, $this->TCEform->formName, $textAreaId, $PA['itemFormElName']);
477 $this->TCEform->additionalJS_delete[] = $this->setDeleteRTE($this->TCEform->RTEcounter, $this->TCEform->formName, $textAreaId);
478 // Loading ExtJs inline code
479 $this->pageRenderer->enableExtJSQuickTips();
480 // Add TYPO3 notifications JavaScript
481 $this->pageRenderer->addJsFile('../t3lib/js/extjs/notifications.js');
482 // Add RTE JavaScript
483 $this->addRteJsFiles($this->TCEform->RTEcounter);
484 $this->pageRenderer->addJsFile($this->buildJSMainLangFile($this->TCEform->RTEcounter));
485 $this->pageRenderer->addJsInlineCode('HTMLArea-init', $this->getRteInitJsCode(), TRUE);
486 /* =======================================
487 * DRAW THE EDITOR
488 * =======================================
489 */
490 // Transform value:
491 $value = $this->transformContent('rte', $PA['itemFormElValue'], $table, $field, $row, $specConf, $thisConfig, $RTErelPath, $thePidValue);
492 // Further content transformation by registered plugins
493 foreach ($this->registeredPlugins as $pluginId => $plugin) {
494 if ($this->isPluginEnabled($pluginId) && method_exists($plugin, 'transformContent')) {
495 $value = $plugin->transformContent($value);
496 }
497 }
498 // Draw the textarea
499 $visibility = 'hidden';
500 $item = $this->triggerField($PA['itemFormElName']) . '
501 <div id="pleasewait' . $textAreaId . '" class="pleasewait" style="display: block;" >' . $LANG->getLL('Please wait') . '</div>
502 <div id="editorWrap' . $textAreaId . '" class="editorWrap" style="visibility: hidden; width:' . $editorWrapWidth . '; height:' . $editorWrapHeight . ';">
503 <textarea id="RTEarea' . $textAreaId . '" name="' . htmlspecialchars($PA['itemFormElName']) . '" rows="0" cols="0" style="' . \TYPO3\CMS\Core\Utility\GeneralUtility::deHSCentities(htmlspecialchars($this->RTEdivStyle)) . '">' . \TYPO3\CMS\Core\Utility\GeneralUtility::formatForTextarea($value) . '</textarea>
504 </div>' . LF;
505 }
506 // Return form item:
507 return $item;
508 }
509
510 /**
511 * Add link to content style sheet to document header
512 *
513 * @return void
514 */
515 protected function addPageStyle() {
516 $this->addStyleSheet('rtehtmlarea-page-style', $this->getContentCssFileName(), 'htmlArea RTE Content CSS', 'alternate stylesheet');
517 }
518
519 /**
520 * Get the name of the contentCSS file to use
521 *
522 * @return the full file name of the content css file to use
523 */
524 protected function getContentCssFileName() {
525 // Get stylesheet file name from Page TSConfig if any
526 $fileName = trim($this->thisConfig['contentCSS']);
527 if ($fileName) {
528 $fileName = $this->getFullFileName($fileName);
529 }
530 $absolutePath = $fileName ? \TYPO3\CMS\Core\Utility\GeneralUtility::resolveBackPath(PATH_site . ($this->is_FE() || $this->isFrontendEditActive() ? '' : TYPO3_mainDir) . $fileName) : '';
531 // Fallback to default content css file if configured file does not exists or is of zero size
532 if (!$fileName || !file_exists($absolutePath) || !filesize($absolutePath)) {
533 $fileName = $this->getFullFileName('EXT:' . $this->ID . '/res/contentcss/default.css');
534 }
535 return $fileName;
536 }
537
538 /**
539 * Add links to skin style sheet(s) to document header
540 *
541 * @return void
542 */
543 protected function addSkin() {
544 // Get skin file name from Page TSConfig if any
545 $skinFilename = trim($this->thisConfig['skin']) ? trim($this->thisConfig['skin']) : 'EXT:' . $this->ID . '/htmlarea/skins/default/htmlarea.css';
546 $this->editorCSS = $this->getFullFileName($skinFilename);
547 $skinDir = dirname($this->editorCSS);
548 // Editing area style sheet
549 $this->editedContentCSS = $skinDir . '/htmlarea-edited-content.css';
550 $this->addStyleSheet('rtehtmlarea-editing-area-skin', $this->editedContentCSS);
551 // Main skin
552 $this->addStyleSheet('rtehtmlarea-skin', $this->editorCSS);
553 // Additional icons from registered plugins
554 foreach ($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] as $pluginId) {
555 if (is_object($this->registeredPlugins[$pluginId])) {
556 $pathToSkin = $this->registeredPlugins[$pluginId]->getPathToSkin();
557 if ($pathToSkin) {
558 $key = $this->registeredPlugins[$pluginId]->getExtensionKey();
559 $this->addStyleSheet('rtehtmlarea-plugin-' . $pluginId . '-skin', ($this->is_FE() ? \TYPO3\CMS\Core\Extension\ExtensionManager::siteRelPath($key) : $this->backPath . \TYPO3\CMS\Core\Extension\ExtensionManager::extRelPath($key)) . $pathToSkin);
560 }
561 }
562 }
563 }
564
565 /**
566 * Add style sheet file to document header
567 *
568 * @param string $key: some key identifying the style sheet
569 * @param string $href: uri to the style sheet file
570 * @param string $title: value for the title attribute of the link element
571 * @return string $relation: value for the rel attribute of the link element
572 * @return void
573 */
574 protected function addStyleSheet($key, $href, $title = '', $relation = 'stylesheet') {
575 // If it was not known that an RTE-enabled would be created when the page was first created, the css would not be added to head
576 if (is_object($this->TCEform->inline) && $this->TCEform->inline->isAjaxCall) {
577 $this->TCEform->additionalCode_pre[$key] = '<link rel="' . $relation . '" type="text/css" href="' . $href . '" title="' . $title . '" />';
578 } else {
579 $this->pageRenderer->addCssFile($href, $relation, 'screen', $title);
580 }
581 }
582
583 /**
584 * Initialize toolbar configuration and enable registered plugins
585 *
586 * @return void
587 */
588 protected function initializeToolbarConfiguration() {
589 // Enable registred plugins
590 $this->enableRegisteredPlugins();
591 // Configure toolbar
592 $this->setToolbar();
593 // Check if some plugins need to be disabled
594 $this->setPlugins();
595 // Merge the list of enabled plugins with the lists from the previous RTE editing areas on the same form
596 $this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] = $this->pluginEnabledArray;
597 if ($this->TCEform->RTEcounter > 1 && isset($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter - 1]) && is_array($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter - 1])) {
598 $this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] = array_unique(array_values(array_merge($this->pluginEnabledArray, $this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter - 1])));
599 }
600 }
601
602 /**
603 * Add registered plugins to the array of enabled plugins
604 *
605 * @todo Define visibility
606 */
607 public function enableRegisteredPlugins() {
608 global $TYPO3_CONF_VARS;
609 // Traverse registered plugins
610 if (is_array($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['plugins'])) {
611 foreach ($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['plugins'] as $pluginId => $pluginObjectConfiguration) {
612 $plugin = FALSE;
613 if (is_array($pluginObjectConfiguration) && count($pluginObjectConfiguration)) {
614 $plugin = \TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj($pluginObjectConfiguration['objectReference']);
615 }
616 if (is_object($plugin)) {
617 if ($plugin->main($this)) {
618 $this->registeredPlugins[$pluginId] = $plugin;
619 // Override buttons from previously registered plugins
620 $pluginButtons = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $plugin->getPluginButtons(), 1);
621 foreach ($this->pluginButton as $previousPluginId => $buttonList) {
622 $this->pluginButton[$previousPluginId] = implode(',', array_diff(\TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $this->pluginButton[$previousPluginId], 1), $pluginButtons));
623 }
624 $this->pluginButton[$pluginId] = $plugin->getPluginButtons();
625 $pluginLabels = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $plugin->getPluginLabels(), 1);
626 foreach ($this->pluginLabel as $previousPluginId => $labelList) {
627 $this->pluginLabel[$previousPluginId] = implode(',', array_diff(\TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $this->pluginLabel[$previousPluginId], 1), $pluginLabels));
628 }
629 $this->pluginLabel[$pluginId] = $plugin->getPluginLabels();
630 $this->pluginEnabledArray[] = $pluginId;
631 }
632 }
633 }
634 }
635 // Process overrides
636 $hidePlugins = array();
637 foreach ($this->registeredPlugins as $pluginId => $plugin) {
638 if ($plugin->addsButtons() && !$this->pluginButton[$pluginId]) {
639 $hidePlugins[] = $pluginId;
640 }
641 }
642 $this->pluginEnabledArray = array_unique(array_diff($this->pluginEnabledArray, $hidePlugins));
643 }
644
645 /**
646 * Set the toolbar config (only in this PHP-Object, not in JS):
647 *
648 * @todo Define visibility
649 */
650 public function setToolbar() {
651 if ($this->client['browser'] == 'msie' || $this->client['browser'] == 'opera') {
652 $this->thisConfig['keepButtonGroupTogether'] = 0;
653 }
654 $this->defaultToolbarOrder = 'bar, blockstylelabel, blockstyle, space, textstylelabel, textstyle, linebreak,
655 bar, formattext, bold, strong, italic, emphasis, big, small, insertedtext, deletedtext, citation, code, definition, keyboard, monospaced, quotation, sample, variable, bidioverride, strikethrough, subscript, superscript, underline, span,
656 bar, fontstyle, space, fontsize, bar, formatblock, insertparagraphbefore, insertparagraphafter, blockquote, line,
657 bar, left, center, right, justifyfull,
658 bar, orderedlist, unorderedlist, definitionlist, definitionitem, outdent, indent, bar, lefttoright, righttoleft, language, showlanguagemarks,
659 bar, textcolor, bgcolor, textindicator,
660 bar, editelement, showmicrodata, emoticon, insertcharacter, insertsofthyphen, link, unlink, image, table,' . ($this->thisConfig['hideTableOperationsInToolbar'] && is_array($this->thisConfig['buttons.']) && is_array($this->thisConfig['buttons.']['toggleborders.']) && $this->thisConfig['buttons.']['toggleborders.']['keepInToolbar'] ? ' toggleborders,' : '') . ' user, acronym, bar, findreplace, spellcheck,
661 bar, chMode, inserttag, removeformat, bar, copy, cut, paste, pastetoggle, pastebehaviour, bar, undo, redo, bar, showhelp, about, linebreak,
662 ' . ($this->thisConfig['hideTableOperationsInToolbar'] ? '' : 'bar, toggleborders,') . ' bar, tableproperties, tablerestyle, bar, rowproperties, rowinsertabove, rowinsertunder, rowdelete, rowsplit, bar,
663 columnproperties, columninsertbefore, columninsertafter, columndelete, columnsplit, bar,
664 cellproperties, cellinsertbefore, cellinsertafter, celldelete, cellsplit, cellmerge';
665 // Additional buttons from registered plugins
666 foreach ($this->registeredPlugins as $pluginId => $plugin) {
667 if ($this->isPluginEnabled($pluginId)) {
668 $this->defaultToolbarOrder = $plugin->addButtonsToToolbar();
669 }
670 }
671 $toolbarOrder = $this->thisConfig['toolbarOrder'] ? $this->thisConfig['toolbarOrder'] : $this->defaultToolbarOrder;
672 // Getting rid of undefined buttons
673 $this->toolbarOrderArray = array_intersect(\TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $toolbarOrder, 1), \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $this->defaultToolbarOrder, 1));
674 $toolbarOrder = array_unique(array_values($this->toolbarOrderArray));
675 // Fetching specConf for field from backend
676 $pList = is_array($this->specConf['richtext']['parameters']) ? implode(',', $this->specConf['richtext']['parameters']) : '';
677 if ($pList != '*') {
678 // If not all
679 $show = is_array($this->specConf['richtext']['parameters']) ? $this->specConf['richtext']['parameters'] : array();
680 if ($this->thisConfig['showButtons']) {
681 if (!\TYPO3\CMS\Core\Utility\GeneralUtility::inList($this->thisConfig['showButtons'], '*')) {
682 $show = array_unique(array_merge($show, \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $this->thisConfig['showButtons'], 1)));
683 } else {
684 $show = array_unique(array_merge($show, $toolbarOrder));
685 }
686 }
687 if (is_array($this->thisConfig['showButtons.'])) {
688 foreach ($this->thisConfig['showButtons.'] as $buttonId => $value) {
689 if ($value) {
690 $show[] = $buttonId;
691 }
692 }
693 $show = array_unique($show);
694 }
695 } else {
696 $show = $toolbarOrder;
697 }
698 // Resticting to RTEkeyList for backend user
699 if (is_object($GLOBALS['BE_USER'])) {
700 $RTEkeyList = isset($GLOBALS['BE_USER']->userTS['options.']['RTEkeyList']) ? $GLOBALS['BE_USER']->userTS['options.']['RTEkeyList'] : '*';
701 if ($RTEkeyList != '*') {
702 // If not all
703 $show = array_intersect($show, \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $RTEkeyList, 1));
704 }
705 }
706 // Hiding buttons of disabled plugins
707 $hideButtons = array('space', 'bar', 'linebreak');
708 foreach ($this->pluginButton as $pluginId => $buttonList) {
709 if (!$this->isPluginEnabled($pluginId)) {
710 $buttonArray = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $buttonList, 1);
711 foreach ($buttonArray as $button) {
712 $hideButtons[] = $button;
713 }
714 }
715 }
716 // Hiding labels of disabled plugins
717 foreach ($this->pluginLabel as $pluginId => $label) {
718 if (!$this->isPluginEnabled($pluginId)) {
719 $hideButtons[] = $label;
720 }
721 }
722 // Hiding buttons
723 $show = array_diff($show, $this->conf_toolbar_hide, \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $this->thisConfig['hideButtons'], 1));
724 // Apply toolbar constraints from registered plugins
725 foreach ($this->registeredPlugins as $pluginId => $plugin) {
726 if ($this->isPluginEnabled($pluginId) && method_exists($plugin, 'applyToolbarConstraints')) {
727 $show = $plugin->applyToolbarConstraints($show);
728 }
729 }
730 // Getting rid of the buttons for which we have no position
731 $show = array_intersect($show, $toolbarOrder);
732 $this->toolbar = $show;
733 }
734
735 /**
736 * Disable some plugins
737 *
738 * @todo Define visibility
739 */
740 public function setPlugins() {
741 // Disabling a plugin that adds buttons if none of its buttons is in the toolbar
742 $hidePlugins = array();
743 foreach ($this->pluginButton as $pluginId => $buttonList) {
744 if ($this->registeredPlugins[$pluginId]->addsButtons()) {
745 $showPlugin = FALSE;
746 $buttonArray = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $buttonList, 1);
747 foreach ($buttonArray as $button) {
748 if (in_array($button, $this->toolbar)) {
749 $showPlugin = TRUE;
750 }
751 }
752 if (!$showPlugin) {
753 $hidePlugins[] = $pluginId;
754 }
755 }
756 }
757 $this->pluginEnabledArray = array_diff($this->pluginEnabledArray, $hidePlugins);
758 // Hiding labels of disabled plugins
759 $hideLabels = array();
760 foreach ($this->pluginLabel as $pluginId => $label) {
761 if (!$this->isPluginEnabled($pluginId)) {
762 $hideLabels[] = $label;
763 }
764 }
765 $this->toolbar = array_diff($this->toolbar, $hideLabels);
766 // Adding plugins declared as prerequisites by enabled plugins
767 $requiredPlugins = array();
768 foreach ($this->registeredPlugins as $pluginId => $plugin) {
769 if ($this->isPluginEnabled($pluginId)) {
770 $requiredPlugins = array_merge($requiredPlugins, \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $plugin->getRequiredPlugins(), 1));
771 }
772 }
773 $requiredPlugins = array_unique($requiredPlugins);
774 foreach ($requiredPlugins as $pluginId) {
775 if (is_object($this->registeredPlugins[$pluginId]) && !$this->isPluginEnabled($pluginId)) {
776 $this->pluginEnabledArray[] = $pluginId;
777 }
778 }
779 $this->pluginEnabledArray = array_unique($this->pluginEnabledArray);
780 // Completing the toolbar conversion array for htmlArea
781 foreach ($this->registeredPlugins as $pluginId => $plugin) {
782 if ($this->isPluginEnabled($pluginId)) {
783 $this->convertToolbarForHtmlAreaArray = array_unique(array_merge($this->convertToolbarForHtmlAreaArray, $plugin->getConvertToolbarForHtmlAreaArray()));
784 }
785 }
786 }
787
788 /**
789 * Convert the TYPO3 names of buttons into the names for htmlArea RTE
790 *
791 * @param string buttonname (typo3-name)
792 * @return string buttonname (htmlarea-name)
793 * @todo Define visibility
794 */
795 public function convertToolbarForHTMLArea($button) {
796 return $this->convertToolbarForHtmlAreaArray[$button];
797 }
798
799 /**
800 * Add RTE main scripts and plugin scripts
801 *
802 * @param string $RTEcounter: The index number of the current RTE editing area within the form.
803 * @return void
804 */
805 protected function addRteJsFiles($RTEcounter) {
806 $this->pageRenderer->addJsFile($this->getFullFileName('EXT:' . $this->ID . '/htmlarea/htmlarea.js'));
807 foreach ($this->pluginEnabledCumulativeArray[$RTEcounter] as $pluginId) {
808 $extensionKey = is_object($this->registeredPlugins[$pluginId]) ? $this->registeredPlugins[$pluginId]->getExtensionKey() : $this->ID;
809 $this->pageRenderer->addJsFile($this->getFullFileName('EXT:' . $extensionKey . '/htmlarea/plugins/' . $pluginId . '/' . strtolower(preg_replace('/([a-z])([A-Z])([a-z])/', '$1-$2$3', $pluginId)) . '.js'));
810 }
811 }
812
813 /**
814 * Return RTE initialization inline JavaScript code
815 *
816 * @return string RTE initialization inline JavaScript code
817 */
818 protected function getRteInitJsCode() {
819 return '
820 if (typeof(RTEarea) == "undefined") {
821 RTEarea = new Object();
822 RTEarea[0] = new Object();
823 RTEarea[0].version = "' . $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->ID]['version'] . '";
824 RTEarea[0].editorUrl = "' . $this->extHttpPath . 'htmlarea/";
825 RTEarea[0].editorCSS = "' . \TYPO3\CMS\Core\Utility\GeneralUtility::createVersionNumberedFilename($this->editorCSS) . '";
826 RTEarea[0].editorSkin = "' . dirname($this->editorCSS) . '/";
827 RTEarea[0].editedContentCSS = "' . \TYPO3\CMS\Core\Utility\GeneralUtility::createVersionNumberedFilename($this->editedContentCSS) . '";
828 RTEarea[0].hostUrl = "' . $this->hostURL . '";
829 RTEarea.init = function() {
830 if (typeof(HTMLArea) == "undefined" || !Ext.isReady) {
831 window.setTimeout("RTEarea.init();", 10);
832 } else {
833 Ext.QuickTips.init();
834 HTMLArea.init();
835 }
836 };
837 RTEarea.initEditor = function(editorNumber) {
838 if (typeof(HTMLArea) == "undefined" || !HTMLArea.isReady) {
839 RTEarea.initEditor.defer(40, null, [editorNumber]);
840 } else {
841 HTMLArea.initEditor(editorNumber);
842 }
843 };
844 }
845 RTEarea.init();';
846 }
847
848 /**
849 * Return the Javascript code for configuring the RTE
850 *
851 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
852 * @param string $table: The table that includes this RTE (optional, necessary for IRRE).
853 * @param string $uid: The uid of that table that includes this RTE (optional, necessary for IRRE).
854 * @param string $field: The field of that record that includes this RTE (optional).
855 * @return string the Javascript code for configuring the RTE
856 * @todo Define visibility
857 */
858 public function registerRTEinJS($RTEcounter, $table = '', $uid = '', $field = '', $textAreaId = '') {
859 $configureRTEInJavascriptString = '
860 if (typeof(configureEditorInstance) == "undefined") {
861 configureEditorInstance = new Object();
862 }
863 configureEditorInstance["' . $textAreaId . '"] = function() {
864 if (typeof(RTEarea) == "undefined" || typeof(HTMLArea) == "undefined") {
865 window.setTimeout("configureEditorInstance[\'' . $textAreaId . '\']();", 40);
866 } else {
867 editornumber = "' . $textAreaId . '";
868 RTEarea[editornumber] = new Object();
869 RTEarea[editornumber].RTEtsConfigParams = "&RTEtsConfigParams=' . rawurlencode($this->RTEtsConfigParams()) . '";
870 RTEarea[editornumber].number = editornumber;
871 RTEarea[editornumber].deleted = false;
872 RTEarea[editornumber].textAreaId = "' . $textAreaId . '";
873 RTEarea[editornumber].id = "RTEarea" + editornumber;
874 RTEarea[editornumber].RTEWidthOverride = "' . (is_object($GLOBALS['BE_USER']) && isset($GLOBALS['BE_USER']->uc['rteWidth']) && trim($GLOBALS['BE_USER']->uc['rteWidth']) ? trim($GLOBALS['BE_USER']->uc['rteWidth']) : trim($this->thisConfig['RTEWidthOverride'])) . '";
875 RTEarea[editornumber].RTEHeightOverride = "' . (is_object($GLOBALS['BE_USER']) && isset($GLOBALS['BE_USER']->uc['rteHeight']) && intval($GLOBALS['BE_USER']->uc['rteHeight']) ? intval($GLOBALS['BE_USER']->uc['rteHeight']) : intval($this->thisConfig['RTEHeightOverride'])) . '";
876 RTEarea[editornumber].resizable = ' . (is_object($GLOBALS['BE_USER']) && isset($GLOBALS['BE_USER']->uc['rteResize']) && $GLOBALS['BE_USER']->uc['rteResize'] ? 'true' : (trim($this->thisConfig['rteResize']) ? 'true' : 'false')) . ';
877 RTEarea[editornumber].maxHeight = "' . (is_object($GLOBALS['BE_USER']) && isset($GLOBALS['BE_USER']->uc['rteMaxHeight']) && intval($GLOBALS['BE_USER']->uc['rteMaxHeight']) ? trim($GLOBALS['BE_USER']->uc['rteMaxHeight']) : (intval($this->thisConfig['rteMaxHeight']) ? intval($this->thisConfig['rteMaxHeight']) : '2000')) . '";
878 RTEarea[editornumber].fullScreen = ' . ($this->fullScreen ? 'true' : 'false') . ';
879 RTEarea[editornumber].showStatusBar = ' . (trim($this->thisConfig['showStatusBar']) ? 'true' : 'false') . ';
880 RTEarea[editornumber].enableWordClean = ' . (trim($this->thisConfig['enableWordClean']) ? 'true' : 'false') . ';
881 RTEarea[editornumber].htmlRemoveComments = ' . (trim($this->thisConfig['removeComments']) ? 'true' : 'false') . ';
882 RTEarea[editornumber].disableEnterParagraphs = ' . (trim($this->thisConfig['disableEnterParagraphs']) ? 'true' : 'false') . ';
883 RTEarea[editornumber].disableObjectResizing = ' . (trim($this->thisConfig['disableObjectResizing']) ? 'true' : 'false') . ';
884 RTEarea[editornumber].removeTrailingBR = ' . (trim($this->thisConfig['removeTrailingBR']) ? 'true' : 'false') . ';
885 RTEarea[editornumber].useCSS = ' . (trim($this->thisConfig['useCSS']) ? 'true' : 'false') . ';
886 RTEarea[editornumber].keepButtonGroupTogether = ' . (trim($this->thisConfig['keepButtonGroupTogether']) ? 'true' : 'false') . ';
887 RTEarea[editornumber].disablePCexamples = ' . (trim($this->thisConfig['disablePCexamples']) ? 'true' : 'false') . ';
888 RTEarea[editornumber].showTagFreeClasses = ' . (trim($this->thisConfig['showTagFreeClasses']) ? 'true' : 'false') . ';
889 RTEarea[editornumber].useHTTPS = ' . (trim(stristr($this->siteURL, 'https')) || $this->thisConfig['forceHTTPS'] ? 'true' : 'false') . ';
890 RTEarea[editornumber].tceformsNested = ' . (is_object($this->TCEform) && method_exists($this->TCEform, 'getDynNestedStack') ? $this->TCEform->getDynNestedStack(TRUE) : '[]') . ';
891 RTEarea[editornumber].dialogueWindows = new Object();';
892 if (isset($this->thisConfig['dialogueWindows.']['defaultPositionFromTop'])) {
893 $configureRTEInJavascriptString .= '
894 RTEarea[editornumber].dialogueWindows.positionFromTop = ' . intval($this->thisConfig['dialogueWindows.']['defaultPositionFromTop']) . ';';
895 }
896 if (isset($this->thisConfig['dialogueWindows.']['defaultPositionFromLeft'])) {
897 $configureRTEInJavascriptString .= '
898 RTEarea[editornumber].dialogueWindows.positionFromLeft = ' . intval($this->thisConfig['dialogueWindows.']['defaultPositionFromLeft']) . ';';
899 }
900 // The following properties apply only to the backend
901 if (!$this->is_FE()) {
902 $configureRTEInJavascriptString .= '
903 RTEarea[editornumber].sys_language_content = "' . $this->contentLanguageUid . '";
904 RTEarea[editornumber].typo3ContentLanguage = "' . $this->contentTypo3Language . '";
905 RTEarea[editornumber].typo3ContentCharset = "' . $this->contentCharset . '";
906 RTEarea[editornumber].userUid = "' . $this->userUid . '";';
907 }
908 // Setting the plugin flags
909 $configureRTEInJavascriptString .= '
910 RTEarea[editornumber].plugin = new Object();
911 RTEarea[editornumber].pathToPluginDirectory = new Object();';
912 foreach ($this->pluginEnabledArray as $pluginId) {
913 $configureRTEInJavascriptString .= '
914 RTEarea[editornumber].plugin.' . $pluginId . ' = true;';
915 if (is_object($this->registeredPlugins[$pluginId])) {
916 $pathToPluginDirectory = $this->registeredPlugins[$pluginId]->getPathToPluginDirectory();
917 if ($pathToPluginDirectory) {
918 $configureRTEInJavascriptString .= '
919 RTEarea[editornumber].pathToPluginDirectory.' . $pluginId . ' = "' . $pathToPluginDirectory . '";';
920 }
921 }
922 }
923 // Setting the buttons configuration
924 $configureRTEInJavascriptString .= '
925 RTEarea[editornumber].buttons = new Object();';
926 if (is_array($this->thisConfig['buttons.'])) {
927 foreach ($this->thisConfig['buttons.'] as $buttonIndex => $conf) {
928 $button = substr($buttonIndex, 0, -1);
929 if (is_array($conf)) {
930 $configureRTEInJavascriptString .= '
931 RTEarea[editornumber].buttons.' . $button . ' = ' . $this->buildNestedJSArray($conf) . ';';
932 }
933 }
934 }
935 // Setting the list of tags to be removed if specified in the RTE config
936 if (trim($this->thisConfig['removeTags'])) {
937 $configureRTEInJavascriptString .= '
938 RTEarea[editornumber].htmlRemoveTags = /^(' . implode('|', \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $this->thisConfig['removeTags'], 1)) . ')$/i;';
939 }
940 // Setting the list of tags to be removed with their contents if specified in the RTE config
941 if (trim($this->thisConfig['removeTagsAndContents'])) {
942 $configureRTEInJavascriptString .= '
943 RTEarea[editornumber].htmlRemoveTagsAndContents = /^(' . implode('|', \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $this->thisConfig['removeTagsAndContents'], 1)) . ')$/i;';
944 }
945 // Setting array of custom tags if specified in the RTE config
946 if (!empty($this->thisConfig['customTags'])) {
947 $customTags = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $this->thisConfig['customTags'], 1);
948 if (!empty($customTags)) {
949 $configureRTEInJavascriptString .= '
950 RTEarea[editornumber].customTags= ' . json_encode($customTags) . ';';
951 }
952 }
953 // Setting the pageStyle
954 $configureRTEInJavascriptString .= '
955 RTEarea[editornumber].pageStyle = "' . \TYPO3\CMS\Core\Utility\GeneralUtility::createVersionNumberedFilename($this->getContentCssFileName()) . '";';
956 // Process classes configuration
957 $classesConfigurationRequired = FALSE;
958 foreach ($this->registeredPlugins as $pluginId => $plugin) {
959 if ($this->isPluginEnabled($pluginId)) {
960 $classesConfigurationRequired = $classesConfigurationRequired || $plugin->requiresClassesConfiguration();
961 }
962 }
963 if ($classesConfigurationRequired) {
964 $configureRTEInJavascriptString .= $this->buildJSClassesConfig($RTEcounter);
965 }
966 // Add Javascript configuration for registered plugins
967 foreach ($this->registeredPlugins as $pluginId => $plugin) {
968 if ($this->isPluginEnabled($pluginId)) {
969 $configureRTEInJavascriptString .= $plugin->buildJavascriptConfiguration('editornumber');
970 }
971 }
972 // Avoid premature reference to HTMLArea when being initially loaded by IRRE Ajax call
973 $configureRTEInJavascriptString .= '
974 RTEarea[editornumber].toolbar = ' . $this->getJSToolbarArray() . ';
975 RTEarea[editornumber].convertButtonId = ' . json_encode(array_flip($this->convertToolbarForHtmlAreaArray)) . ';
976 RTEarea.initEditor(editornumber);
977 }
978 };
979 configureEditorInstance["' . $textAreaId . '"]();';
980 return $configureRTEInJavascriptString;
981 }
982
983 /**
984 * Return TRUE, if the plugin can be loaded
985 *
986 * @param string $pluginId: The identification string of the plugin
987 * @return boolean TRUE if the plugin can be loaded
988 * @todo Define visibility
989 */
990 public function isPluginEnabled($pluginId) {
991 return in_array($pluginId, $this->pluginEnabledArray);
992 }
993
994 /**
995 * Build the default content style sheet
996 *
997 * @return string Style sheet
998 * @deprecated since TYPO3 6.0, will be removed in TYPO3 6.2
999 * @todo Define visibility
1000 */
1001 public function buildStyleSheet() {
1002 $stylesheet = '/* mainStyleOverride and inlineStyle properties ignored. */';
1003 return $stylesheet;
1004 }
1005
1006 /**
1007 * Return Javascript configuration of classes
1008 *
1009 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
1010 * @return string Javascript configuration of classes
1011 * @todo Define visibility
1012 */
1013 public function buildJSClassesConfig($RTEcounter) {
1014 // Include JS arrays of configured classes
1015 $configureRTEInJavascriptString .= '
1016 RTEarea[editornumber].classesUrl = "' . ($this->is_FE() && $GLOBALS['TSFE']->absRefPrefix ? $GLOBALS['TSFE']->absRefPrefix : '') . $this->writeTemporaryFile('', ('classes_' . $this->language), 'js', $this->buildJSClassesArray(), TRUE) . '";';
1017 return $configureRTEInJavascriptString;
1018 }
1019
1020 /**
1021 * Return JS arrays of classes configuration
1022 *
1023 * @return string JS classes arrays
1024 * @todo Define visibility
1025 */
1026 public function buildJSClassesArray() {
1027 if ($this->is_FE()) {
1028 $RTEProperties = $this->RTEsetup;
1029 } else {
1030 $RTEProperties = $this->RTEsetup['properties'];
1031 }
1032 $classesArray = array('labels' => array(), 'values' => array(), 'noShow' => array(), 'alternating' => array(), 'counting' => array(), 'XOR' => array());
1033 $JSClassesArray = '';
1034 // Scanning the list of classes if specified in the RTE config
1035 if (is_array($RTEProperties['classes.'])) {
1036 foreach ($RTEProperties['classes.'] as $className => $conf) {
1037 $className = rtrim($className, '.');
1038 $classesArray['labels'][$className] = $this->getPageConfigLabel($conf['name'], FALSE);
1039 $classesArray['values'][$className] = str_replace('\\\'', '\'', $conf['value']);
1040 if (isset($conf['noShow'])) {
1041 $classesArray['noShow'][$className] = $conf['noShow'];
1042 }
1043 if (is_array($conf['alternating.'])) {
1044 $classesArray['alternating'][$className] = $conf['alternating.'];
1045 }
1046 if (is_array($conf['counting.'])) {
1047 $classesArray['counting'][$className] = $conf['counting.'];
1048 }
1049 }
1050 }
1051 // Scanning the list of sets of mutually exclusives classes if specified in the RTE config
1052 if (is_array($RTEProperties['mutuallyExclusiveClasses.'])) {
1053 foreach ($RTEProperties['mutuallyExclusiveClasses.'] as $listName => $conf) {
1054 $classSet = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $conf, 1);
1055 $classList = implode(',', $classSet);
1056 foreach ($classSet as $className) {
1057 $classesArray['XOR'][$className] = '/^(' . implode('|', \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', \TYPO3\CMS\Core\Utility\GeneralUtility::rmFromList($className, $classList), 1)) . ')$/';
1058 }
1059 }
1060 }
1061 foreach ($classesArray as $key => $subArray) {
1062 $JSClassesArray .= 'HTMLArea.classes' . ucfirst($key) . ' = ' . $this->buildNestedJSArray($subArray) . ';' . LF;
1063 }
1064 return $JSClassesArray;
1065 }
1066
1067 /**
1068 * Translate Page TS Config array in JS nested array definition
1069 * Replace 0 values with false
1070 * Unquote regular expression values
1071 * Replace empty arrays with empty objects
1072 *
1073 * @param array $conf: Page TSConfig configuration array
1074 * @return string nested JS array definition
1075 * @todo Define visibility
1076 */
1077 public function buildNestedJSArray($conf) {
1078 $convertedConf = \TYPO3\CMS\Core\Utility\GeneralUtility::removeDotsFromTS($conf);
1079 return str_replace(array(':"0"', ':"\\/^(', ')$\\/i"', ':"\\/^(', ')$\\/"', '[]'), array(':false', ':/^(', ')$/i', ':/^(', ')$/', '{}'), json_encode($convertedConf));
1080 }
1081
1082 /**
1083 * Return a Javascript localization array for htmlArea RTE
1084 *
1085 * @return string Javascript localization array
1086 * @todo Define visibility
1087 */
1088 public function buildJSMainLangArray() {
1089 $JSLanguageArray = 'HTMLArea.I18N = new Object();' . LF;
1090 $labelsArray = array('tooltips' => array(), 'msg' => array(), 'dialogs' => array());
1091 foreach ($labelsArray as $labels => $subArray) {
1092 $LOCAL_LANG = \TYPO3\CMS\Core\Utility\GeneralUtility::readLLfile('EXT:' . $this->ID . '/htmlarea/locallang_' . $labels . '.xml', $this->language, 'utf-8');
1093 if (!empty($LOCAL_LANG[$this->language])) {
1094 $LOCAL_LANG[$this->language] = \TYPO3\CMS\Core\Utility\GeneralUtility::array_merge_recursive_overrule($LOCAL_LANG['default'], $LOCAL_LANG[$this->language], FALSE, FALSE);
1095 } else {
1096 $LOCAL_LANG[$this->language] = $LOCAL_LANG['default'];
1097 }
1098 $labelsArray[$labels] = $LOCAL_LANG[$this->language];
1099 }
1100 $JSLanguageArray .= 'HTMLArea.I18N = ' . json_encode($labelsArray) . ';' . LF;
1101 return $JSLanguageArray;
1102 }
1103
1104 /**
1105 * Writes contents in a file in typo3temp/rtehtmlarea directory and returns the file name
1106 *
1107 * @param string $sourceFileName: The name of the file from which the contents should be extracted
1108 * @param string $label: A label to insert at the beginning of the name of the file
1109 * @param string $fileExtension: The file extension of the file, defaulting to 'js'
1110 * @param string $contents: The contents to write into the file if no $sourceFileName is provided
1111 * @return string The name of the file writtten to typo3temp/rtehtmlarea
1112 */
1113 public function writeTemporaryFile($sourceFileName = '', $label, $fileExtension = 'js', $contents = '', $concatenate = FALSE) {
1114 if ($sourceFileName) {
1115 $output = '';
1116 $source = \TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName($sourceFileName);
1117 $output = file_get_contents($source);
1118 } else {
1119 $output = $contents;
1120 }
1121 $relativeFilename = 'typo3temp/' . $this->ID . '_' . str_replace('-', '_', $label) . '_' . \TYPO3\CMS\Core\Utility\GeneralUtility::shortMD5((TYPO3_version . $TYPO3_CONF_VARS['EXTCONF'][$this->ID]['version'] . ($sourceFileName ? $sourceFileName : $output)), 20) . '.' . $fileExtension;
1122 $destination = PATH_site . $relativeFilename;
1123 if (!file_exists($destination)) {
1124 $minifiedJavaScript = '';
1125 if ($fileExtension == 'js' && $output != '') {
1126 $minifiedJavaScript = \TYPO3\CMS\Core\Utility\GeneralUtility::minifyJavaScript($output);
1127 }
1128 $failure = \TYPO3\CMS\Core\Utility\GeneralUtility::writeFileToTypo3tempDir($destination, $minifiedJavaScript ? $minifiedJavaScript : $output);
1129 if ($failure) {
1130 throw new \RuntimeException($failure, 1294585668);
1131 }
1132 }
1133 if ($this->is_FE()) {
1134 $filename = $relativeFilename;
1135 } else {
1136 $filename = ($this->isFrontendEditActive() ? '' : $this->backPath . '../') . $relativeFilename;
1137 }
1138 return \TYPO3\CMS\Core\Utility\GeneralUtility::resolveBackPath($filename);
1139 }
1140
1141 /**
1142 * Return a file name containing the main JS language array for HTMLArea
1143 *
1144 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
1145 * @return string filename
1146 * @todo Define visibility
1147 */
1148 public function buildJSMainLangFile($RTEcounter) {
1149 $contents = $this->buildJSMainLangArray() . LF;
1150 foreach ($this->pluginEnabledCumulativeArray[$RTEcounter] as $pluginId) {
1151 $contents .= $this->buildJSLangArray($pluginId) . LF;
1152 }
1153 return $this->writeTemporaryFile('', $this->language . '_' . $this->OutputCharset, 'js', $contents, TRUE);
1154 }
1155
1156 /**
1157 * Return a Javascript localization array for the plugin
1158 *
1159 * @param string $plugin: identification string of the plugin
1160 * @return string Javascript localization array
1161 * @todo Define visibility
1162 */
1163 public function buildJSLangArray($plugin) {
1164 $LOCAL_LANG = FALSE;
1165 $extensionKey = is_object($this->registeredPlugins[$plugin]) ? $this->registeredPlugins[$plugin]->getExtensionKey() : $this->ID;
1166 $LOCAL_LANG = \TYPO3\CMS\Core\Utility\GeneralUtility::readLLfile('EXT:' . $extensionKey . '/htmlarea/plugins/' . $plugin . '/locallang.xml', $this->language, 'utf-8', 1);
1167 $JSLanguageArray = 'HTMLArea.I18N["' . $plugin . '"] = new Object();' . LF;
1168 if (is_array($LOCAL_LANG)) {
1169 if (!empty($LOCAL_LANG[$this->language])) {
1170 $LOCAL_LANG[$this->language] = \TYPO3\CMS\Core\Utility\GeneralUtility::array_merge_recursive_overrule($LOCAL_LANG['default'], $LOCAL_LANG[$this->language], FALSE, FALSE);
1171 } else {
1172 $LOCAL_LANG[$this->language] = $LOCAL_LANG['default'];
1173 }
1174 $JSLanguageArray .= 'HTMLArea.I18N["' . $plugin . '"] = ' . json_encode($LOCAL_LANG[$this->language]) . ';' . LF;
1175 }
1176 return $JSLanguageArray;
1177 }
1178
1179 /**
1180 * Return the JS code of the toolbar configuration for the HTMLArea editor
1181 *
1182 * @return string the JS code as nested JS arrays
1183 */
1184 protected function getJSToolbarArray() {
1185 // The toolbar array
1186 $toolbar = array();
1187 // The current row; a "linebreak" ends the current row
1188 $row = array();
1189 // The current group; each group is between "bar"s; a "linebreak" ends the current group
1190 $group = array();
1191 // Process each toolbar item in the toolbar order list
1192 foreach ($this->toolbarOrderArray as $item) {
1193 switch ($item) {
1194 case 'linebreak':
1195 // Add row to toolbar if not empty
1196 if (!empty($group)) {
1197 $row[] = $group;
1198 $group = array();
1199 }
1200 if (!empty($row)) {
1201 $toolbar[] = $row;
1202 $row = array();
1203 }
1204 break;
1205 case 'bar':
1206 // Add group to row if not empty
1207 if (!empty($group)) {
1208 $row[] = $group;
1209 $group = array();
1210 }
1211 break;
1212 case 'space':
1213 if (end($group) != $this->convertToolbarForHTMLArea($item)) {
1214 $group[] = $this->convertToolbarForHTMLArea($item);
1215 }
1216 break;
1217 default:
1218 if (in_array($item, $this->toolbar)) {
1219 // Add the item to the group
1220 $convertedItem = $this->convertToolbarForHTMLArea($item);
1221 if ($convertedItem) {
1222 $group[] = $convertedItem;
1223 }
1224 }
1225 break;
1226 }
1227 }
1228 // Add the last group and last line, if not empty
1229 if (!empty($group)) {
1230 $row[] = $group;
1231 }
1232 if (!empty($row)) {
1233 $toolbar[] = $row;
1234 }
1235 return json_encode($toolbar);
1236 }
1237
1238 /**
1239 * Localize a string using the language of the content element rather than the language of the BE interface
1240 *
1241 * @param string string: the label to be localized
1242 * @return string Localized string.
1243 */
1244 public function getLLContent($string) {
1245 $BE_lang = $GLOBALS['LANG']->lang;
1246 $GLOBALS['LANG']->lang = $this->contentTypo3Language;
1247 $LLString = $GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->sL($string));
1248 $GLOBALS['LANG']->lang = $BE_lang;
1249 return $LLString;
1250 }
1251
1252 public function getPageConfigLabel($string, $JScharCode = 1) {
1253 global $LANG, $TSFE, $TYPO3_CONF_VARS;
1254 if ($this->is_FE()) {
1255 if (strcmp(substr($string, 0, 4), 'LLL:')) {
1256 // A pure string coming from Page TSConfig must be in utf-8
1257 $label = $TSFE->csConvObj->conv($TSFE->sL(trim($string)), 'utf-8', $this->OutputCharset);
1258 } else {
1259 $label = $TSFE->csConvObj->conv($TSFE->sL(trim($string)), $this->charset, $this->OutputCharset);
1260 }
1261 $label = str_replace('"', '\\"', str_replace('\\\'', '\'', $label));
1262 $label = $JScharCode ? $this->feJScharCode($label) : $label;
1263 } else {
1264 if (strcmp(substr($string, 0, 4), 'LLL:')) {
1265 $label = $string;
1266 } else {
1267 $label = $LANG->sL(trim($string));
1268 }
1269 $label = str_replace('"', '\\"', str_replace('\\\'', '\'', $label));
1270 $label = $JScharCode ? $LANG->JScharCode($label) : $label;
1271 }
1272 return $label;
1273 }
1274
1275 /**
1276 * @todo Define visibility
1277 */
1278 public function feJScharCode($str) {
1279 // Convert string to UTF-8:
1280 if ($this->OutputCharset != 'utf-8') {
1281 $str = $GLOBALS['TSFE']->csConvObj->utf8_encode($str, $this->OutputCharset);
1282 }
1283 // Convert the UTF-8 string into a array of char numbers:
1284 $nArr = $GLOBALS['TSFE']->csConvObj->utf8_to_numberarray($str);
1285 return 'String.fromCharCode(' . implode(',', $nArr) . ')';
1286 }
1287
1288 public function getFullFileName($filename) {
1289 if (substr($filename, 0, 4) == 'EXT:') {
1290 // extension
1291 list($extKey, $local) = explode('/', substr($filename, 4), 2);
1292 $newFilename = '';
1293 if (strcmp($extKey, '') && \TYPO3\CMS\Core\Extension\ExtensionManager::isLoaded($extKey) && strcmp($local, '')) {
1294 $newFilename = ($this->is_FE() || $this->isFrontendEditActive() ? \TYPO3\CMS\Core\Extension\ExtensionManager::siteRelPath($extKey) : $this->backPath . \TYPO3\CMS\Core\Extension\ExtensionManager::extRelPath($extKey)) . $local;
1295 }
1296 } elseif (substr($filename, 0, 1) != '/') {
1297 $newFilename = ($this->is_FE() || $this->isFrontendEditActive() ? '' : $this->backPath . '../') . $filename;
1298 } else {
1299 $newFilename = ($this->is_FE() || $this->isFrontendEditActive() ? '' : $this->backPath . '../') . substr($filename, 1);
1300 }
1301 return \TYPO3\CMS\Core\Utility\GeneralUtility::resolveBackPath($newFilename);
1302 }
1303
1304 /**
1305 * Return the Javascript code for copying the HTML code from the editor into the hidden input field.
1306 * This is for submit function of the form.
1307 *
1308 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
1309 * @param string $formName: the name of the form
1310 * @param string $textareaId: the id of the textarea
1311 * @param string $textareaName: the name of the textarea
1312 * @return string Javascript code
1313 * @todo Define visibility
1314 */
1315 public function setSaveRTE($RTEcounter, $formName, $textareaId, $textareaName) {
1316 return 'if (RTEarea["' . $textareaId . '"]) { document.' . $formName . '["' . $textareaName . '"].value = RTEarea["' . $textareaId . '"].editor.getHTML(); } else { OK = 0; };';
1317 }
1318
1319 /**
1320 * Return the Javascript code for copying the HTML code from the editor into the hidden input field.
1321 * This is for submit function of the form.
1322 *
1323 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
1324 * @param string $formName: the name of the form
1325 * @param string $textareaId: the id of the textarea
1326 * @return string Javascript code
1327 * @todo Define visibility
1328 */
1329 public function setDeleteRTE($RTEcounter, $formName, $textareaId) {
1330 return 'if (RTEarea["' . $textareaId . '"]) { RTEarea["' . $textareaId . '"].deleted = true;}';
1331 }
1332
1333 /**
1334 * Return TRUE if we are in the FE, but not in the FE editing feature of BE.
1335 *
1336 * @return boolean
1337 * @todo Define visibility
1338 */
1339 public function is_FE() {
1340 return is_object($GLOBALS['TSFE']) && !$this->isFrontendEditActive() && TYPO3_MODE == 'FE';
1341 }
1342
1343 /**
1344 * Checks whether frontend editing is active.
1345 *
1346 * @return boolean
1347 */
1348 public function isFrontendEditActive() {
1349 return is_object($GLOBALS['TSFE']) && $GLOBALS['TSFE']->beUserLogin && $GLOBALS['BE_USER']->frontendEdit instanceof \TYPO3\CMS\Core\FrontendEditing\FrontendEditingController;
1350 }
1351
1352 /**
1353 * Client Browser Information
1354 *
1355 * @param string $userAgent: The useragent string, t3lib_div::getIndpEnv('HTTP_USER_AGENT')
1356 * @return array Contains keys "useragent", "browser", "version", "system
1357 * @todo Define visibility
1358 */
1359 public function clientInfo($userAgent = '') {
1360 if (!$userAgent) {
1361 $userAgent = \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('HTTP_USER_AGENT');
1362 }
1363 $browserInfo = \TYPO3\CMS\Core\Utility\ClientUtility::getBrowserInfo($userAgent);
1364 // Known engines: order is not irrelevant!
1365 $knownEngines = array('opera', 'msie', 'gecko', 'webkit');
1366 if (is_array($browserInfo['all'])) {
1367 foreach ($knownEngines as $engine) {
1368 if ($browserInfo['all'][$engine]) {
1369 $browserInfo['browser'] = $engine;
1370 $browserInfo['version'] = \TYPO3\CMS\Core\Utility\ClientUtility::getVersion($browserInfo['all'][$engine]);
1371 break;
1372 }
1373 }
1374 }
1375 return $browserInfo;
1376 }
1377
1378 /**
1379 * Log usage of deprecated Page TS Config Property
1380 *
1381 * @param string $deprecatedProperty: Name of deprecated property
1382 * @param string $useProperty: Name of property to use instead
1383 * @param string $version: Version of TYPO3 in which the property will be removed
1384 * @return void
1385 */
1386 public function logDeprecatedProperty($deprecatedProperty, $useProperty, $version) {
1387 if (!$this->thisConfig['logDeprecatedProperties.']['disabled']) {
1388 $message = sprintf('RTE Page TSConfig property "%1$s" used on page id #%4$s is DEPRECATED and will be removed in TYPO3 %3$s. Use "%2$s" instead.', $deprecatedProperty, $useProperty, $version, $this->thePid);
1389 \TYPO3\CMS\Core\Utility\GeneralUtility::deprecationLog($message);
1390 if (is_object($GLOBALS['BE_USER']) && $this->thisConfig['logDeprecatedProperties.']['logAlsoToBELog']) {
1391 $message = sprintf($GLOBALS['LANG']->getLL('deprecatedPropertyMessage'), $deprecatedProperty, $useProperty, $version, $this->thePid);
1392 $GLOBALS['BE_USER']->simplelog($message, $this->ID);
1393 }
1394 }
1395 }
1396
1397 /***************************
1398 *
1399 * OTHER FUNCTIONS: (from Classic RTE)
1400 *
1401 ***************************/
1402 /**
1403 * @return [type] ...
1404 * @desc
1405 * @todo Define visibility
1406 */
1407 public function RTEtsConfigParams() {
1408 if ($this->is_FE()) {
1409 return '';
1410 } else {
1411 $p = \TYPO3\CMS\Backend\Utility\BackendUtility::getSpecConfParametersFromArray($this->specConf['rte_transform']['parameters']);
1412 return $this->elementParts[0] . ':' . $this->elementParts[1] . ':' . $this->elementParts[2] . ':' . $this->thePid . ':' . $this->typeVal . ':' . $this->tscPID . ':' . $p['imgpath'];
1413 }
1414 }
1415
1416 public function cleanList($str) {
1417 if (strstr($str, '*')) {
1418 $str = '*';
1419 } else {
1420 $str = implode(',', array_unique(\TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $str, 1)));
1421 }
1422 return $str;
1423 }
1424
1425 /**
1426 * @todo Define visibility
1427 */
1428 public function filterStyleEl($elValue, $matchList) {
1429 $matchParts = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $matchList, 1);
1430 $styleParts = explode(';', $elValue);
1431 $nStyle = array();
1432 foreach ($styleParts as $k => $p) {
1433 $pp = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(':', $p);
1434 if ($pp[0] && $pp[1]) {
1435 foreach ($matchParts as $el) {
1436 $star = substr($el, -1) == '*';
1437 if (!strcmp($pp[0], $el) || $star && \TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($pp[0], substr($el, 0, -1))) {
1438 $nStyle[] = $pp[0] . ':' . $pp[1];
1439 } else {
1440 unset($styleParts[$k]);
1441 }
1442 }
1443 } else {
1444 unset($styleParts[$k]);
1445 }
1446 }
1447 return implode('; ', $nStyle);
1448 }
1449
1450 // Hook on lorem_ipsum extension to insert text into the RTE in wysiwyg mode
1451 /**
1452 * @todo Define visibility
1453 */
1454 public function loremIpsumInsert($params) {
1455 return '
1456 if (typeof(lorem_ipsum) == \'function\' && ' . $params['element'] . '.tagName.toLowerCase() == \'textarea\' ) lorem_ipsum(' . $params['element'] . ', lipsum_temp_strings[lipsum_temp_pointer]);
1457 ';
1458 }
1459
1460 }
1461
1462
1463 ?>