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