[BUGFIX] Fix wrong JS function name in RTE
[Packages/TYPO3.CMS.git] / typo3 / sysext / rtehtmlarea / Classes / SelectImage.php
1 <?php
2 namespace TYPO3\CMS\Rtehtmlarea;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 1999-2013 Kasper Skårhøj (kasper@typo3.com)
8 * (c) 2004-2013 Stanislas Rolland <typo3(arobas)jbr.ca>
9 * All rights reserved
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 * A copy is found in the text file GPL.txt and important notices to the license
20 * from the author is found in LICENSE.txt distributed with these scripts.
21 *
22 *
23 * This script is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * This copyright notice MUST APPEAR in all copies of the script!
29 ***************************************************************/
30
31 use TYPO3\CMS\Backend\Utility\BackendUtility;
32 use TYPO3\CMS\Core\Utility\GeneralUtility;
33 use TYPO3\CMS\Core\Resource;
34
35 /**
36 * Script Class
37 *
38 * @author Kasper Skårhøj <kasper@typo3.com>
39 */
40 class SelectImage extends \TYPO3\CMS\Recordlist\Browser\ElementBrowser {
41
42 /**
43 * These file extensions are allowed in the "plain" image selection mode.
44 *
45 * @const
46 */
47 const PLAIN_MODE_IMAGE_FILE_EXTENSIONS = 'jpg,jpeg,gif,png';
48
49 /**
50 * @todo Define visibility
51 */
52 public $extKey = 'rtehtmlarea';
53
54 /**
55 * @todo Define visibility
56 */
57 public $content;
58
59 public $allowedItems;
60
61 public $allowedFileTypes = array();
62
63 protected $defaultClass;
64
65 /**
66 * Relevant for RTE mode "plain": the maximum width an image must have to be selectable.
67 *
68 * @var int
69 */
70 protected $plainMaxWidth;
71
72 /**
73 * Relevant for RTE mode "plain": the maximum height an image must have to be selectable.
74 *
75 * @var int
76 */
77 protected $plainMaxHeight;
78
79 protected $imgPath;
80
81 public $editorNo;
82
83 public $sys_language_content;
84
85 public $thisConfig;
86
87 public $buttonConfig;
88
89 protected $imgObj;
90
91 /**
92 * Initialisation
93 *
94 * @return void
95 */
96 public function init() {
97 $this->initVariables();
98 $this->initConfiguration();
99 $this->initHookObjects('ext/rtehtmlarea/mod4/class.tx_rtehtmlarea_select_image.php');
100
101 $this->allowedItems = $this->getAllowedItems('magic,plain,image');
102 $this->insertImage();
103
104 $this->initDocumentTemplate();
105 }
106
107 /**
108 * Initialize class variables
109 *
110 * @return void
111 */
112 public function initVariables() {
113 parent::initVariables();
114 // Get "act"
115 $this->act = GeneralUtility::_GP('act');
116 if (!$this->act) {
117 $this->act = FALSE;
118 }
119 // Process bparams
120 $pArr = explode('|', $this->bparams);
121 $pRteArr = explode(':', $pArr[1]);
122 $this->editorNo = $pRteArr[0];
123 $this->sys_language_content = $pRteArr[1];
124 $this->RTEtsConfigParams = $pArr[2];
125 if (!$this->editorNo) {
126 $this->editorNo = GeneralUtility::_GP('editorNo');
127 $this->sys_language_content = GeneralUtility::_GP('sys_language_content');
128 $this->RTEtsConfigParams = GeneralUtility::_GP('RTEtsConfigParams');
129 }
130 $pArr[1] = implode(':', array($this->editorNo, $this->sys_language_content));
131 $pArr[2] = $this->RTEtsConfigParams;
132 if ($this->act == 'dragdrop' || $this->act == 'plain') {
133 $this->allowedFileTypes = explode(',', self::PLAIN_MODE_IMAGE_FILE_EXTENSIONS);
134 }
135 $pArr[3] = implode(',', $this->allowedFileTypes);
136 $this->bparams = implode('|', $pArr);
137 }
138
139 /**
140 * Initialize document template object
141 *
142 * @return void
143 */
144 protected function initDocumentTemplate() {
145 parent::initDocumentTemplate();
146
147 $this->doc->bodyTagId = 'typo3-browse-links-php';
148 $this->doc->bodyTagAdditions = $this->getBodyTagAdditions();
149
150 $this->doc->JScode .= $this->doc->wrapScriptTags('
151 Tree.ajaxID = "SC_alt_file_navframe::expandCollapse";
152 ');
153 $this->doc->getPageRenderer()->addCssFile($this->doc->backPath . \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath('t3skin') . 'rtehtmlarea/htmlarea.css');
154 $this->doc->getContextMenuCode();
155 }
156
157 /**
158 * Provide the additional parameters to be included in the template body tag
159 *
160 * @return string the body tag additions
161 */
162 public function getBodyTagAdditions() {
163 return 'onload="initEventListeners();"';
164 }
165
166 /**
167 * Get the path to the folder where RTE images are stored
168 *
169 * @return string the path to the folder where RTE images are stored
170 * @deprecated since 6.2, will be removed in two versions
171 */
172 protected function getRTEImageStorageDir() {
173 GeneralUtility::logDeprecatedFunction();
174 return $this->imgPath ?: $GLOBALS['TYPO3_CONF_VARS']['BE']['RTE_imageStorageDir'];
175 }
176
177 /**
178 * Insert the image in the editing area
179 *
180 * @return void
181 */
182 protected function insertImage() {
183 $table = htmlspecialchars(GeneralUtility::_GP('table'));
184 $uid = (int) GeneralUtility::_GP('uid');
185 if (GeneralUtility::_GP('insertImage') && $uid) {
186 /** @var $fileObject Resource\File */
187 $fileObject = Resource\ResourceFactory::getInstance()->getFileObject($uid);
188 // Get default values for alt and title attributes from file properties
189 $altText = $fileObject->getProperty('alternative');
190 $titleText = $fileObject->getProperty('title');
191 switch ($this->act) {
192 case 'magic':
193 $this->insertMagicImage($fileObject, $altText, $titleText, 'data-htmlarea-file-uid="' . $uid . '" data-htmlarea-file-table="' . $table . '"');
194 die;
195 break;
196 case 'plain':
197 $this->insertPlainImage($fileObject, $altText, $titleText, 'data-htmlarea-file-uid="' . $uid . '" data-htmlarea-file-table="' . $table . '"');
198 die;
199 break;
200 default:
201 // Call hook
202 foreach ($this->hookObjects as $hookObject) {
203 if (method_exists($hookObject, 'insertElement')) {
204 $hookObject->insertElement($this->act);
205 }
206 }
207 }
208 }
209 }
210
211 /**
212 * Insert a magic image
213 *
214 * @param Resource\File $fileObject: the image file
215 * @param string $altText: text for the alt attribute of the image
216 * @param string $titleText: text for the title attribute of the image
217 * @param string $additionalParams: text representing more HTML attributes to be added on the img tag
218 * @return void
219 */
220 public function insertMagicImage(Resource\File $fileObject, $altText = '', $titleText = '', $additionalParams = '') {
221 // Create the magic image service
222 /** @var $magicImageService Resource\Service\MagicImageService */
223 $magicImageService = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\Service\\MagicImageService');
224 $magicImageService->setMagicImageMaximumDimensions($this->thisConfig);
225 // Create the magic image
226 $imageConfiguration = array(
227 'width' => GeneralUtility::_GP('cWidth'),
228 'height' => GeneralUtility::_GP('cHeight')
229 );
230 $magicImage = $magicImageService->createMagicImage($fileObject, $imageConfiguration);
231 $imageUrl = $magicImage->getPublicUrl();
232 // If file is local, make the url absolute
233 if (substr($imageUrl, 0, 4) !== 'http') {
234 $imageUrl = $this->siteURL . $imageUrl;
235 }
236 // Insert the magic image
237 $this->imageInsertJS($imageUrl, $magicImage->getProperty('width'), $magicImage->getProperty('height'), $altText, $titleText, $additionalParams);
238 }
239
240 /**
241 * Insert a plain image
242 *
243 * @param \TYPO3\CMS\Core\Resource\File $fileObject: the image file
244 * @param string $altText: text for the alt attribute of the image
245 * @param string $titleText: text for the title attribute of the image
246 * @param string $additionalParams: text representing more HTML attributes to be added on the img tag
247 * @return void
248 */
249 public function insertPlainImage(Resource\File $fileObject, $altText = '', $titleText = '', $additionalParams = '') {
250 $width = $fileObject->getProperty('width');
251 $height = $fileObject->getProperty('height');
252 if (!$width || !$height) {
253 $filePath = $fileObject->getForLocalProcessing(FALSE);
254 $imageInfo = @getimagesize($filePath);
255 $width = $imageInfo[0];
256 $height = $imageInfo[1];
257 }
258 $imageUrl = $fileObject->getPublicUrl();
259 // If file is local, make the url absolute
260 if (substr($imageUrl, 0, 4) !== 'http') {
261 $imageUrl = $this->siteURL . $imageUrl;
262 }
263 $this->imageInsertJS($imageUrl, $width, $height, $altText, $titleText, $additionalParams);
264 }
265
266 /**
267 * Echo the HTML page and JS that will insert the image
268 *
269 * @param string $url: the url of the image
270 * @param integer $width: the width of the image
271 * @param integer $height: the height of the image
272 * @param string $altText: text for the alt attribute of the image
273 * @param string $titleText: text for the title attribute of the image
274 * @param string $additionalParams: text representing more html attributes to be added on the img tag
275 * @return void
276 */
277 protected function imageInsertJS($url, $width, $height, $altText = '', $titleText = '', $additionalParams = '') {
278 echo '
279 <!DOCTYPE html>
280 <html>
281 <head>
282 <title>Untitled</title>
283 <script type="text/javascript">
284 /*<![CDATA[*/
285 var plugin = window.parent.RTEarea["' . $this->editorNo . '"].editor.getPlugin("TYPO3Image");
286 function insertImage(file,width,height,alt,title,additionalParams) {
287 plugin.insertImage(\'<img src="\'+file+\'" width="\'+parseInt(width)+\'" height="\'+parseInt(height)+\'"\'' . ($this->defaultClass ? '+\' class="' . $this->defaultClass . '"\'' : '') . '+(alt?\' alt="\'+alt+\'"\':\'\')+(title?\' title="\'+title+\'"\':\'\')+(additionalParams?\' \'+additionalParams:\'\')+\' />\');
288 }
289 /*]]>*/
290 </script>
291 </head>
292 <body>
293 <script type="text/javascript">
294 /*<![CDATA[*/
295 insertImage(' . GeneralUtility::quoteJSvalue($url, 1) . ',' . $width . ',' . $height . ',' . GeneralUtility::quoteJSvalue($altText, 1) . ',' . GeneralUtility::quoteJSvalue($titleText, 1) . ',' . GeneralUtility::quoteJSvalue($additionalParams, 1) . ');
296 /*]]>*/
297 </script>
298 </body>
299 </html>';
300 }
301
302 /**
303 * Generate JS code to be used on the image insert/modify dialogue
304 *
305 * @param string $act: the action to be performed
306 * @param string $editorNo: the number of the RTE instance on the page
307 * @param string $sys_language_content: the language of the content element
308 * @return string the generated JS code
309 * @todo Define visibility
310 */
311 public function getJSCode($act, $editorNo, $sys_language_content) {
312 $removedProperties = array();
313 if (is_array($this->buttonConfig['properties.'])) {
314 if ($this->buttonConfig['properties.']['removeItems']) {
315 $removedProperties = GeneralUtility::trimExplode(',', $this->buttonConfig['properties.']['removeItems'], TRUE);
316 }
317 }
318 if ($this->buttonConfig['properties.']['class.']['allowedClasses']) {
319 $classesImageArray = GeneralUtility::trimExplode(',', $this->buttonConfig['properties.']['class.']['allowedClasses'], TRUE);
320 $classesImageJSOptions = '<option value=""></option>';
321 foreach ($classesImageArray as $class) {
322 $classesImageJSOptions .= '<option value="' . $class . '">' . $class . '</option>';
323 }
324 }
325 $lockPlainWidth = 'false';
326 $lockPlainHeight = 'false';
327 if (is_array($this->thisConfig['proc.']) && $this->thisConfig['proc.']['plainImageMode']) {
328 $plainImageMode = $this->thisConfig['proc.']['plainImageMode'];
329 $lockPlainWidth = $plainImageMode == 'lockDimensions' ? 'true' : 'false';
330 $lockPlainHeight = $lockPlainWidth || $plainImageMode == 'lockRatio' || $plainImageMode == 'lockRatioWhenSmaller' ? 'true' : 'false';
331 }
332 $JScode = '
333 var plugin = window.parent.RTEarea["' . $editorNo . '"].editor.getPlugin("TYPO3Image");
334 var HTMLArea = window.parent.HTMLArea;
335
336 HTMLArea.TYPO3Image.insertElement = function (table, uid, type, filename, filePath, fileExt, fileIcon) {
337 return jumpToUrl(' . GeneralUtility::quoteJSvalue($this->getThisScript() . 'editorNo=') . ' + \'' . $editorNo . '\' + \'&insertImage=\' + filePath + \'&table=\' + table + \'&uid=\' + uid + \'&type=\' + type + \'bparams=\' + \'' . $this->bparams . '\');
338 }
339 function insertElement(table, uid, type, fileName, filePath, fileExt, fileIcon, action, close) {
340 return jumpToUrl(' . GeneralUtility::quoteJSvalue($this->getThisScript() . 'editorNo=') . ' + \'' . $editorNo . '\' + \'&insertImage=\' + filePath + \'&table=\' + table + \'&uid=\' + uid + \'&type=\' + type + \'bparams=\' + \'' . $this->bparams . '\');
341 }
342 function initEventListeners() {
343 if (Ext.isWebKit) {
344 Ext.EventManager.addListener(window.document.body, "dragend", plugin.onDrop, plugin, { single: true });
345 }
346 }
347 function jumpToUrl(URL,anchor) {
348 var add_act = URL.indexOf("act=")==-1 ? "&act=' . $act . '" : "";
349 var add_editorNo = URL.indexOf("editorNo=")==-1 ? "&editorNo=' . $editorNo . '" : "";
350 var add_sys_language_content = URL.indexOf("sys_language_content=")==-1 ? "&sys_language_content=' . $sys_language_content . '" : "";
351 var RTEtsConfigParams = "&RTEtsConfigParams=' . rawurlencode($this->RTEtsConfigParams) . '";
352
353 var cur_width = selectedImageRef ? "&cWidth="+selectedImageRef.style.width : "";
354 var cur_height = selectedImageRef ? "&cHeight="+selectedImageRef.style.height : "";
355
356 var theLocation = URL+add_act+add_editorNo+add_sys_language_content+RTEtsConfigParams+cur_width+cur_height+(typeof(anchor)=="string"?anchor:"");
357 window.location.href = theLocation;
358 return false;
359 }
360 function insertImage(file,width,height) {
361 plugin.insertImage(\'<img src="\'+file+\'"' . ($this->defaultClass ? ' class="' . $this->defaultClass . '"' : '') . ' width="\'+parseInt(width)+\'" height="\'+parseInt(height)+\'" />\');
362 }
363 function launchView(url) {
364 var thePreviewWindow="";
365 thePreviewWindow = window.open("' . GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . TYPO3_mainDir . 'show_item.php?table="+url,"ShowItem","height=300,width=410,status=0,menubar=0,resizable=0,location=0,directories=0,scrollbars=1,toolbar=0");
366 if (thePreviewWindow && thePreviewWindow.focus) {
367 thePreviewWindow.focus();
368 }
369 }
370 function getCurrentImageRef() {
371 if (plugin.image) {
372 return plugin.image;
373 } else {
374 return null;
375 }
376 }
377 function printCurrentImageOptions() {
378 var classesImage = ' . ($this->buttonConfig['properties.']['class.']['allowedClasses'] || $this->thisConfig['classesImage'] ? 'true' : 'false') . ';
379 if (classesImage) var styleSelector=\'<select id="iClass" name="iClass" style="width:140px;">' . $classesImageJSOptions . '</select>\';
380 var floatSelector=\'<select id="iFloat" name="iFloat"><option value="">' . $GLOBALS['LANG']->getLL('notSet') . '</option><option value="none">' . $GLOBALS['LANG']->getLL('nonFloating') . '</option><option value="left">' . $GLOBALS['LANG']->getLL('left') . '</option><option value="right">' . $GLOBALS['LANG']->getLL('right') . '</option></select>\';
381 if (plugin.getButton("Language")) {
382 var languageSelector = \'<select id="iLang" name="iLang">\';
383 plugin.getButton("Language").getStore().each(function (record) {
384 languageSelector +=\'<option value="\' + record.get("value") + \'">\' + record.get("text") + \'</option>\';
385 });
386 languageSelector += \'</select>\';
387 }
388 var sz="";
389 sz+=\'<form action="" name="imageData"><table class="htmlarea-window-table">\';
390 ' . (in_array('class', $removedProperties) ? '' : '
391 if(classesImage) {
392 sz+=\'<tr><td><label for="iClass">' . $GLOBALS['LANG']->getLL('class') . ': </label></td><td>\'+styleSelector+\'</td></tr>\';
393 }') . (in_array('width', $removedProperties) ? '' : '
394 if (!(selectedImageRef && selectedImageRef.src.indexOf("RTEmagic") == -1 && ' . $lockPlainWidth . ')) {
395 sz+=\'<tr><td><label for="iWidth">' . $GLOBALS['LANG']->getLL('width') . ': </label></td><td><input type="text" id="iWidth" name="iWidth" value=""' . $GLOBALS['TBE_TEMPLATE']->formWidth(4) . ' /></td></tr>\';
396 }') . (in_array('height', $removedProperties) ? '' : '
397 if (!(selectedImageRef && selectedImageRef.src.indexOf("RTEmagic") == -1 && ' . $lockPlainHeight . ')) {
398 sz+=\'<tr><td><label for="iHeight">' . $GLOBALS['LANG']->getLL('height') . ': </label></td><td><input type="text" id="iHeight" name="iHeight" value=""' . $GLOBALS['TBE_TEMPLATE']->formWidth(4) . ' /></td></tr>\';
399 }') . (in_array('border', $removedProperties) ? '' : '
400 sz+=\'<tr><td><label for="iBorder">' . $GLOBALS['LANG']->getLL('border') . ': </label></td><td><input type="checkbox" id="iBorder" name="iBorder" value="1" /></td></tr>\';') . (in_array('float', $removedProperties) ? '' : '
401 sz+=\'<tr><td><label for="iFloat">' . $GLOBALS['LANG']->getLL('float') . ': </label></td><td>\'+floatSelector+\'</td></tr>\';') . (in_array('paddingTop', $removedProperties) ? '' : '
402 sz+=\'<tr><td><label for="iPaddingTop">' . $GLOBALS['LANG']->getLL('padding_top') . ': </label></td><td><input type="text" id="iPaddingTop" name="iPaddingTop" value=""' . $GLOBALS['TBE_TEMPLATE']->formWidth(4) . '></td></tr>\';') . (in_array('paddingRight', $removedProperties) ? '' : '
403 sz+=\'<tr><td><label for="iPaddingRight">' . $GLOBALS['LANG']->getLL('padding_right') . ': </label></td><td><input type="text" id="iPaddingRight" name="iPaddingRight" value=""' . $GLOBALS['TBE_TEMPLATE']->formWidth(4) . ' /></td></tr>\';') . (in_array('paddingBottom', $removedProperties) ? '' : '
404 sz+=\'<tr><td><label for="iPaddingBottom">' . $GLOBALS['LANG']->getLL('padding_bottom') . ': </label></td><td><input type="text" id="iPaddingBottom" name="iPaddingBottom" value=""' . $GLOBALS['TBE_TEMPLATE']->formWidth(4) . ' /></td></tr>\';') . (in_array('paddingLeft', $removedProperties) ? '' : '
405 sz+=\'<tr><td><label for="iPaddingLeft">' . $GLOBALS['LANG']->getLL('padding_left') . ': </label></td><td><input type="text" id="iPaddingLeft" name="iPaddingLeft" value=""' . $GLOBALS['TBE_TEMPLATE']->formWidth(4) . ' /></td></tr>\';') . (in_array('title', $removedProperties) ? '' : '
406 sz+=\'<tr><td><label for="iTitle">' . $GLOBALS['LANG']->getLL('title') . ': </label></td><td><input type="text" id="iTitle" name="iTitle"' . $GLOBALS['TBE_TEMPLATE']->formWidth(20) . ' /></td></tr>\';') . (in_array('alt', $removedProperties) ? '' : '
407 sz+=\'<tr><td><label for="iAlt">' . $GLOBALS['LANG']->getLL('alt') . ': </label></td><td><input type="text" id="iAlt" name="iAlt"' . $GLOBALS['TBE_TEMPLATE']->formWidth(20) . ' /></td></tr>\';') . (in_array('lang', $removedProperties) ? '' : '
408 if (plugin.getButton("Language")) {
409 sz+=\'<tr><td><label for="iLang">\' + plugin.editor.getPlugin("Language").localize(\'Language-Tooltip\') + \': </label></td><td>\' + languageSelector + \'</td></tr>\';
410 }') . (in_array('clickenlarge', $removedProperties) || in_array('data-htmlarea-clickenlarge', $removedProperties) ? '' : '
411 sz+=\'<tr><td><label for="iClickEnlarge">' . $GLOBALS['LANG']->sL('LLL:EXT:cms/locallang_ttc.xlf:image_zoom', TRUE) . ' </label></td><td><input type="checkbox" name="iClickEnlarge" id="iClickEnlarge" value="0" /></td></tr>\';') . '
412 sz+=\'<tr><td></td><td><input type="submit" value="' . $GLOBALS['LANG']->getLL('update') . '" onClick="return setImageProperties();"></td></tr>\';
413 sz+=\'</table></form>\';
414 return sz;
415 }
416 function setImageProperties() {
417 var classesImage = ' . ($this->buttonConfig['properties.']['class.']['allowedClasses'] || $this->thisConfig['classesImage'] ? 'true' : 'false') . ';
418 if (selectedImageRef) {
419 if (document.imageData.iWidth) {
420 if (document.imageData.iWidth.value && parseInt(document.imageData.iWidth.value)) {
421 selectedImageRef.style.width = "";
422 selectedImageRef.width = parseInt(document.imageData.iWidth.value);
423 }
424 }
425 if (document.imageData.iHeight) {
426 if (document.imageData.iHeight.value && parseInt(document.imageData.iHeight.value)) {
427 selectedImageRef.style.height = "";
428 selectedImageRef.height = parseInt(document.imageData.iHeight.value);
429 }
430 }
431 if (document.imageData.iPaddingTop) {
432 if (document.imageData.iPaddingTop.value != "" && !isNaN(parseInt(document.imageData.iPaddingTop.value))) {
433 selectedImageRef.style.paddingTop = parseInt(document.imageData.iPaddingTop.value) + "px";
434 } else {
435 selectedImageRef.style.paddingTop = "";
436 }
437 }
438 if (document.imageData.iPaddingRight) {
439 if (document.imageData.iPaddingRight.value != "" && !isNaN(parseInt(document.imageData.iPaddingRight.value))) {
440 selectedImageRef.style.paddingRight = parseInt(document.imageData.iPaddingRight.value) + "px";
441 } else {
442 selectedImageRef.style.paddingRight = "";
443 }
444 }
445 if (document.imageData.iPaddingBottom) {
446 if (document.imageData.iPaddingBottom.value != "" && !isNaN(parseInt(document.imageData.iPaddingBottom.value))) {
447 selectedImageRef.style.paddingBottom = parseInt(document.imageData.iPaddingBottom.value) + "px";
448 } else {
449 selectedImageRef.style.paddingBottom = "";
450 }
451 }
452 if (document.imageData.iPaddingLeft) {
453 if (document.imageData.iPaddingLeft.value != "" && !isNaN(parseInt(document.imageData.iPaddingLeft.value))) {
454 selectedImageRef.style.paddingLeft = parseInt(document.imageData.iPaddingLeft.value) + "px";
455 } else {
456 selectedImageRef.style.paddingLeft = "";
457 }
458 }
459 if (document.imageData.iTitle) {
460 selectedImageRef.title=document.imageData.iTitle.value;
461 }
462 if (document.imageData.iAlt) {
463 selectedImageRef.alt=document.imageData.iAlt.value;
464 }
465 if (document.imageData.iBorder) {
466 selectedImageRef.style.borderStyle = "";
467 selectedImageRef.style.borderWidth = "";
468 selectedImageRef.style.border = ""; // this statement ignored by Mozilla 1.3.1
469 selectedImageRef.style.borderTopStyle = "";
470 selectedImageRef.style.borderRightStyle = "";
471 selectedImageRef.style.borderBottomStyle = "";
472 selectedImageRef.style.borderLeftStyle = "";
473 selectedImageRef.style.borderTopWidth = "";
474 selectedImageRef.style.borderRightWidth = "";
475 selectedImageRef.style.borderBottomWidth = "";
476 selectedImageRef.style.borderLeftWidth = "";
477 if(document.imageData.iBorder.checked) {
478 selectedImageRef.style.borderStyle = "solid";
479 selectedImageRef.style.borderWidth = "thin";
480 }
481 selectedImageRef.removeAttribute("border");
482 }
483 if (document.imageData.iFloat) {
484 var iFloat = document.imageData.iFloat.options[document.imageData.iFloat.selectedIndex].value;
485 if (document.all) {
486 selectedImageRef.style.styleFloat = iFloat ? iFloat : "";
487 } else {
488 selectedImageRef.style.cssFloat = iFloat ? iFloat : "";
489 }
490 }
491 if (classesImage && document.imageData.iClass) {
492 var iClass = document.imageData.iClass.options[document.imageData.iClass.selectedIndex].value;
493 if (iClass || (selectedImageRef.attributes["class"] && selectedImageRef.attributes["class"].value)) {
494 selectedImageRef.className = iClass;
495 } else {
496 selectedImageRef.className = "";
497 }
498 }
499 if (document.imageData.iLang) {
500 var iLang = document.imageData.iLang.options[document.imageData.iLang.selectedIndex].value;
501 var languageObject = plugin.editor.getPlugin("Language");
502 if (iLang || languageObject.getLanguageAttribute(selectedImageRef)) {
503 languageObject.setLanguageAttributes(selectedImageRef, iLang);
504 } else {
505 languageObject.setLanguageAttributes(selectedImageRef, "none");
506 }
507 }
508 if (document.imageData.iClickEnlarge) {
509 if (document.imageData.iClickEnlarge.checked) {
510 selectedImageRef.setAttribute("data-htmlarea-clickenlarge","1");
511 } else {
512 selectedImageRef.removeAttribute("data-htmlarea-clickenlarge");
513 selectedImageRef.removeAttribute("clickenlarge");
514 }
515 }
516 plugin.close();
517 }
518 return false;
519 }
520 function insertImagePropertiesInForm() {
521 var classesImage = ' . ($this->buttonConfig['properties.']['class.']['allowedClasses'] || $this->thisConfig['classesImage'] ? 'true' : 'false') . ';
522 if (selectedImageRef) {
523 var styleWidth, styleHeight, padding;
524 if (document.imageData.iWidth) {
525 styleWidth = selectedImageRef.style.width ? selectedImageRef.style.width : selectedImageRef.width;
526 styleWidth = parseInt(styleWidth);
527 if (!(isNaN(styleWidth) || styleWidth == 0)) {
528 document.imageData.iWidth.value = styleWidth;
529 }
530 }
531 if (document.imageData.iHeight) {
532 styleHeight = selectedImageRef.style.height ? selectedImageRef.style.height : selectedImageRef.height;
533 styleHeight = parseInt(styleHeight);
534 if (!(isNaN(styleHeight) || styleHeight == 0)) {
535 document.imageData.iHeight.value = styleHeight;
536 }
537 }
538 if (document.imageData.iPaddingTop) {
539 var padding = selectedImageRef.style.paddingTop ? selectedImageRef.style.paddingTop : selectedImageRef.vspace;
540 var padding = parseInt(padding);
541 if (isNaN(padding) || padding <= 0) { padding = ""; }
542 document.imageData.iPaddingTop.value = padding;
543 }
544 if (document.imageData.iPaddingRight) {
545 padding = selectedImageRef.style.paddingRight ? selectedImageRef.style.paddingRight : selectedImageRef.hspace;
546 var padding = parseInt(padding);
547 if (isNaN(padding) || padding <= 0) { padding = ""; }
548 document.imageData.iPaddingRight.value = padding;
549 }
550 if (document.imageData.iPaddingBottom) {
551 var padding = selectedImageRef.style.paddingBottom ? selectedImageRef.style.paddingBottom : selectedImageRef.vspace;
552 var padding = parseInt(padding);
553 if (isNaN(padding) || padding <= 0) { padding = ""; }
554 document.imageData.iPaddingBottom.value = padding;
555 }
556 if (document.imageData.iPaddingLeft) {
557 var padding = selectedImageRef.style.paddingLeft ? selectedImageRef.style.paddingLeft : selectedImageRef.hspace;
558 var padding = parseInt(padding);
559 if (isNaN(padding) || padding <= 0) { padding = ""; }
560 document.imageData.iPaddingLeft.value = padding;
561 }
562 if (document.imageData.iTitle) {
563 document.imageData.iTitle.value = selectedImageRef.title;
564 }
565 if (document.imageData.iAlt) {
566 document.imageData.iAlt.value = selectedImageRef.alt;
567 }
568 if (document.imageData.iBorder) {
569 if((selectedImageRef.style.borderStyle && selectedImageRef.style.borderStyle != "none" && selectedImageRef.style.borderStyle != "none none none none") || selectedImageRef.border) {
570 document.imageData.iBorder.checked = 1;
571 }
572 }
573 if (document.imageData.iFloat) {
574 var fObj=document.imageData.iFloat;
575 var value = (selectedImageRef.style.cssFloat ? selectedImageRef.style.cssFloat : selectedImageRef.style.styleFloat);
576 var l=fObj.length;
577 for (var a=0;a<l;a++) {
578 if (fObj.options[a].value == value) {
579 fObj.selectedIndex = a;
580 }
581 }
582 }
583 if (classesImage && document.imageData.iClass) {
584 var fObj=document.imageData.iClass;
585 var value=selectedImageRef.className;
586 var l=fObj.length;
587 for (var a=0;a < l; a++) {
588 if (fObj.options[a].value == value) {
589 fObj.selectedIndex = a;
590 }
591 }
592 }
593 if (document.imageData.iLang) {
594 var fObj=document.imageData.iLang;
595 var value=plugin.editor.getPlugin("Language").getLanguageAttribute(selectedImageRef);
596 for (var i = 0, n = fObj.length; i < n; i++) {
597 if (fObj.options[i].value == value) {
598 fObj.selectedIndex = i;
599 if (i) {
600 fObj.options[0].text = plugin.editor.getPlugin("Language").localize("Remove language mark");
601 }
602 }
603 }
604 }
605 if (document.imageData.iClickEnlarge) {
606 if (selectedImageRef.getAttribute("data-htmlarea-clickenlarge") == "1" || selectedImageRef.getAttribute("clickenlarge") == "1") {
607 document.imageData.iClickEnlarge.checked = 1;
608 } else {
609 document.imageData.iClickEnlarge.checked = 0;
610 }
611 }
612 return false;
613 }
614 }
615
616 var selectedImageRef = getCurrentImageRef();';
617 // Setting this to a reference to the image object.
618 return $JScode;
619 }
620
621 /**
622 * Session data for this class can be set from outside with this method.
623 * Call after init()
624 *
625 * @param array $data Session data array
626 * @return array Session data and boolean which indicates that data needs to be stored in session because it's changed
627 * @todo Define visibility
628 */
629 public function processSessionData($data) {
630 $store = FALSE;
631 if ($this->act != 'image') {
632 if (isset($this->act)) {
633 $data['act'] = $this->act;
634 $store = TRUE;
635 } else {
636 $this->act = $data['act'];
637 }
638 }
639 if (isset($this->expandFolder)) {
640 $data['expandFolder'] = $this->expandFolder;
641 $store = TRUE;
642 } else {
643 $this->expandFolder = $data['expandFolder'];
644 }
645 return array($data, $store);
646 }
647
648 /**
649 * @return string
650 * @todo Define visibility
651 */
652 public function main_rte() {
653 // Starting content:
654 $this->content = $this->doc->startPage($GLOBALS['LANG']->getLL('Insert Image', TRUE));
655 // Making menu in top:
656 $menuDef = array();
657 if (in_array('image', $this->allowedItems) && ($this->act === 'image' || GeneralUtility::_GP('cWidth'))) {
658 $menuDef['image']['isActive'] = FALSE;
659 $menuDef['image']['label'] = $GLOBALS['LANG']->getLL('currentImage', TRUE);
660 $menuDef['image']['url'] = '#';
661 $menuDef['image']['addParams'] = 'onClick="jumpToUrl(' . GeneralUtility::quoteJSvalue($this->getThisScript() . 'act=image&bparams=' . $this->bparams) . ');return false;"';
662 }
663 if (in_array('magic', $this->allowedItems)) {
664 $menuDef['magic']['isActive'] = FALSE;
665 $menuDef['magic']['label'] = $GLOBALS['LANG']->getLL('magicImage', TRUE);
666 $menuDef['magic']['url'] = '#';
667 $menuDef['magic']['addParams'] = 'onClick="jumpToUrl(' . GeneralUtility::quoteJSvalue($this->getThisScript() . 'act=magic&bparams=' . $this->bparams) . ');return false;"';
668 }
669 if (in_array('plain', $this->allowedItems)) {
670 $menuDef['plain']['isActive'] = FALSE;
671 $menuDef['plain']['label'] = $GLOBALS['LANG']->getLL('plainImage', TRUE);
672 $menuDef['plain']['url'] = '#';
673 $menuDef['plain']['addParams'] = 'onClick="jumpToUrl(' . GeneralUtility::quoteJSvalue($this->getThisScript() . 'act=plain&bparams=' . $this->bparams) . ');return false;"';
674 }
675 if (in_array('dragdrop', $this->allowedItems)) {
676 $menuDef['dragdrop']['isActive'] = FALSE;
677 $menuDef['dragdrop']['label'] = $GLOBALS['LANG']->getLL('dragDropImage', TRUE);
678 $menuDef['dragdrop']['url'] = '#';
679 $menuDef['dragdrop']['addParams'] = 'onClick="jumpToUrl(' . GeneralUtility::quoteJSvalue($this->getThisScript() . 'act=dragdrop&bparams=' . $this->bparams) . ');return false;"';
680 }
681 // Call hook for extra options
682 foreach ($this->hookObjects as $hookObject) {
683 $menuDef = $hookObject->modifyMenuDefinition($menuDef);
684 }
685 // Order the menu items as specified in Page TSconfig
686 $menuDef = $this->orderMenuDefinition($menuDef);
687 // Set active menu item
688 reset($menuDef);
689 if ($this->act === FALSE || !in_array($this->act, $this->allowedItems)) {
690 $this->act = key($menuDef);
691 }
692 $menuDef[$this->act]['isActive'] = TRUE;
693 $this->content .= $this->doc->getTabMenuRaw($menuDef);
694 switch ($this->act) {
695 case 'image':
696 $JScode = '
697 document.write(printCurrentImageOptions());
698 insertImagePropertiesInForm();';
699 $this->content .= '<br />' . $this->doc->wrapScriptTags($JScode);
700 break;
701 case 'plain':
702
703 case 'magic':
704 // Create folder tree:
705 $foldertree = GeneralUtility::makeInstance('TYPO3\\CMS\\Rtehtmlarea\\FolderTree');
706 $foldertree->thisScript = $this->thisScript;
707 $tree = $foldertree->getBrowsableTree();
708 // Get currently selected folder
709 if (!$this->curUrlInfo['value'] || $this->curUrlInfo['act'] != $this->act) {
710 $cmpPath = '';
711 } else {
712 $cmpPath = $this->curUrlInfo['value'];
713 if (!isset($this->expandFolder)) {
714 $this->expandFolder = $cmpPath;
715 }
716 }
717 // Get the selected folder
718 $selectedFolder = FALSE;
719 if ($this->expandFolder) {
720 $fileOrFolderObject = NULL;
721 try {
722 $fileOrFolderObject = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->retrieveFileOrFolderObject($this->expandFolder);
723 } catch (\Exception $e) {
724 // No path is selected
725 }
726 if ($fileOrFolderObject instanceof \TYPO3\CMS\Core\Resource\Folder) {
727 // it's a folder
728 $selectedFolder = $fileOrFolderObject;
729 } elseif ($fileOrFolderObject instanceof \TYPO3\CMS\Core\Resource\FileInterface) {
730 // it's a file
731 $selectedFolder = $fileOrFolderObject->getParentFolder();
732 }
733 }
734 // If no folder is selected, get the user's default upload folder
735 if (!$selectedFolder) {
736 try {
737 $selectedFolder = $GLOBALS['BE_USER']->getDefaultUploadFolder();
738 } catch (\Exception $e) {
739 // The configured default user folder does not exist
740 }
741 }
742 // Build the file upload and folder creation form
743 $uploadForm = '';
744 $createFolder = '';
745 if ($selectedFolder) {
746 $uploadForm = $this->uploadForm($selectedFolder);
747 $createFolder = $this->createFolder($selectedFolder);
748 }
749 // Insert the upload form on top, if so configured
750 if ($GLOBALS['BE_USER']->getTSConfigVal('options.uploadFieldsInTopOfEB')) {
751 $this->content .= $uploadForm;
752 }
753 // Render the filelist if there is a folder selected
754 $files = '';
755 if ($selectedFolder) {
756 $files = $this->TBE_expandFolder($selectedFolder, $this->act === 'plain' ? self::PLAIN_MODE_IMAGE_FILE_EXTENSIONS : $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $GLOBALS['BE_USER']->getTSConfigVal('options.noThumbsInRTEimageSelect'));
757 }
758 // Setup filelist indexed elements:
759 $this->doc->JScode .= $this->doc->wrapScriptTags('BrowseLinks.addElements(' . json_encode($this->elements) . ');');
760 // Wrap tree
761 $this->content .= '
762
763 <!--
764 Wrapper table for folder tree / file/folder list:
765 -->
766 <table border="0" cellpadding="0" cellspacing="0" id="typo3-linkFiles">
767 <tr>
768 <td class="c-wCell" valign="top">' . $this->barheader(($GLOBALS['LANG']->getLL('folderTree') . ':')) . $tree . '</td>
769 <td class="c-wCell" valign="top">' . $files . '</td>
770 </tr>
771 </table>
772 ';
773 // Add help message
774 $helpMessage = $this->getHelpMessage($this->act);
775 if ($helpMessage) {
776 $this->content .= $this->getMsgBox($helpMessage);
777 }
778 // Adding create folder + upload form if applicable
779 if (!$GLOBALS['BE_USER']->getTSConfigVal('options.uploadFieldsInTopOfEB')) {
780 $this->content .= $uploadForm;
781 }
782 $this->content .= $createFolder;
783 $this->content .= '<br />';
784 break;
785 case 'dragdrop':
786 $foldertree = GeneralUtility::makeInstance('TBE_FolderTree');
787 $foldertree->thisScript = $this->thisScript;
788 $foldertree->ext_noTempRecyclerDirs = TRUE;
789 $tree = $foldertree->getBrowsableTree();
790 // Get currently selected folder
791 if (!$this->curUrlInfo['value'] || $this->curUrlInfo['act'] != $this->act) {
792 $cmpPath = '';
793 } else {
794 $cmpPath = $this->curUrlInfo['value'];
795 if (!isset($this->expandFolder)) {
796 $this->expandFolder = $cmpPath;
797 }
798 }
799 $selectedFolder = FALSE;
800 if ($this->expandFolder) {
801 try {
802 $selectedFolder = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->getFolderObjectFromCombinedIdentifier($this->expandFolder);
803 } catch (\Exception $e) {
804 }
805 }
806 // Render the filelist if there is a folder selected
807 $files = '';
808 if ($selectedFolder) {
809 $files = $this->TBE_dragNDrop($selectedFolder, implode(',', $this->allowedFileTypes));
810 }
811 // Wrap tree
812 $this->content .= '<table border="0" cellpadding="0" cellspacing="0">
813 <tr>
814 <td style="vertical-align: top;">' . $this->barheader(($GLOBALS['LANG']->getLL('folderTree') . ':')) . $tree . '</td>
815 <td>&nbsp;</td>
816 <td style="vertical-align: top;">' . $files . '</td>
817 </tr>
818 </table>';
819 break;
820 default:
821 // Call hook
822 foreach ($this->hookObjects as $hookObject) {
823 $this->content .= $hookObject->getTab($this->act);
824 }
825 }
826 $this->content .= $this->doc->endPage();
827
828 // unset the default jumpToUrl() function
829 unset($this->doc->JScodeArray['jumpToUrl']);
830
831 $this->doc->JScodeArray['rtehtmlarea'] = $this->getJSCode($this->act, $this->editorNo, $this->sys_language_content);
832 $this->content = $this->doc->insertStylesAndJS($this->content);
833 return $this->content;
834 }
835
836 /**
837 * Initializes the configuration variables
838 *
839 * @return void
840 */
841 public function initConfiguration() {
842 $this->thisConfig = $this->getRTEConfig();
843 $this->buttonConfig = $this->getButtonConfig();
844 $this->imgPath = $this->getImgPath();
845 $this->defaultClass = $this->getDefaultClass();
846 $this->setMaximumPlainImageDimensions();
847 }
848
849 /**
850 * Get the path of the image to be inserted or modified
851 *
852 * @return string path to the image
853 */
854 protected function getImgPath() {
855 $RTEtsConfigParts = explode(':', $this->RTEtsConfigParams);
856 return $RTEtsConfigParts[6];
857 }
858
859 /**
860 * Get the configuration of the image button
861 *
862 * @return array the configuration array of the image button
863 */
864 protected function getButtonConfig() {
865 return is_array($this->thisConfig['buttons.']) && is_array($this->thisConfig['buttons.']['image.']) ? $this->thisConfig['buttons.']['image.'] : array();
866 }
867
868 /**
869 * Get the allowed items or tabs
870 *
871 * @param string $items: initial list of possible items
872 * @return array the allowed items
873 */
874 public function getAllowedItems($items) {
875 $allowedItems = explode(',', $items);
876 $clientInfo = GeneralUtility::clientInfo();
877 if ($clientInfo['BROWSER'] !== 'opera') {
878 $allowedItems[] = 'dragdrop';
879 }
880 // Call hook for extra options
881 foreach ($this->hookObjects as $hookObject) {
882 $allowedItems = $hookObject->addAllowedItems($allowedItems);
883 }
884 // Remove tab "image" if there is no current image
885 if ($this->act !== 'image') {
886 $allowedItems = array_diff($allowedItems, array('image'));
887 }
888 // Remove options according to RTE configuration
889 if (is_array($this->buttonConfig['options.']) && $this->buttonConfig['options.']['removeItems']) {
890 $allowedItems = array_diff($allowedItems, GeneralUtility::trimExplode(',', $this->buttonConfig['options.']['removeItems'], TRUE));
891 }
892 return $allowedItems;
893 }
894
895 /**
896 * Order the definition of menu items according to configured order
897 *
898 * @param array $menuDefinition: definition of menu items
899 * @return array ordered menu definition
900 */
901 public function orderMenuDefinition($menuDefinition) {
902 $orderedMenuDefinition = array();
903 if (is_array($this->buttonConfig['options.']) && $this->buttonConfig['options.']['orderItems']) {
904 $orderItems = GeneralUtility::trimExplode(',', $this->buttonConfig['options.']['orderItems'], TRUE);
905 $orderItems = array_intersect($orderItems, $this->allowedItems);
906 foreach ($orderItems as $item) {
907 $orderedMenuDefinition[$item] = $menuDefinition[$item];
908 }
909 } else {
910 $orderedMenuDefinition = $menuDefinition;
911 }
912 return $orderedMenuDefinition;
913 }
914
915 /**
916 * Get the default image class
917 *
918 * @return string the default class, if any
919 */
920 protected function getDefaultClass() {
921 $defaultClass = '';
922 if (is_array($this->buttonConfig['properties.'])) {
923 if (is_array($this->buttonConfig['properties.']['class.']) && trim($this->buttonConfig['properties.']['class.']['default'])) {
924 $defaultClass = trim($this->buttonConfig['properties.']['class.']['default']);
925 }
926 }
927 return $defaultClass;
928 }
929
930 /**
931 * Set variables for maximum plain image dimensions
932 *
933 * @return void
934 */
935 protected function setMaximumPlainImageDimensions() {
936 if (is_array($this->buttonConfig['options.']) && is_array($this->buttonConfig['options.']['plain.'])) {
937 if ($this->buttonConfig['options.']['plain.']['maxWidth']) {
938 $this->plainMaxWidth = $this->buttonConfig['options.']['plain.']['maxWidth'];
939 }
940 if ($this->buttonConfig['options.']['plain.']['maxHeight']) {
941 $this->plainMaxHeight = $this->buttonConfig['options.']['plain.']['maxHeight'];
942 }
943 }
944 if (!$this->plainMaxWidth) {
945 $this->plainMaxWidth = 640;
946 }
947 if (!$this->plainMaxHeight) {
948 $this->plainMaxHeight = 680;
949 }
950 }
951
952 /**
953 * Get the help message to be displayed on a given tab
954 *
955 * @param string $act: the identifier of the tab
956 * @return string the text of the message
957 */
958 public function getHelpMessage($act) {
959 switch ($act) {
960 case 'plain':
961 return sprintf($GLOBALS['LANG']->getLL('plainImage_msg'), $this->plainMaxWidth, $this->plainMaxHeight);
962 break;
963 case 'magic':
964 return sprintf($GLOBALS['LANG']->getLL('magicImage_msg'));
965 break;
966 default:
967 return '';
968 }
969 }
970
971 /**
972 * Checks if the given file is selectable in the file list.
973 *
974 * In "plain" RTE mode only image files with a maximum width and height are selectable.
975 *
976 * @param \TYPO3\CMS\Core\Resource\FileInterface $file
977 * @param array $imgInfo Image dimensions from \TYPO3\CMS\Core\Imaging\GraphicalFunctions::getImageDimensions()
978 * @return bool TRUE if file is selectable.
979 */
980 protected function fileIsSelectableInFileList(\TYPO3\CMS\Core\Resource\FileInterface $file, array $imgInfo) {
981 return (
982 $this->act !== 'plain'
983 || (
984 GeneralUtility::inList(self::PLAIN_MODE_IMAGE_FILE_EXTENSIONS, strtolower($file->getExtension()))
985 && $imgInfo[0] <= $this->plainMaxWidth
986 && $imgInfo[1] <= $this->plainMaxHeight
987 )
988 );
989 }
990 }