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