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