TYPO3 CMS  TYPO3_7-6
BrowseLinksController.php
Go to the documentation of this file.
1 <?php
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 
23 
28 {
47  protected $bparams;
48 
52  protected $editorNo;
53 
60 
67 
71  protected $buttonConfig = [];
72 
76  protected $thisConfig = [];
77 
83  protected $RTEProperties = [];
84 
91  protected $RTEtsConfigParams;
92 
96  protected $classesAnchorDefault = [];
97 
102 
106  protected $classesAnchorClassTitle = [];
107 
112 
116  protected $classesAnchorJSOptions = [];
117 
121  protected $defaultLinkTarget = '';
122 
126  protected $additionalAttributes = [];
127 
131  protected $siteUrl = '';
132 
136  protected function init()
137  {
138  parent::init();
139 
140  $lang = $this->getLanguageService();
141  $lang->includeLLFile('EXT:rtehtmlarea/Resources/Private/Language/locallang_browselinkscontroller.xlf');
142  $lang->includeLLFile('EXT:rtehtmlarea/Resources/Private/Language/locallang_dialogs.xlf');
143 
144  $this->contentLanguageService = GeneralUtility::makeInstance(LanguageService::class);
145  }
146 
150  protected function initVariables(ServerRequestInterface $request)
151  {
152  parent::initVariables($request);
153 
154  $queryParameters = $request->getQueryParams();
155  $this->bparams = isset($queryParameters['bparams']) ? $queryParameters['bparams'] : '';
156 
157  $this->siteUrl = GeneralUtility::getIndpEnv('TYPO3_SITE_URL');
158 
159  $currentLinkParts = isset($queryParameters['curUrl']) ? $queryParameters['curUrl'] : [];
160  if (isset($currentLinkParts['all'])) {
161  $currentLinkParts = GeneralUtility::get_tag_attributes($queryParameters['curUrl']['all']);
162  $currentLinkParts['url'] = htmlspecialchars_decode($currentLinkParts['href']);
163  unset($currentLinkParts['href']);
164  }
165  $this->currentLinkParts = $currentLinkParts;
166 
167  // Process bparams
168  $pArr = explode('|', $this->bparams);
169  $pRteArr = explode(':', $pArr[1]);
170  $this->editorNo = $pRteArr[0];
171  $this->contentTypo3Language = $pRteArr[1];
172  $this->RTEtsConfigParams = $pArr[2];
173  if (!$this->editorNo) {
174  $this->editorNo = GeneralUtility::_GP('editorNo');
175  $this->contentTypo3Language = GeneralUtility::_GP('contentTypo3Language');
176  $this->RTEtsConfigParams = GeneralUtility::_GP('RTEtsConfigParams');
177  }
178  $pArr[1] = implode(':', [$this->editorNo, $this->contentTypo3Language]);
179  $pArr[2] = $this->RTEtsConfigParams;
180  $this->bparams = implode('|', $pArr);
181 
182  $this->contentLanguageService->init($this->contentTypo3Language);
183 
184  $RTEtsConfigParts = explode(':', $this->RTEtsConfigParams);
185  $RTEsetup = $this->getBackendUser()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
186  $this->RTEProperties = $RTEsetup['properties'];
187 
188  $this->thisConfig = BackendUtility::RTEsetup($this->RTEProperties, $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
189  $this->buttonConfig = isset($this->thisConfig['buttons.']['link.'])
190  ? $this->thisConfig['buttons.']['link.']
191  : [];
192  }
193 
199  protected function initDocumentTemplate()
200  {
201  parent::initDocumentTemplate();
202 
203  $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
204  $pageRenderer->loadRequireJsModule('TYPO3/CMS/Rtehtmlarea/RteLinkBrowser');
205  }
206 
212  protected function initCurrentUrl()
213  {
214  if (empty($this->currentLinkParts)) {
215  return;
216  }
217 
218  if (!empty($this->currentLinkParts['class'])) {
219  // remove required classes
220  $currentClasses = GeneralUtility::trimExplode(' ', $this->currentLinkParts['class'], true);
221  if (count($currentClasses) > 1) {
222  $this->currentLinkParts['class'] = end($currentClasses);
223  }
224  }
225 
226  if (empty($this->currentLinkParts['data-htmlarea-external']) && strpos($this->currentLinkParts['url'], 'mailto:') === false) {
227  // strip siteUrl prefix except for external and mail links
228  $paramsPosition = strpos($this->currentLinkParts['url'], '?');
229  if ($paramsPosition !== false) {
230  $this->currentLinkParts['url'] = substr($this->currentLinkParts['url'], $paramsPosition + 1);
231  }
232  // special treatment for page links, remove the id= part
233  $idPosition = strpos($this->currentLinkParts['url'], 'id=');
234  if ($idPosition !== false) {
235  $this->currentLinkParts['url'] = substr($this->currentLinkParts['url'], $idPosition + 3);
236  }
237 
238  // in RTE the additional params are encoded directly at the end of the href part
239  // we need to split this again into dedicated fields
240  $additionalParamsPosition = strpos($this->currentLinkParts['url'], '?');
241  if ($additionalParamsPosition === false) {
242  $additionalParamsPosition = strpos($this->currentLinkParts['url'], '&');
243  }
244  if ($additionalParamsPosition !== false) {
245  $this->currentLinkParts['params'] = substr($this->currentLinkParts['url'], $additionalParamsPosition);
246  $this->currentLinkParts['url'] = substr($this->currentLinkParts['url'], 0, $additionalParamsPosition);
247  // in case the first sign was an ? override it with &
248  $this->currentLinkParts['params'][0] = '&';
249  }
250  }
251 
252  parent::initCurrentUrl();
253  }
254 
260  public function renderLinkAttributeFields()
261  {
262  // Processing the classes configuration
263  if (!empty($this->buttonConfig['properties.']['class.']['allowedClasses'])) {
264  $classesAnchorArray = GeneralUtility::trimExplode(',', $this->buttonConfig['properties.']['class.']['allowedClasses'], true);
265  // Collecting allowed classes and configured default values
266  $classesAnchor = [
267  'all' => []
268  ];
269  $titleReadOnly = $this->buttonConfig['properties.']['title.']['readOnly']
270  || $this->buttonConfig[$this->displayedLinkHandlerId . '.']['properties.']['title.']['readOnly'];
271  if (is_array($this->RTEProperties['classesAnchor.'])) {
272  foreach ($this->RTEProperties['classesAnchor.'] as $label => $conf) {
273  if (in_array($conf['class'], $classesAnchorArray)) {
274  $classesAnchor['all'][] = $conf['class'];
275  if ($conf['type'] === $this->displayedLinkHandlerId) {
276  $classesAnchor[$conf['type']][] = $conf['class'];
277  if ($this->buttonConfig[$conf['type'] . '.']['properties.']['class.']['default'] == $conf['class']) {
278  $this->classesAnchorDefault[$conf['type']] = $conf['class'];
279  if ($conf['titleText']) {
280  $this->classesAnchorDefaultTitle[$conf['type']] = $this->contentLanguageService->sL(trim($conf['titleText']));
281  }
282  if (isset($conf['target'])) {
283  $this->classesAnchorDefaultTarget[$conf['type']] = trim($conf['target']);
284  }
285  }
286  }
287  if ($titleReadOnly && $conf['titleText']) {
288  $this->classesAnchorClassTitle[$conf['class']] = ($this->classesAnchorDefaultTitle[$conf['type']] = $this->contentLanguageService->sL(trim($conf['titleText'])));
289  }
290  }
291  }
292  }
293  if (isset($this->linkAttributeValues['class'])
294  && isset($classesAnchor[$this->displayedLinkHandlerId])
295  && !in_array($this->linkAttributeValues['class'], $classesAnchor[$this->displayedLinkHandlerId], true)
296  ) {
297  unset($this->linkAttributeValues['class']);
298  }
299  // Constructing the class selector options
300  foreach ($classesAnchorArray as $class) {
301  if (!in_array($class, $classesAnchor['all']) || in_array($class, $classesAnchor['all']) && is_array($classesAnchor[$this->displayedLinkHandlerId]) && in_array($class, $classesAnchor[$this->displayedLinkHandlerId])) {
302  $selected = '';
303  if ($this->linkAttributeValues['class'] === $class || !$this->linkAttributeValues['class'] && $this->classesAnchorDefault[$this->displayedLinkHandlerId] == $class) {
304  $selected = 'selected="selected"';
305  }
306  $classLabel = !empty($this->RTEProperties['classes.'][$class . '.']['name'])
307  ? $this->getPageConfigLabel($this->RTEProperties['classes.'][$class . '.']['name'], 0)
308  : $class;
309  $classStyle = !empty($this->RTEProperties['classes.'][$class . '.']['value'])
310  ? $this->RTEProperties['classes.'][$class . '.']['value']
311  : '';
312  $this->classesAnchorJSOptions[$this->displayedLinkHandlerId] .= '<option ' . $selected . ' value="' . $class . '"' . ($classStyle ? ' style="' . $classStyle . '"' : '') . '>' . $classLabel . '</option>';
313  }
314  }
315  if ($this->classesAnchorJSOptions[$this->displayedLinkHandlerId] && !($this->buttonConfig['properties.']['class.']['required'] || $this->buttonConfig[$this->displayedLinkHandlerId . '.']['properties.']['class.']['required'])) {
316  $selected = '';
317  if (!$this->linkAttributeValues['class'] && !$this->classesAnchorDefault[$this->displayedLinkHandlerId]) {
318  $selected = 'selected="selected"';
319  }
320  $this->classesAnchorJSOptions[$this->displayedLinkHandlerId] = '<option ' . $selected . ' value=""></option>' . $this->classesAnchorJSOptions[$this->displayedLinkHandlerId];
321  }
322  }
323  // Default target
324  $this->defaultLinkTarget = $this->classesAnchorDefault[$this->displayedLinkHandlerId] && $this->classesAnchorDefaultTarget[$this->displayedLinkHandlerId]
325  ? $this->classesAnchorDefaultTarget[$this->displayedLinkHandlerId]
326  : (isset($this->buttonConfig[$this->displayedLinkHandlerId . '.']['properties.']['target.']['default'])
327  ? $this->buttonConfig[$this->displayedLinkHandlerId . '.']['properties.']['target.']['default']
328  : (isset($this->buttonConfig['properties.']['target.']['default'])
329  ? $this->buttonConfig['properties.']['target.']['default']
330  : ''));
331  // Initializing additional attributes
332  if ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins']['TYPO3Link']['additionalAttributes']) {
333  $addAttributes = GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins']['TYPO3Link']['additionalAttributes'], true);
334  foreach ($addAttributes as $attribute) {
335  $this->additionalAttributes[$attribute] = isset($this->linkAttributeValues[$attribute]) ? $this->linkAttributeValues[$attribute] : '';
336  }
337  }
338  return parent::renderLinkAttributeFields();
339  }
340 
348  public function getPageConfigLabel($string, $JScharCode = true)
349  {
350  if (substr($string, 0, 4) !== 'LLL:') {
351  $label = $string;
352  } else {
353  $label = $this->getLanguageService()->sL(trim($string));
354  }
355  $label = str_replace('"', '\\"', str_replace('\\\'', '\'', $label));
356  return $JScharCode ? GeneralUtility::quoteJSvalue($label) : $label;
357  }
358 
362  protected function renderCurrentUrl()
363  {
364  $removeLink = '<a href="#" class="btn btn-default t3js-removeCurrentLink">' . $this->getLanguageService()->getLL('removeLink', true) . '</a>';
365  return '
366  <table border="0" cellpadding="0" cellspacing="0" id="typo3-curUrl">
367  <tr>
368  <td>' . $this->getLanguageService()->getLL('currentLink', true) . ': ' . htmlspecialchars($this->currentLinkHandler->formatCurrentUrl()) . $removeLink . '</td>
369  </tr>
370  </table>';
371  }
372 
378  protected function getAllowedItems()
379  {
380  $allowedItems = parent::getAllowedItems();
381 
382  $blindLinkOptions = isset($this->thisConfig['blindLinkOptions'])
383  ? GeneralUtility::trimExplode(',', $this->thisConfig['blindLinkOptions'], true)
384  : [];
385  $allowedItems = array_diff($allowedItems, $blindLinkOptions);
386 
387  if (is_array($this->buttonConfig['options.']) && $this->buttonConfig['options.']['removeItems']) {
388  $allowedItems = array_diff($allowedItems, GeneralUtility::trimExplode(',', $this->buttonConfig['options.']['removeItems'], true));
389  }
390 
391  return $allowedItems;
392  }
393 
399  protected function getAllowedLinkAttributes()
400  {
401  $allowedLinkAttributes = parent::getAllowedLinkAttributes();
402 
403  $blindLinkFields = isset($this->thisConfig['blindLinkFields'])
404  ? GeneralUtility::trimExplode(',', $this->thisConfig['blindLinkFields'], true)
405  : [];
406  $allowedLinkAttributes = array_diff($allowedLinkAttributes, $blindLinkFields);
407 
408  return $allowedLinkAttributes;
409  }
410 
416  protected function getLinkAttributeFieldDefinitions()
417  {
418  $fieldRenderingDefinitions = parent::getLinkAttributeFieldDefinitions();
419  $fieldRenderingDefinitions['title'] = $this->getTitleField();
420  $fieldRenderingDefinitions['class'] = $this->getClassField();
421  $fieldRenderingDefinitions['target'] = $this->getTargetField();
422  $fieldRenderingDefinitions['rel'] = $this->getRelField();
423  if (empty($this->buttonConfig['queryParametersSelector.']['enabled'])) {
424  unset($fieldRenderingDefinitions['params']);
425  }
426  return $fieldRenderingDefinitions;
427  }
428 
434  protected function getRelField()
435  {
436  if (empty($this->buttonConfig['relAttribute.']['enabled'])) {
437  return '';
438  }
439  // @todo add rel to attributes
440  $currentRel = $this->displayedLinkHandler === $this->currentLinkHandler && !empty($this->currentLinkParts)
441  ? $this->linkAttributeValues['rel']
442  : '';
443  // @todo define label "linkRelationship" below in xlf
444  return '
445  <form action="" name="lrelform" id="lrelform" class="t3js-dummyform">
446  <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkRel">
447  <tr>
448  <td><label>' . $this->getLanguageService()->getLL('linkRelationship', true) . ':</label></td>
449  <td colspan="3"><input type="text" name="lrel" value="' . $currentRel . '" /></td>
450  </tr>
451  </table>
452  </form>
453  ';
454  }
455 
461  protected function getTargetField()
462  {
463  $targetSelectorConfig = [];
464  if (is_array($this->buttonConfig['targetSelector.'])) {
465  $targetSelectorConfig = $this->buttonConfig['targetSelector.'];
466  }
467  $target = $this->linkAttributeValues['target'] ?: $this->defaultLinkTarget;
468  $lang = $this->getLanguageService();
469  $targetSelector = '';
470 
471  if (!$targetSelectorConfig['disabled']) {
472  $targetSelector = '
473  <select name="ltarget_type" class="t3js-targetPreselect">
474  <option value=""></option>
475  <option value="_top">' . $lang->getLL('top', true) . '</option>
476  <option value="_blank">' . $lang->getLL('newWindow', true) . '</option>
477  </select>
478  ';
479  }
480 
481  return '
482  <form action="" name="ltargetform" id="ltargetform" class="t3js-dummyform">
483  <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkTarget">
484  <tr' . ($targetSelectorConfig['disabled'] ? ' style="display: none;"' : '') . '>
485  <td style="width: 96px;">' . $lang->getLL('target', true) . ':</td>
486  <td>
487  <input type="text" name="ltarget" class="t3js-linkTarget" value="' . htmlspecialchars($target) . '" />
488  ' . $targetSelector . '
489  </td>
490  </tr>
491  </table>
492  </form>
493  ';
494  }
495 
501  protected function getTitleField()
502  {
503  if ($this->linkAttributeValues['title']) {
504  $title = $this->linkAttributeValues['title'];
505  } else {
506  $title = $this->classesAnchorDefaultTitle[$this->displayedLinkHandlerId] ?: '';
507  }
508  if (isset($this->buttonConfig[$this->displayedLinkHandlerId . '.']['properties.']['title.']['readOnly'])) {
509  $readOnly = (bool)$this->buttonConfig[$this->displayedLinkHandlerId . '.']['properties.']['title.']['readOnly'];
510  } else {
511  $readOnly = isset($this->buttonConfig['properties.']['title.']['readOnly'])
512  ? (bool)$this->buttonConfig['properties.']['title.']['readOnly']
513  : false;
514  }
515 
516  if ($readOnly) {
517  $currentClass = $this->linkAttributeFields['class'];
518  if (!$currentClass) {
519  $currentClass = empty($this->classesAnchorDefault[$this->displayedLinkHandlerId]) ? '' : $this->classesAnchorDefault[$this->displayedLinkHandlerId];
520  }
521  $title = $currentClass
522  ? $this->classesAnchorClassTitle[$currentClass]
523  : $this->classesAnchorDefaultTitle[$this->displayedLinkHandlerId];
524  }
525  return '
526  <form action="" name="ltitleform" id="ltitleform" class="t3js-dummyform">
527  <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkTitle">
528  <tr>
529  <td style="width: 96px;"><label for="rtehtmlarea-browse-links-anchor_title" id="rtehtmlarea-browse-links-title-label">' . $this->getLanguageService()->getLL('anchor_title', true) . '</label></td>
530  <td>
531  <span id="rtehtmlarea-browse-links-title-input" style="display: ' . ($readOnly ? 'none' : 'inline') . ';">
532  <input type="text" id="rtehtmlarea-browse-links-anchor_title" name="ltitle" value="' . htmlspecialchars($title) . '" />
533  </span>
534  <span id="rtehtmlarea-browse-links-title-readonly" style="display: ' . ($readOnly ? 'inline' : 'none') . ';">' . htmlspecialchars($title) . '</span>
535  </td>
536  </tr>
537  </table>
538  </form>
539  ';
540  }
541 
547  protected function getClassField()
548  {
549  $selectClass = '';
550  if ($this->classesAnchorJSOptions[$this->displayedLinkHandlerId]) {
551  $selectClass = '
552  <form action="" name="lclassform" id="lclassform" class="t3js-dummyform">
553  <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkClass">
554  <tr>
555  <td style="width: 96px;">' . $this->getLanguageService()->getLL('anchor_class', true) . '</td>
556  <td><select name="lclass" class="t3js-class-selector">
557  ' . $this->classesAnchorJSOptions[$this->displayedLinkHandlerId] . '
558  </select></td>
559  </tr>
560  </table>
561  </form>
562  ';
563  }
564  return $selectClass;
565  }
566 
572  protected function getCurrentPageId()
573  {
574  return explode(':', $this->RTEtsConfigParams)[5];
575  }
576 
584  public function getConfiguration()
585  {
586  return $this->buttonConfig;
587  }
588 
594  protected function getBodyTagAttributes()
595  {
596  $parameters = parent::getBodyTagAttributes();
597  $parameters['data-site-url'] = $this->siteUrl;
598  return $parameters;
599  }
600 
606  public function getUrlParameters(array $overrides = null)
607  {
608  return [
609  'act' => isset($overrides['act']) ? $overrides['act'] : $this->displayedLinkHandlerId,
610  'bparams' => $this->bparams,
611  'editorNo' => $this->editorNo,
612  'contentTypo3Language' => $this->contentTypo3Language
613  ];
614  }
615 }
static getPagesTSconfig($id, $rootLine=null, $returnPartArray=false)
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
static RTEsetup($RTEprop, $table, $field, $type='')
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']