[TASK] Migrate eID scripts to use PSR-7
[Packages/TYPO3.CMS.git] / typo3 / sysext / rtehtmlarea / Classes / BrowseLinks.php
1 <?php
2 namespace TYPO3\CMS\Rtehtmlarea;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Backend\Utility\BackendUtility;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19
20 /**
21 * Script class for the Element Browser window.
22 */
23 class BrowseLinks extends \TYPO3\CMS\Recordlist\Browser\ElementBrowser {
24
25 public $editorNo;
26 /**
27 * TYPO3 language code of the content language
28 */
29 public $contentTypo3Language;
30
31 public $contentTypo3Charset = 'utf-8';
32 /**
33 * Language service object for localization to the content language
34 */
35 protected $contentLanguageService;
36
37 public $additionalAttributes = array();
38
39 public $buttonConfig = array();
40
41 public $RTEProperties = array();
42
43 public $anchorTypes = array('page', 'url', 'file', 'mail');
44
45 public $classesAnchorDefault = array();
46
47 public $classesAnchorDefaultTitle = array();
48
49 public $classesAnchorClassTitle = array();
50
51 public $classesAnchorDefaultTarget = array();
52
53 public $classesAnchorJSOptions = array();
54
55 protected $defaultLinkTarget;
56
57 public $allowedItems;
58
59 /**
60 * Constructor:
61 * Initializes a lot of variables, setting JavaScript functions in header etc.
62 *
63 * @return void
64 */
65 public function init() {
66 $this->initVariables();
67 // Create content language service
68 $this->contentLanguageService = GeneralUtility::makeInstance(\TYPO3\CMS\Lang\LanguageService::class);
69 $this->contentLanguageService->init($this->contentTypo3Language);
70 $this->initConfiguration();
71
72 $this->initDocumentTemplate();
73
74 // Initializing hooking browsers
75 $this->initHookObjects('ext/rtehtmlarea/mod3/class.tx_rtehtmlarea_browse_links.php');
76 $this->allowedItems = $this->getAllowedItems('page,file,folder,url,mail');
77 $this->initCurrentUrl();
78 // Determine nature of current url:
79 $this->act = GeneralUtility::_GP('act');
80 if (!$this->act) {
81 $this->act = $this->curUrlInfo['act'];
82 }
83 // Setting initial values for link attributes
84 $this->initLinkAttributes();
85
86 // Adding RTE JS code
87 // also unset the default jumpToUrl() function before
88 unset($this->doc->JScodeArray['jumpToUrl']);
89 $this->doc->JScodeArray['rtehtmlarea'] = $this->getJSCode();
90 }
91
92 /**
93 * Initialize class variables
94 *
95 * @return void
96 */
97 public function initVariables() {
98 parent::initVariables();
99
100 // Process bparams
101 $pArr = explode('|', $this->bparams);
102 $pRteArr = explode(':', $pArr[1]);
103 $this->editorNo = $pRteArr[0];
104 $this->contentTypo3Language = $pRteArr[1];
105 $this->RTEtsConfigParams = $pArr[2];
106 if (!$this->editorNo) {
107 $this->editorNo = GeneralUtility::_GP('editorNo');
108 $this->contentTypo3Language = GeneralUtility::_GP('contentTypo3Language');
109 $this->RTEtsConfigParams = GeneralUtility::_GP('RTEtsConfigParams');
110 }
111 $pArr[1] = implode(':', array($this->editorNo, $this->contentTypo3Language, $this->contentTypo3Charset));
112 $pArr[2] = $this->RTEtsConfigParams;
113 $this->bparams = implode('|', $pArr);
114 }
115
116 /**
117 * Initializes the configuration variables
118 *
119 * @return void
120 */
121 public function initConfiguration() {
122 $this->thisConfig = $this->getRTEConfig();
123 $this->buttonConfig = $this->getButtonConfig('link');
124 }
125
126 /**
127 * Initialize document template object
128 *
129 * @return void
130 */
131 protected function initDocumentTemplate() {
132 parent::initDocumentTemplate();
133 $this->doc->getContextMenuCode();
134 // Apply the same styles as those of the base script
135 $this->doc->bodyTagId = 'typo3-browse-links-php';
136 $this->getPageRenderer()->addCssFile($this->doc->backPath . \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath('t3skin') . 'rtehtmlarea/htmlarea.css');
137 // Add attributes to body tag. Note: getBodyTagAdditions will invoke the hooks
138 $this->doc->bodyTagAdditions = $this->getBodyTagAdditions();
139 $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/LegacyTree', 'function(Tree) {
140 Tree.ajaxID = "SC_alt_file_navframe::expandCollapse";
141 }');
142 }
143
144 /**
145 * Initialize $this->curUrlArray and $this->curUrlInfo based on script parameters
146 *
147 * @return void
148 */
149 protected function initCurrentUrl() {
150 // CurrentUrl - the current link url must be passed around if it exists
151 $this->curUrlArray = GeneralUtility::_GP('curUrl');
152 if ($this->curUrlArray['all']) {
153 $this->curUrlArray = GeneralUtility::get_tag_attributes($this->curUrlArray['all']);
154 $this->curUrlArray['href'] = htmlspecialchars_decode($this->curUrlArray['href']);
155 }
156 // Note: parseCurUrl will invoke the hooks
157 $this->curUrlInfo = $this->parseCurUrl($this->curUrlArray['href'], $this->siteURL);
158 if (isset($this->curUrlArray['data-htmlarea-external']) && $this->curUrlArray['data-htmlarea-external'] === '1' && $this->curUrlInfo['act'] != 'mail') {
159 $this->curUrlInfo['act'] = 'url';
160 $this->curUrlInfo['info'] = $this->curUrlArray['href'];
161 }
162 }
163
164 /**
165 * Get the RTE configuration from Page TSConfig
166 *
167 * @return array RTE configuration array
168 */
169 protected function getRTEConfig() {
170 $RTEtsConfigParts = explode(':', $this->RTEtsConfigParams);
171 $RTEsetup = $GLOBALS['BE_USER']->getTSConfig('RTE', BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
172 $this->RTEProperties = $RTEsetup['properties'];
173 return BackendUtility::RTEsetup($this->RTEProperties, $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
174 }
175
176 /**
177 * Get the configuration of the button
178 *
179 * @param string $buttonName: the name of the button
180 * @return array the configuration array of the image button
181 */
182 protected function getButtonConfig($buttonName) {
183 return is_array($this->thisConfig['buttons.']) && is_array($this->thisConfig['buttons.'][$buttonName . '.'])
184 ? $this->thisConfig['buttons.'][$buttonName . '.']
185 : array();
186 }
187
188 /**
189 * Initialize the current or default values of the link attributes
190 *
191 * @return void
192 */
193 protected function initLinkAttributes() {
194 // Initializing the class value
195 $this->setClass = isset($this->curUrlArray['class']) ? $this->curUrlArray['class'] : '';
196 // Processing the classes configuration
197 $classSelected = array();
198 if ($this->buttonConfig['properties.']['class.']['allowedClasses']) {
199 $classesAnchorArray = GeneralUtility::trimExplode(',', $this->buttonConfig['properties.']['class.']['allowedClasses'], TRUE);
200 // Collecting allowed classes and configured default values
201 $classesAnchor = array();
202 $classesAnchor['all'] = array();
203 $titleReadOnly = $this->buttonConfig['properties.']['title.']['readOnly']
204 || $this->buttonConfig[$this->act . '.']['properties.']['title.']['readOnly'];
205 if (is_array($this->RTEProperties['classesAnchor.'])) {
206 foreach ($this->RTEProperties['classesAnchor.'] as $label => $conf) {
207 if (in_array($conf['class'], $classesAnchorArray)) {
208 $classesAnchor['all'][] = $conf['class'];
209 if (in_array($conf['type'], $this->anchorTypes)) {
210 $classesAnchor[$conf['type']][] = $conf['class'];
211 if ($this->buttonConfig[$conf['type'] . '.']['properties.']['class.']['default'] == $conf['class']) {
212 $this->classesAnchorDefault[$conf['type']] = $conf['class'];
213 if ($conf['titleText']) {
214 $this->classesAnchorDefaultTitle[$conf['type']] = $this->getLLContent(trim($conf['titleText']));
215 }
216 if (isset($conf['target'])) {
217 $this->classesAnchorDefaultTarget[$conf['type']] = trim($conf['target']);
218 }
219 }
220 }
221 if ($titleReadOnly && $conf['titleText']) {
222 $this->classesAnchorClassTitle[$conf['class']] = ($this->classesAnchorDefaultTitle[$conf['type']] = $this->getLLContent(trim($conf['titleText'])));
223 }
224 }
225 }
226 }
227 // Constructing the class selector options
228 foreach ($this->anchorTypes as $anchorType) {
229 $currentClass = $this->curUrlInfo['act'] === $anchorType ? $this->curUrlArray['class'] : '';
230 foreach ($classesAnchorArray as $class) {
231 if (!in_array($class, $classesAnchor['all']) || in_array($class, $classesAnchor['all']) && is_array($classesAnchor[$anchorType]) && in_array($class, $classesAnchor[$anchorType])) {
232 $selected = '';
233 if ($currentClass == $class || !$currentClass && $this->classesAnchorDefault[$anchorType] == $class) {
234 $selected = 'selected="selected"';
235 $classSelected[$anchorType] = TRUE;
236 }
237 $classLabel = is_array($this->RTEProperties['classes.']) && is_array($this->RTEProperties['classes.'][$class . '.']) && $this->RTEProperties['classes.'][$class . '.']['name'] ? $this->getPageConfigLabel($this->RTEProperties['classes.'][$class . '.']['name'], 0) : $class;
238 $classStyle = is_array($this->RTEProperties['classes.']) && is_array($this->RTEProperties['classes.'][$class . '.']) && $this->RTEProperties['classes.'][$class . '.']['value'] ? $this->RTEProperties['classes.'][$class . '.']['value'] : '';
239 $this->classesAnchorJSOptions[$anchorType] .= '<option ' . $selected . ' value="' . $class . '"' . ($classStyle ? ' style="' . $classStyle . '"' : '') . '>' . $classLabel . '</option>';
240 }
241 }
242 if ($this->classesAnchorJSOptions[$anchorType] && !($this->buttonConfig['properties.']['class.']['required'] || $this->buttonConfig[$this->act . '.']['properties.']['class.']['required'])) {
243 $selected = '';
244 if (!$this->setClass && !$this->classesAnchorDefault[$anchorType]) {
245 $selected = 'selected="selected"';
246 }
247 $this->classesAnchorJSOptions[$anchorType] = '<option ' . $selected . ' value=""></option>' . $this->classesAnchorJSOptions[$anchorType];
248 }
249 }
250 }
251 // Initializing the title value
252 $this->setTitle = isset($this->curUrlArray['title']) ? $this->curUrlArray['title'] : '';
253 // Initializing the target value
254 $this->setTarget = isset($this->curUrlArray['target']) ? $this->curUrlArray['target'] : '';
255 // Default target
256 $this->defaultLinkTarget = $this->classesAnchorDefault[$this->act] && $this->classesAnchorDefaultTarget[$this->act]
257 ? $this->classesAnchorDefaultTarget[$this->act]
258 : (isset($this->buttonConfig[$this->act . '.']['properties.']['target.']['default'])
259 ? $this->buttonConfig[$this->act . '.']['properties.']['target.']['default']
260 : (isset($this->buttonConfig['properties.']['target.']['default'])
261 ? $this->buttonConfig['properties.']['target.']['default']
262 : ''));
263 // Initializing additional attributes
264 if ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins']['TYPO3Link']['additionalAttributes']) {
265 $addAttributes = GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins']['TYPO3Link']['additionalAttributes'], TRUE);
266 foreach ($addAttributes as $attribute) {
267 $this->additionalAttributes[$attribute] = isset($this->curUrlArray[$attribute]) ? $this->curUrlArray[$attribute] : '';
268 }
269 }
270 }
271
272 /**
273 * Provide the additional parameters to be included in the template body tag
274 *
275 * @return string the body tag additions
276 */
277 public function getBodyTagAdditions() {
278 $bodyTagAdditions = array();
279 // call hook for extra additions
280 foreach ($this->hookObjects as $hookObject) {
281 if (method_exists($hookObject, 'addBodyTagAdditions')) {
282 $bodyTagAdditions = $hookObject->addBodyTagAdditions($bodyTagAdditions);
283 }
284 }
285 return GeneralUtility::implodeAttributes($bodyTagAdditions, TRUE);
286 }
287
288 /**
289 * Generate JS code to be used on the link insert/modify dialogue
290 *
291 * @return string the generated JS code
292 */
293 public function getJSCode() {
294 // BEGIN accumulation of header JavaScript:
295 $JScode = '';
296 $JScode .= '
297 var plugin = window.parent.RTEarea["' . $this->editorNo . '"].editor.getPlugin("TYPO3Link");
298 var HTMLArea = window.parent.HTMLArea;
299 var add_href=' . GeneralUtility::quoteJSvalue($this->curUrlArray['href'] ? '&curUrl[href]=' . rawurlencode($this->curUrlArray['href']) : '') . ';
300 var add_target=' . GeneralUtility::quoteJSvalue($this->setTarget ? '&curUrl[target]=' . rawurlencode($this->setTarget) : '') . ';
301 var add_class=' . GeneralUtility::quoteJSvalue($this->setClass ? '&curUrl[class]=' . rawurlencode($this->setClass) : '') . ';
302 var add_title=' . GeneralUtility::quoteJSvalue($this->setTitle ? '&curUrl[title]=' . rawurlencode($this->setTitle) : '') . ';
303 var add_params=' . GeneralUtility::quoteJSvalue($this->bparams ? '&bparams=' . rawurlencode($this->bparams) : '') . ';
304 var additionalValues = ' . (!empty($this->additionalAttributes) ? json_encode($this->additionalAttributes, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) : '{}') . ';';
305 // Attributes setting functions
306 $JScode .= '
307 var cur_href=' . GeneralUtility::quoteJSvalue($this->curUrlArray['href'] ? ($this->curUrlInfo['query'] ? substr($this->curUrlArray['href'], 0, -strlen($this->curUrlInfo['query'])) : $this->curUrlArray['href']) : '') . ';
308 var cur_target=' . GeneralUtility::quoteJSvalue($this->setTarget ?: '') . ';
309 var cur_class=' . GeneralUtility::quoteJSvalue($this->setClass ?: '') . ';
310 var cur_title=' . GeneralUtility::quoteJSvalue($this->setTitle ?: '') . ';
311
312 function browse_links_setTarget(value) {
313 cur_target=value;
314 add_target="&curUrl[target]="+encodeURIComponent(value);
315 }
316 function browse_links_setClass(value) {
317 cur_class=value;
318 add_class="&curUrl[class]="+encodeURIComponent(value);
319 }
320 function browse_links_setTitle(value) {
321 cur_title=value;
322 add_title="&curUrl[title]="+encodeURIComponent(value);
323 }
324 function browse_links_setHref(value) {
325 cur_href=value;
326 add_href="&curUrl[href]="+value;
327 }
328 function browse_links_setAdditionalValue(name, value) {
329 additionalValues[name] = value;
330 }
331 ';
332 // Link setting functions
333 $JScode .= '
334 function link_typo3Page(id,anchor) {
335 var parameters = (document.ltargetform.query_parameters && document.ltargetform.query_parameters.value) ? (document.ltargetform.query_parameters.value.charAt(0) == "&" ? "" : "&") + document.ltargetform.query_parameters.value : "";
336 var theLink = \'' . $this->siteURL . '?id=\' + id + parameters + (anchor ? anchor : "");
337 if (document.ltargetform.anchor_title) browse_links_setTitle(document.ltargetform.anchor_title.value);
338 if (document.ltargetform.anchor_class) browse_links_setClass(document.ltargetform.anchor_class.value);
339 if (document.ltargetform.ltarget) browse_links_setTarget(document.ltargetform.ltarget.value);
340 if (document.ltargetform.lrel) browse_links_setAdditionalValue("rel", document.ltargetform.lrel.value);
341 browse_links_setAdditionalValue("data-htmlarea-external", "");
342 plugin.createLink(theLink,cur_target,cur_class,cur_title,additionalValues);
343 return false;
344 }
345 function link_folder(folder) {
346 if (folder && folder.substr(0, 5) == "file:") {
347 var theLink = \'' . $this->siteURL . '?file:\' + encodeURIComponent(folder.substr(5));
348 } else {
349 var theLink = \'' . $this->siteURL . '?\' + folder;
350 }
351 if (document.ltargetform.anchor_title) browse_links_setTitle(document.ltargetform.anchor_title.value);
352 if (document.ltargetform.anchor_class) browse_links_setClass(document.ltargetform.anchor_class.value);
353 if (document.ltargetform.ltarget) browse_links_setTarget(document.ltargetform.ltarget.value);
354 if (document.ltargetform.lrel) browse_links_setAdditionalValue("rel", document.ltargetform.lrel.value);
355 browse_links_setAdditionalValue("data-htmlarea-external", "");
356 plugin.createLink(theLink,cur_target,cur_class,cur_title,additionalValues);
357 return false;
358 }
359 function link_current() {
360 var parameters = (document.ltargetform.query_parameters && document.ltargetform.query_parameters.value) ? (document.ltargetform.query_parameters.value.charAt(0) == "&" ? "" : "&") + document.ltargetform.query_parameters.value : "";
361 if (document.ltargetform.anchor_title) browse_links_setTitle(document.ltargetform.anchor_title.value);
362 if (document.ltargetform.anchor_class) browse_links_setClass(document.ltargetform.anchor_class.value);
363 if (document.ltargetform.ltarget) browse_links_setTarget(document.ltargetform.ltarget.value);
364 if (document.ltargetform.lrel) browse_links_setAdditionalValue("rel", document.ltargetform.lrel.value);
365 if (cur_href!="http://" && cur_href!="mailto:") {
366 plugin.createLink(cur_href + parameters,cur_target,cur_class,cur_title,additionalValues);
367 }
368 return false;
369 }
370 ';
371 // General "jumpToUrl" and launchView functions:
372 $JScode .= '
373 function jumpToUrl(URL,anchor) {
374 if (URL.charAt(0) === \'?\') {
375 URL = ' . GeneralUtility::quoteJSvalue($this->getThisScript()) . ' + URL.substring(1);
376 }
377 var add_editorNo = URL.indexOf("editorNo=")==-1 ? "&editorNo=' . $this->editorNo . '" : "";
378 var add_contentTypo3Language = URL.indexOf("contentTypo3Language=")==-1 ? "&contentTypo3Language=' . $this->contentTypo3Language . '" : "";
379 var add_act = URL.indexOf("act=")==-1 ? "&act=' . $this->act . '" : "";
380 var add_mode = URL.indexOf("mode=")==-1 ? "&mode=' . $this->mode . '" : "";
381 var add_additionalValues = "";
382 if (plugin.pageTSConfiguration && plugin.pageTSConfiguration.additionalAttributes) {
383 var additionalAttributes = plugin.pageTSConfiguration.additionalAttributes.split(",");
384 for (var i = additionalAttributes.length; --i >= 0;) {
385 if (additionalValues[additionalAttributes[i]] != "") {
386 add_additionalValues += "&curUrl[" + additionalAttributes[i] + "]=" + encodeURIComponent(additionalValues[additionalAttributes[i]]);
387 }
388 }
389 }
390 var theLocation = URL+add_act+add_editorNo+add_contentTypo3Language+add_mode+add_href+add_target+add_class+add_title+add_additionalValues+add_params+(anchor?anchor:"");
391 window.location.href = theLocation;
392 return false;
393 }
394 function launchView(url) {
395 var thePreviewWindow="";
396 thePreviewWindow = window.open(' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('show_item') . '&table=') . '+url,"ShowItem","height=300,width=410,status=0,menubar=0,resizable=0,location=0,directories=0,scrollbars=1,toolbar=0");
397 if (thePreviewWindow && thePreviewWindow.focus) {
398 thePreviewWindow.focus();
399 }
400 }
401 ';
402 // Hook to overwrite or extend javascript functions
403 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/rtehtmlarea/mod3/class.tx_rtehtmlarea_browse_links.php']['extendJScode']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/rtehtmlarea/mod3/class.tx_rtehtmlarea_browse_links.php']['extendJScode'])) {
404 $conf = array();
405 $_params = array(
406 'conf' => &$conf
407 );
408 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/rtehtmlarea/mod3/class.tx_rtehtmlarea_browse_links.php']['extendJScode'] as $objRef) {
409 $processor =& GeneralUtility::getUserObj($objRef);
410 $JScode .= $processor->extendJScode($_params, $this);
411 }
412 }
413 return $JScode;
414 }
415
416 /******************************************************************
417 *
418 * Main functions
419 *
420 ******************************************************************/
421 /**
422 * Rich Text Editor (RTE) link selector (MAIN function)
423 * Generates the link selector for the Rich Text Editor.
424 * Can also be used to select links for the TCEforms (see $wiz)
425 *
426 * @param bool $wiz If set, the "remove link" is not shown in the menu: Used for the "Select link" wizard which is used by the TCEforms
427 * @return string Modified content variable.
428 */
429 public function main_rte($wiz = FALSE) {
430 // Starting content:
431 $content = $this->doc->startPage($GLOBALS['LANG']->getLL('Insert/Modify Link', TRUE));
432 // Making menu in top:
433 $content .= $this->doc->getTabMenuRaw($this->buildMenuArray($wiz, $this->allowedItems));
434 // Adding the menu and header to the top of page:
435 $content .= $this->printCurrentUrl($this->curUrlInfo['info']) . '<br />';
436 // Depending on the current action we will create the actual module content for selecting a link:
437 switch ($this->act) {
438 case 'mail':
439 $extUrl = $this->getEmailSelectorHtml();
440 $content .= $this->addAttributesForm($extUrl);
441 break;
442 case 'url':
443 $extUrl = $this->getExternalUrlSelectorHtml();
444 $content .= $this->addAttributesForm($extUrl);
445 break;
446 case 'file':
447 case 'folder':
448 $content .= $this->addAttributesForm();
449 $content .= $this->getFileSelectorHtml(\TYPO3\CMS\Rtehtmlarea\FolderTree::class);
450 break;
451 case 'page':
452 $content .= $this->addAttributesForm();
453 $content .= $this->getPageSelectorHtml(\TYPO3\CMS\Rtehtmlarea\PageTree::class);
454 break;
455 default:
456 // call hook
457 foreach ($this->hookObjects as $hookObject) {
458 $content .= $hookObject->getTab($this->act);
459 }
460 }
461 // End page, return content:
462 $content .= $this->doc->endPage();
463 $content = $this->doc->insertStylesAndJS($content);
464 return $content;
465 }
466
467 /**
468 * Returns an array definition of the top menu
469 *
470 * @param $wiz
471 * @param $allowedItems
472 * @return array
473 */
474 protected function buildMenuArray($wiz, $allowedItems) {
475 $menuDef = array();
476 if (!$wiz && $this->curUrlArray['href']) {
477 $menuDef['removeLink']['isActive'] = $this->act == 'removeLink';
478 $menuDef['removeLink']['label'] = $GLOBALS['LANG']->getLL('removeLink', TRUE);
479 $menuDef['removeLink']['url'] = '#';
480 $menuDef['removeLink']['addParams'] = 'onclick="plugin.unLink();return false;"';
481 }
482 if (in_array('page', $this->allowedItems)) {
483 $menuDef['page']['isActive'] = $this->act == 'page';
484 $menuDef['page']['label'] = $GLOBALS['LANG']->getLL('page', TRUE);
485 $menuDef['page']['url'] = '#';
486 $menuDef['page']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=page&mode=' . $this->mode . '&bparams=' . $this->bparams) . ');return false;"';
487 }
488 if (in_array('file', $this->allowedItems)) {
489 $menuDef['file']['isActive'] = $this->act == 'file';
490 $menuDef['file']['label'] = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_browse_links.xlf:file', TRUE);
491 $menuDef['file']['url'] = '#';
492 $menuDef['file']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=file&mode=' . $this->mode . '&bparams=' . $this->bparams) . ');return false;"';
493 }
494 if (in_array('folder', $this->allowedItems)) {
495 $menuDef['folder']['isActive'] = $this->act == 'folder';
496 $menuDef['folder']['label'] = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_browse_links.xlf:folder', TRUE);
497 $menuDef['folder']['url'] = '#';
498 $menuDef['folder']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=folder&mode=' . $this->mode . '&bparams=' . $this->bparams) . ');return false;"';
499 }
500 if (in_array('url', $this->allowedItems)) {
501 $menuDef['url']['isActive'] = $this->act == 'url';
502 $menuDef['url']['label'] = $GLOBALS['LANG']->getLL('extUrl', TRUE);
503 $menuDef['url']['url'] = '#';
504 $menuDef['url']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=url&mode=' . $this->mode . '&bparams=' . $this->bparams) . ');return false;"';
505 }
506 if (in_array('mail', $this->allowedItems)) {
507 $menuDef['mail']['isActive'] = $this->act == 'mail';
508 $menuDef['mail']['label'] = $GLOBALS['LANG']->getLL('email', TRUE);
509 $menuDef['mail']['url'] = '#';
510 $menuDef['mail']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=mail&mode=' . $this->mode . '&bparams=' . $this->bparams) . ');return false;"';
511 }
512 // call hook for extra options
513 foreach ($this->hookObjects as $hookObject) {
514 $menuDef = $hookObject->modifyMenuDefinition($menuDef);
515 }
516 return $menuDef;
517 }
518
519 /**
520 * Returns HTML of the email link from
521 *
522 * @return string
523 */
524 protected function getEmailSelectorHtml() {
525 $extUrl = '
526 <!--
527 Enter mail address:
528 -->
529 <tr>
530 <td>
531 <label>
532 ' . $GLOBALS['LANG']->getLL('emailAddress', TRUE) . ':
533 </label>
534 </td>
535 <td>
536 <input type="text" name="lemail"' . $this->doc->formWidth(20)
537 . ' value="' . htmlspecialchars(($this->curUrlInfo['act'] == 'mail' ? $this->curUrlInfo['info'] : '')) . '" />
538 <input class="btn btn-default" type="submit" value="' . $GLOBALS['LANG']->getLL('setLink', TRUE)
539 . '" onclick="browse_links_setTarget(\'\');browse_links_setHref(\'mailto:\'+document.ltargetform.lemail.value);'
540 . 'browse_links_setAdditionalValue(\'data-htmlarea-external\', \'\');return link_current();" />
541 </td>
542 </tr>';
543 return $extUrl;
544 }
545
546 /**
547 * Returns HTML of the external url link from
548 *
549 * @return string
550 */
551 protected function getExternalUrlSelectorHtml() {
552 $extUrl = '
553 <!--
554 Enter External URL:
555 -->
556 <tr>
557 <td>
558 <label>
559 URL:
560 </label>
561 </td>
562 <td colspan="3">
563 <input type="text" name="lurl"' . $this->doc->formWidth(20)
564 . ' value="' . htmlspecialchars(($this->curUrlInfo['act'] == 'url' ? $this->curUrlInfo['info'] : 'http://'))
565 . '" />
566 <input class="btn btn-default" type="submit" value="' . $GLOBALS['LANG']->getLL('setLink', TRUE)
567 . '" onclick="if (/^[A-Za-z0-9_+]{1,8}:/.test(document.ltargetform.lurl.value)) { '
568 . ' browse_links_setHref(document.ltargetform.lurl.value); } else { browse_links_setHref(\'http://\''
569 . '+document.ltargetform.lurl.value); }; browse_links_setAdditionalValue(\'data-htmlarea-external\', \'1\');'
570 . 'return link_current();" />
571 </td>
572 </tr>';
573 return $extUrl;
574 }
575
576 /**
577 * Get the allowed items or tabs
578 *
579 * @param string $items: initial list of possible items
580 * @return array the allowed items
581 */
582 public function getAllowedItems($items) {
583 $allowedItems = explode(',', $items);
584 // Calling hook for extra options
585 foreach ($this->hookObjects as $hookObject) {
586 $allowedItems = $hookObject->addAllowedItems($allowedItems);
587 }
588 // Removing items as per configuration
589 if (is_array($this->buttonConfig['options.']) && $this->buttonConfig['options.']['removeItems']) {
590 $allowedItems = array_diff($allowedItems, GeneralUtility::trimExplode(',', $this->buttonConfig['options.']['removeItems'], TRUE));
591 }
592 reset($allowedItems);
593 if (!in_array($this->act, $allowedItems)) {
594 $this->act = current($allowedItems);
595 }
596 return $allowedItems;
597 }
598
599 /**
600 * Creates a form for link attributes
601 *
602 * @param string $rows: html code for some initial rows of the table to be wrapped in form
603 * @return string The HTML code of the form
604 */
605 public function addAttributesForm($rows = '') {
606 $ltargetForm = '';
607 $additionalAttributeFields = '';
608 // Add page id, target, class selector box, title and parameters fields:
609 $lpageId = $this->addPageIdSelector();
610 $queryParameters = $this->addQueryParametersSelector();
611 $ltarget = $this->addTargetSelector();
612 $lclass = $this->addClassSelector();
613 $ltitle = $this->addTitleSelector();
614 $rel = $this->addRelField();
615 // additional fields for links
616 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/rtehtmlarea/mod3/class.tx_rtehtmlarea_browse_links.php']['addAttributeFields'])
617 && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/rtehtmlarea/mod3/class.tx_rtehtmlarea_browse_links.php']['addAttributeFields'])
618 ) {
619 $conf = array();
620 $_params = array(
621 'conf' => &$conf
622 );
623 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/rtehtmlarea/mod3/class.tx_rtehtmlarea_browse_links.php']['addAttributeFields'] as $objRef) {
624 $processor =& GeneralUtility::getUserObj($objRef);
625 $additionalAttributeFields .= $processor->getAttributefields($_params, $this);
626 }
627 }
628 if ($rows || $lpageId || $queryParameters || $lclass || $ltitle || $ltarget || $rel) {
629 $ltargetForm = $this->wrapInForm($rows . $lpageId . $queryParameters . $lclass . $ltitle . $ltarget . $rel . $additionalAttributeFields);
630 }
631 return $ltargetForm;
632 }
633
634 /**
635 * Wrap in form
636 *
637 * @param string $string
638 * @return string
639 */
640 public function wrapInForm($string) {
641 $form = '
642 <!--
643 Selecting target for link:
644 -->
645 <form action="" name="ltargetform" id="ltargetform">
646 <table id="typo3-linkTarget" class="htmlarea-window-table">' . $string;
647 if ($this->act == $this->curUrlInfo['act'] && $this->act != 'mail' && $this->curUrlArray['href']) {
648 $form .= '
649 <tr>
650 <td>
651 </td>
652 <td colspan="3">
653 <input class="btn btn-default" type="submit" value="' . $GLOBALS['LANG']->getLL('update', TRUE) . '" onclick="'
654 . ($this->act == 'url' ? 'browse_links_setAdditionalValue(\'data-htmlarea-external\', \'1\'); ' : '')
655 . 'return link_current();" />
656 </td>
657 </tr>';
658 }
659 $form .= '
660 </table>
661 </form>';
662 return $form;
663 }
664
665 /**
666 * Add page id selector
667 *
668 * @return string
669 */
670 public function addPageIdSelector() {
671 if ($this->act == 'page' && isset($this->buttonConfig['pageIdSelector.']['enabled'])
672 && $this->buttonConfig['pageIdSelector.']['enabled']
673 ) {
674 return '
675 <tr>
676 <td>
677 <label>
678 ' . $GLOBALS['LANG']->getLL('page_id', TRUE) . ':
679 </label>
680 </td>
681 <td colspan="3">
682 <input type="text" size="6" name="luid" /> <input class="btn btn-default" type="submit" value="'
683 . $GLOBALS['LANG']->getLL('setLink', TRUE) . '" onclick="return link_typo3Page(document.ltargetform.luid.value);" />
684 </td>
685 </tr>';
686 }
687 return '';
688 }
689
690 /**
691 * Add rel field
692 *
693 * @return string
694 */
695 public function addRelField() {
696 // Unset rel attribute if we changed tab
697 $currentRel = $this->curUrlInfo['act'] === $this->act && isset($this->curUrlArray['rel']) ? $this->curUrlArray['rel'] : '';
698 if (($this->act == 'page' || $this->act == 'url' || $this->act == 'file')
699 && isset($this->buttonConfig['relAttribute.']['enabled']) && $this->buttonConfig['relAttribute.']['enabled']
700 ) {
701 return '
702 <tr>
703 <td><label>' . $GLOBALS['LANG']->getLL('linkRelationship', TRUE) . ':</label></td>
704 <td colspan="3">
705 <input type="text" name="lrel" value="' . $currentRel . '" '
706 . $this->doc->formWidth(30) . ' />
707 </td>
708 </tr>';
709 }
710 return '';
711 }
712
713 /**
714 * Add query parameter selector
715 *
716 * @return string
717 */
718 public function addQueryParametersSelector() {
719 if ($this->act == 'page' && isset($this->buttonConfig['queryParametersSelector.']['enabled'])
720 && $this->buttonConfig['queryParametersSelector.']['enabled']
721 ) {
722 return '
723 <tr>
724 <td><label>' . $GLOBALS['LANG']->getLL('query_parameters', TRUE) . ':</label></td>
725 <td colspan="3">
726 <input type="text" name="query_parameters" value="' . ($this->curUrlInfo['query'] ?: '')
727 . '" ' . $this->doc->formWidth(30) . ' />
728 </td>
729 </tr>';
730 }
731 return '';
732 }
733
734 /**
735 * Add target selector
736 *
737 * @return string
738 */
739 public function addTargetSelector() {
740 if ($this->act === 'mail') {
741 return '';
742 }
743 $targetSelectorConfig = array();
744 $popupSelectorConfig = array();
745 if (is_array($this->buttonConfig['targetSelector.'])) {
746 $targetSelectorConfig = $this->buttonConfig['targetSelector.'];
747 }
748 if (is_array($this->buttonConfig['popupSelector.'])) {
749 $popupSelectorConfig = $this->buttonConfig['popupSelector.'];
750 }
751 // Reset the target to default if we changed tab
752 $currentTarget = $this->curUrlInfo['act'] === $this->act && isset($this->curUrlArray['target']) ? $this->curUrlArray['target'] : '';
753 $target = $currentTarget ?: $this->defaultLinkTarget;
754 $ltarget = '
755 <tr id="ltargetrow"' . ($targetSelectorConfig['disabled'] && $popupSelectorConfig['disabled'] ? ' style="display: none;"' : '') . '>
756 <td><label>' . $GLOBALS['LANG']->getLL('target', TRUE) . ':</label></td>
757 <td><input type="text" name="ltarget" onchange="browse_links_setTarget(this.value);" value="'
758 . htmlspecialchars($target) . '"' . $this->doc->formWidth(10) . ' /></td>';
759 $ltarget .= '
760 <td colspan="2">';
761 if (!$targetSelectorConfig['disabled']) {
762 $ltarget .= '
763 <select name="ltarget_type" onchange="browse_links_setTarget(this.options[this.selectedIndex].value);document.ltargetform.ltarget.value=this.options[this.selectedIndex].value;this.selectedIndex=0;">
764 <option></option>
765 <option value="_top">' . $GLOBALS['LANG']->getLL('top', TRUE) . '</option>
766 <option value="_blank">' . $GLOBALS['LANG']->getLL('newWindow', TRUE) . '</option>
767 </select>';
768 }
769 $ltarget .= '
770 </td>
771 </tr>';
772 if (!$popupSelectorConfig['disabled']) {
773 $selectJS = 'if (document.ltargetform.popup_width.options[document.ltargetform.popup_width.selectedIndex].value>0 && document.ltargetform.popup_height.options[document.ltargetform.popup_height.selectedIndex].value>0) {
774 document.ltargetform.ltarget.value = document.ltargetform.popup_width.options[document.ltargetform.popup_width.selectedIndex].value+\'x\'+document.ltargetform.popup_height.options[document.ltargetform.popup_height.selectedIndex].value;
775 browse_links_setTarget(document.ltargetform.ltarget.value);
776 document.ltargetform.popup_width.selectedIndex=0;
777 document.ltargetform.popup_height.selectedIndex=0;
778 }';
779 $ltarget .= '
780 <tr>
781 <td><label>' . $GLOBALS['LANG']->getLL('target_popUpWindow', TRUE) . ':</label></td>
782 <td colspan="3">
783 <select name="popup_width" onchange="' . $selectJS . '">
784 <option value="0">' . $GLOBALS['LANG']->getLL('target_popUpWindow_width', TRUE) . '</option>
785 <option value="300">300</option>
786 <option value="400">400</option>
787 <option value="500">500</option>
788 <option value="600">600</option>
789 <option value="700">700</option>
790 <option value="800">800</option>
791 </select>
792 x
793 <select name="popup_height" onchange="' . $selectJS . '">
794 <option value="0">' . $GLOBALS['LANG']->getLL('target_popUpWindow_height', TRUE) . '</option>
795 <option value="200">200</option>
796 <option value="300">300</option>
797 <option value="400">400</option>
798 <option value="500">500</option>
799 <option value="600">600</option>
800 </select>
801 </td>
802 </tr>';
803 }
804 return $ltarget;
805 }
806
807 /**
808 * Return html code for the class selector
809 *
810 * @return string the html code to be added to the form
811 */
812 public function addClassSelector() {
813 $selectClass = '';
814 if ($this->classesAnchorJSOptions[$this->act]) {
815 $selectClass = '
816 <tr>
817 <td><label>' . $GLOBALS['LANG']->getLL('anchor_class', TRUE) . ':</label></td>
818 <td colspan="3">
819 <select name="anchor_class" onchange="' . $this->getClassOnChangeJS() . '">
820 ' . $this->classesAnchorJSOptions[$this->act] . '
821 </select>
822 </td>
823 </tr>';
824 }
825 return $selectClass;
826 }
827
828 /**
829 * Return JS code for the class selector onChange event
830 *
831 * @return string class selector onChange JS code
832 */
833 public function getClassOnChangeJS() {
834 return '
835 if (document.ltargetform.anchor_class) {
836 document.ltargetform.anchor_class.value = document.ltargetform.anchor_class.options[document.ltargetform.anchor_class.selectedIndex].value;
837 if (document.ltargetform.anchor_class.value && HTMLArea.classesAnchorSetup) {
838 for (var i = HTMLArea.classesAnchorSetup.length; --i >= 0;) {
839 var anchorClass = HTMLArea.classesAnchorSetup[i];
840 if (anchorClass[\'name\'] == document.ltargetform.anchor_class.value) {
841 if (anchorClass[\'titleText\'] && document.ltargetform.anchor_title) {
842 document.ltargetform.anchor_title.value = anchorClass[\'titleText\'];
843 document.getElementById(\'rtehtmlarea-browse-links-title-readonly\').innerHTML = anchorClass[\'titleText\'];
844 browse_links_setTitle(anchorClass[\'titleText\']);
845 }
846 if (typeof anchorClass[\'target\'] !== \'undefined\') {
847 if (document.ltargetform.ltarget) {
848 document.ltargetform.ltarget.value = anchorClass[\'target\'];
849 }
850 browse_links_setTarget(anchorClass[\'target\']);
851 } else if (document.ltargetform.ltarget && document.getElementById(\'ltargetrow\').style.display == \'none\') {
852 // Reset target to default if field is not displayed and class has no configured target
853 document.ltargetform.ltarget.value = \'' . ($this->defaultLinkTarget ?: '') . '\';
854 browse_links_setTarget(document.ltargetform.ltarget.value);
855 }
856 break;
857 }
858 }
859 }
860 browse_links_setClass(document.ltargetform.anchor_class.value);
861 }
862 ';
863 }
864
865 /**
866 * Add title selector
867 *
868 * @return string
869 */
870 public function addTitleSelector() {
871 // Reset the title to default if we changed tab
872 $currentTitle = $this->curUrlInfo['act'] === $this->act && isset($this->curUrlArray['title']) ? $this->curUrlArray['title'] : '';
873 $title = $currentTitle ?: (!$this->classesAnchorDefault[$this->act] ? '' : $this->classesAnchorDefaultTitle[$this->act]);
874 $readOnly = isset($this->buttonConfig[$this->act . '.']['properties.']['title.']['readOnly'])
875 ? $this->buttonConfig[$this->act . '.']['properties.']['title.']['readOnly']
876 : (isset($this->buttonConfig['properties.']['title.']['readOnly'])
877 ? $this->buttonConfig['properties.']['title.']['readOnly']
878 : FALSE);
879 if ($readOnly) {
880 $currentClass = $this->curUrlInfo['act'] === $this->act ? $this->curUrlArray['class'] : '';
881 if (!$currentClass) {
882 $currentClass = !$this->classesAnchorDefault[$this->act] ? '' : $this->classesAnchorDefault[$this->act];
883 }
884 $title = $currentClass
885 ? $this->classesAnchorClassTitle[$currentClass]
886 : $this->classesAnchorDefaultTitle[$this->act];
887 }
888 return '
889 <tr>
890 <td><label for="rtehtmlarea-browse-links-anchor_title" id="rtehtmlarea-browse-links-title-label">' . $GLOBALS['LANG']->getLL('anchor_title', TRUE) . ':</label></td>
891 <td colspan="3">
892 <span id="rtehtmlarea-browse-links-title-input" style="display: ' . ($readOnly ? 'none' : 'inline') . ';">
893 <input type="text" id="rtehtmlarea-browse-links-anchor_title" name="anchor_title" value="' . htmlspecialchars($title) . '" ' . $this->doc->formWidth(30) . ' />
894 </span>
895 <span id="rtehtmlarea-browse-links-title-readonly" style="display: ' . ($readOnly ? 'inline' : 'none') . ';">' . htmlspecialchars($title) . '</span>
896 </td>
897 </tr>';
898 }
899
900 /**
901 * Localize a string using the language of the content element rather than the language of the BE interface
902 *
903 * @param string string: the label to be localized
904 * @return string Localized string.
905 */
906 public function getLLContent($string) {
907 return $this->contentLanguageService->sL($string);
908 }
909
910 /**
911 * Localize a label obtained from Page TSConfig
912 *
913 * @param string $string The label to be localized
914 * @param bool $JScharCode If needs to be converted to a array of char numbers
915 * @return string Localized string
916 */
917 public function getPageConfigLabel($string, $JScharCode = TRUE) {
918 if (substr($string, 0, 4) !== 'LLL:') {
919 $label = $string;
920 } else {
921 $label = $GLOBALS['LANG']->sL(trim($string));
922 }
923 $label = str_replace('"', '\\"', str_replace('\\\'', '\'', $label));
924 return $JScharCode ? GeneralUtility::quoteJSvalue($label) : $label;
925 }
926
927 }