TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
rtehtmlarea/Classes/Controller/BrowseLinksController.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Rtehtmlarea\Controller;
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 Psr\Http\Message\ServerRequestInterface;
24 
29 {
48  protected $bparams;
49 
53  protected $editorNo;
54 
61 
68 
72  protected $buttonConfig = [];
73 
77  protected $thisConfig = [];
78 
84  protected $RTEProperties = [];
85 
92  protected $RTEtsConfigParams;
93 
97  protected $classesAnchorDefault = [];
98 
103 
107  protected $classesAnchorClassTitle = [];
108 
113 
117  protected $classesAnchorJSOptions = [];
118 
122  protected $defaultLinkTarget = '';
123 
127  protected $additionalAttributes = [];
128 
132  protected $siteUrl = '';
133 
137  protected function init()
138  {
139  parent::init();
140 
141  $lang = $this->getLanguageService();
142  $lang->includeLLFile('EXT:rtehtmlarea/Resources/Private/Language/locallang_browselinkscontroller.xlf');
143  $lang->includeLLFile('EXT:rtehtmlarea/Resources/Private/Language/locallang_dialogs.xlf');
144 
145  $this->contentLanguageService = GeneralUtility::makeInstance(LanguageService::class);
146  }
147 
151  protected function initVariables(ServerRequestInterface $request)
152  {
153  parent::initVariables($request);
154 
155  $queryParameters = $request->getQueryParams();
156  $this->bparams = isset($queryParameters['bparams']) ? $queryParameters['bparams'] : '';
157 
158  $this->siteUrl = GeneralUtility::getIndpEnv('TYPO3_SITE_URL');
159 
160  $currentLinkParts = isset($queryParameters['curUrl']) ? $queryParameters['curUrl'] : [];
161  if (isset($currentLinkParts['all'])) {
162  $currentLinkParts = GeneralUtility::get_tag_attributes($queryParameters['curUrl']['all']);
163  $currentLinkParts['url'] = htmlspecialchars_decode($currentLinkParts['href']);
164  unset($currentLinkParts['href']);
165  }
166  $this->currentLinkParts = $currentLinkParts;
167 
168  // Process bparams
169  $pArr = explode('|', $this->bparams);
170  $pRteArr = explode(':', $pArr[1]);
171  $this->editorNo = $pRteArr[0];
172  $this->contentTypo3Language = $pRteArr[1];
173  $this->RTEtsConfigParams = $pArr[2];
174  if (!$this->editorNo) {
175  $this->editorNo = GeneralUtility::_GP('editorNo');
176  $this->contentTypo3Language = GeneralUtility::_GP('contentTypo3Language');
177  $this->RTEtsConfigParams = GeneralUtility::_GP('RTEtsConfigParams');
178  }
179  $pArr[1] = implode(':', [$this->editorNo, $this->contentTypo3Language]);
180  $pArr[2] = $this->RTEtsConfigParams;
181  $this->bparams = implode('|', $pArr);
182 
183  $this->contentLanguageService->init($this->contentTypo3Language);
184 
185  $RTEtsConfigParts = explode(':', $this->RTEtsConfigParams);
186  $RTEsetup = $this->getBackendUser()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
187  $this->RTEProperties = $RTEsetup['properties'];
188 
189  $this->thisConfig = BackendUtility::RTEsetup($this->RTEProperties, $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
190  $this->buttonConfig = isset($this->thisConfig['buttons.']['link.'])
191  ? $this->thisConfig['buttons.']['link.']
192  : [];
193  }
194 
200  protected function initDocumentTemplate()
201  {
202  parent::initDocumentTemplate();
203 
204  $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
205  $pageRenderer->loadRequireJsModule('TYPO3/CMS/Rtehtmlarea/RteLinkBrowser');
206  }
207 
213  protected function initCurrentUrl()
214  {
215  if (empty($this->currentLinkParts)) {
216  return;
217  }
218 
219  if (!empty($this->currentLinkParts['url'])) {
220  $linkService = GeneralUtility::makeInstance(LinkService::class);
221  $data = $linkService->resolve($this->currentLinkParts['url']);
222  $this->currentLinkParts['type'] = $data['type'];
223  unset($data['type']);
224  $this->currentLinkParts['url'] = $data;
225  }
226 
227  if (!empty($this->currentLinkParts['class'])) {
228  // remove required classes
229  $currentClasses = GeneralUtility::trimExplode(' ', $this->currentLinkParts['class'], true);
230  if (count($currentClasses) > 1) {
231  $this->currentLinkParts['class'] = end($currentClasses);
232  }
233  }
234  parent::initCurrentUrl();
235  }
236 
242  public function renderLinkAttributeFields()
243  {
244  // Processing the classes configuration
245  if (!empty($this->buttonConfig['properties.']['class.']['allowedClasses'])) {
246  $classesAnchorArray = GeneralUtility::trimExplode(',', $this->buttonConfig['properties.']['class.']['allowedClasses'], true);
247  // Collecting allowed classes and configured default values
248  $classesAnchor = [
249  'all' => []
250  ];
251  $titleReadOnly = $this->buttonConfig['properties.']['title.']['readOnly']
252  || $this->buttonConfig[$this->displayedLinkHandlerId . '.']['properties.']['title.']['readOnly'];
253  if (is_array($this->RTEProperties['classesAnchor.'])) {
254  foreach ($this->RTEProperties['classesAnchor.'] as $label => $conf) {
255  if (in_array($conf['class'], $classesAnchorArray)) {
256  $classesAnchor['all'][] = $conf['class'];
257  if ($conf['type'] === $this->displayedLinkHandlerId) {
258  $classesAnchor[$conf['type']][] = $conf['class'];
259  if ($this->buttonConfig[$conf['type'] . '.']['properties.']['class.']['default'] == $conf['class']) {
260  $this->classesAnchorDefault[$conf['type']] = $conf['class'];
261  if ($conf['titleText']) {
262  $this->classesAnchorDefaultTitle[$conf['type']] = $this->contentLanguageService->sL(trim($conf['titleText']));
263  }
264  if (isset($conf['target'])) {
265  $this->classesAnchorDefaultTarget[$conf['type']] = trim($conf['target']);
266  }
267  }
268  }
269  if ($titleReadOnly && $conf['titleText']) {
270  $this->classesAnchorClassTitle[$conf['class']] = ($this->classesAnchorDefaultTitle[$conf['type']] = $this->contentLanguageService->sL(trim($conf['titleText'])));
271  }
272  }
273  }
274  }
275  if (isset($this->linkAttributeValues['class'])
276  && isset($classesAnchor[$this->displayedLinkHandlerId])
277  && !in_array($this->linkAttributeValues['class'], $classesAnchor[$this->displayedLinkHandlerId], true)
278  ) {
279  unset($this->linkAttributeValues['class']);
280  }
281  // Constructing the class selector options
282  foreach ($classesAnchorArray as $class) {
283  if (!in_array($class, $classesAnchor['all']) || in_array($class, $classesAnchor['all']) && is_array($classesAnchor[$this->displayedLinkHandlerId]) && in_array($class, $classesAnchor[$this->displayedLinkHandlerId])) {
284  $selected = '';
285  if ($this->linkAttributeValues['class'] === $class || !$this->linkAttributeValues['class'] && $this->classesAnchorDefault[$this->displayedLinkHandlerId] == $class) {
286  $selected = 'selected="selected"';
287  }
288  $classLabel = !empty($this->RTEProperties['classes.'][$class . '.']['name'])
289  ? $this->getPageConfigLabel($this->RTEProperties['classes.'][$class . '.']['name'], 0)
290  : $class;
291  $classStyle = !empty($this->RTEProperties['classes.'][$class . '.']['value'])
292  ? $this->RTEProperties['classes.'][$class . '.']['value']
293  : '';
294  $this->classesAnchorJSOptions[$this->displayedLinkHandlerId] .= '<option ' . $selected . ' value="' . $class . '"' . ($classStyle ? ' style="' . $classStyle . '"' : '') . '>' . $classLabel . '</option>';
295  }
296  }
297  if ($this->classesAnchorJSOptions[$this->displayedLinkHandlerId] && !($this->buttonConfig['properties.']['class.']['required'] || $this->buttonConfig[$this->displayedLinkHandlerId . '.']['properties.']['class.']['required'])) {
298  $selected = '';
299  if (!$this->linkAttributeValues['class'] && !$this->classesAnchorDefault[$this->displayedLinkHandlerId]) {
300  $selected = 'selected="selected"';
301  }
302  $this->classesAnchorJSOptions[$this->displayedLinkHandlerId] = '<option ' . $selected . ' value=""></option>' . $this->classesAnchorJSOptions[$this->displayedLinkHandlerId];
303  }
304  }
305  // Default target
306  $this->defaultLinkTarget = $this->classesAnchorDefault[$this->displayedLinkHandlerId] && $this->classesAnchorDefaultTarget[$this->displayedLinkHandlerId]
307  ? $this->classesAnchorDefaultTarget[$this->displayedLinkHandlerId]
308  : (isset($this->buttonConfig[$this->displayedLinkHandlerId . '.']['properties.']['target.']['default'])
309  ? $this->buttonConfig[$this->displayedLinkHandlerId . '.']['properties.']['target.']['default']
310  : (isset($this->buttonConfig['properties.']['target.']['default'])
311  ? $this->buttonConfig['properties.']['target.']['default']
312  : ''));
313  // Initializing additional attributes
314  if ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins']['TYPO3Link']['additionalAttributes']) {
315  $addAttributes = GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins']['TYPO3Link']['additionalAttributes'], true);
316  foreach ($addAttributes as $attribute) {
317  $this->additionalAttributes[$attribute] = isset($this->linkAttributeValues[$attribute]) ? $this->linkAttributeValues[$attribute] : '';
318  }
319  }
320  return parent::renderLinkAttributeFields();
321  }
322 
330  public function getPageConfigLabel($string, $JScharCode = true)
331  {
332  if (substr($string, 0, 4) !== 'LLL:') {
333  $label = $string;
334  } else {
335  $label = $this->getLanguageService()->sL(trim($string));
336  }
337  $label = str_replace('"', '\\"', str_replace('\\\'', '\'', $label));
338  return $JScharCode ? GeneralUtility::quoteJSvalue($label) : $label;
339  }
340 
344  protected function renderCurrentUrl()
345  {
346  $removeLink = ' <a href="#" class="btn btn-default t3js-removeCurrentLink">' . htmlspecialchars($this->getLanguageService()->getLL('removeLink')) . '</a>';
347  return '
348  <div class="link-browser-section link-browser-current-link">
349  <strong>' .
350  htmlspecialchars($this->getLanguageService()->getLL('currentLink')) .
351  ': ' .
352  htmlspecialchars($this->currentLinkHandler->formatCurrentUrl()) .
353  '</strong>' .
354  '<span class="pull-right">' . $removeLink . '</span>' .
355  '</div>';
356  }
357 
363  protected function getAllowedItems()
364  {
365  $allowedItems = parent::getAllowedItems();
366 
367  $blindLinkOptions = isset($this->thisConfig['blindLinkOptions'])
368  ? GeneralUtility::trimExplode(',', $this->thisConfig['blindLinkOptions'], true)
369  : [];
370  $allowedItems = array_diff($allowedItems, $blindLinkOptions);
371 
372  if (is_array($this->buttonConfig['options.']) && $this->buttonConfig['options.']['removeItems']) {
373  $allowedItems = array_diff($allowedItems, GeneralUtility::trimExplode(',', $this->buttonConfig['options.']['removeItems'], true));
374  }
375 
376  return $allowedItems;
377  }
378 
384  protected function getAllowedLinkAttributes()
385  {
386  $allowedLinkAttributes = parent::getAllowedLinkAttributes();
387 
388  $blindLinkFields = isset($this->thisConfig['blindLinkFields'])
389  ? GeneralUtility::trimExplode(',', $this->thisConfig['blindLinkFields'], true)
390  : [];
391  $allowedLinkAttributes = array_diff($allowedLinkAttributes, $blindLinkFields);
392 
393  return $allowedLinkAttributes;
394  }
395 
401  protected function getLinkAttributeFieldDefinitions()
402  {
403  $fieldRenderingDefinitions = parent::getLinkAttributeFieldDefinitions();
404  $fieldRenderingDefinitions['title'] = $this->getTitleField();
405  $fieldRenderingDefinitions['class'] = $this->getClassField();
406  $fieldRenderingDefinitions['target'] = $this->getTargetField();
407  $fieldRenderingDefinitions['rel'] = $this->getRelField();
408  if (empty($this->buttonConfig['queryParametersSelector.']['enabled'])) {
409  unset($fieldRenderingDefinitions['params']);
410  }
411  return $fieldRenderingDefinitions;
412  }
413 
419  protected function getRelField()
420  {
421  if (empty($this->buttonConfig['relAttribute.']['enabled'])) {
422  return '';
423  }
424  // @todo add rel to attributes
425  $currentRel = $this->displayedLinkHandler === $this->currentLinkHandler && !empty($this->currentLinkParts)
426  ? $this->linkAttributeValues['rel']
427  : '';
428  // @todo define label "linkRelationship" below in xlf
429  return '
430  <form action="" name="lrelform" id="lrelform" class="t3js-dummyform form-horizontal">
431  <div class="form-group form-group-sm">
432  <label class="col-xs-4 control-label">' .
433  htmlspecialchars($this->getLanguageService()->getLL('linkRelationship')) .
434  '</label>
435  <div class="col-xs-8">
436  <input type="text" name="lrel" class="form-control" value="' . $currentRel . '" />
437  </div>
438  </div>
439  </form>
440  ';
441  }
442 
448  protected function getTargetField()
449  {
450  $targetSelectorConfig = [];
451  if (is_array($this->buttonConfig['targetSelector.'])) {
452  $targetSelectorConfig = $this->buttonConfig['targetSelector.'];
453  }
454  $target = $this->linkAttributeValues['target'] ?: $this->defaultLinkTarget;
455  $lang = $this->getLanguageService();
456  $targetSelector = '';
457 
458  if (!$targetSelectorConfig['disabled']) {
459  $targetSelector = '
460  <select name="ltarget_type" class="t3js-targetPreselect form-control">
461  <option value=""></option>
462  <option value="_top">' . htmlspecialchars($lang->getLL('top')) . '</option>
463  <option value="_blank">' . htmlspecialchars($lang->getLL('newWindow')) . '</option>
464  </select>
465  ';
466  }
467 
468  return '
469  <form action="" name="ltargetform" id="ltargetform" class="t3js-dummyform form-horizontal">
470  <div class="form-group form-group-sm" ' . ($targetSelectorConfig['disabled'] ? ' style="display: none;"' : '') . '>
471  <label class="col-xs-4 control-label">' . htmlspecialchars($lang->getLL('target')) . '</label>
472  <div class="col-xs-3">
473  <input type="text" name="ltarget" class="t3js-linkTarget form-control"
474  value="' . htmlspecialchars($target) . '" />
475  </div>
476  <div class="col-xs-3">
477  ' . $targetSelector . '
478  </div>
479  </div>
480  </form>
481  ';
482  }
483 
489  protected function getTitleField()
490  {
491  if ($this->linkAttributeValues['title']) {
492  $title = $this->linkAttributeValues['title'];
493  } else {
494  $title = !$this->classesAnchorDefault[$this->displayedLinkHandlerId] ? '' : $this->classesAnchorDefaultTitle[$this->displayedLinkHandlerId];
495  }
496  if (isset($this->buttonConfig[$this->displayedLinkHandlerId . '.']['properties.']['title.']['readOnly'])) {
497  $readOnly = (bool)$this->buttonConfig[$this->displayedLinkHandlerId . '.']['properties.']['title.']['readOnly'];
498  } else {
499  $readOnly = isset($this->buttonConfig['properties.']['title.']['readOnly'])
500  ? (bool)$this->buttonConfig['properties.']['title.']['readOnly']
501  : false;
502  }
503 
504  if ($readOnly) {
505  $currentClass = $this->linkAttributeFields['class'];
506  if (!$currentClass) {
507  $currentClass = empty($this->classesAnchorDefault[$this->displayedLinkHandlerId]) ? '' : $this->classesAnchorDefault[$this->displayedLinkHandlerId];
508  }
509  $title = $currentClass
510  ? $this->classesAnchorClassTitle[$currentClass]
511  : $this->classesAnchorDefaultTitle[$this->displayedLinkHandlerId];
512  }
513  return '
514  <form action="" name="ltitleform" id="ltitleform" class="t3js-dummyform form-horizontal">
515  <div class="form-group form-group-sm">
516  <label class="col-xs-4 control-label">
517  ' . htmlspecialchars($this->getLanguageService()->getLL('anchor_title')) . '
518  </label>
519  <div class="col-xs-8">
520  <span style="display: ' . ($readOnly ? 'none' : 'inline') . ';">
521  <input type="text" name="ltitle" class="form-control"
522  value="' . htmlspecialchars($title) . '" />
523  </span>
524  <span id="rtehtmlarea-browse-links-title-readonly"
525  style="display: ' . ($readOnly ? 'inline' : 'none') . ';">
526  ' . htmlspecialchars($title) . '</span>
527  </div>
528  </div>
529  </form>
530  ';
531  }
532 
538  protected function getClassField()
539  {
540  $selectClass = '';
541  if ($this->classesAnchorJSOptions[$this->displayedLinkHandlerId]) {
542  $selectClass = '
543  <form action="" name="lclassform" id="lclassform" class="t3js-dummyform">
544  <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkClass">
545  <tr>
546  <td style="width: 96px;">' . htmlspecialchars($this->getLanguageService()->getLL('anchor_class')) . '</td>
547  <td><select name="lclass" class="t3js-class-selector form-control">
548  ' . $this->classesAnchorJSOptions[$this->displayedLinkHandlerId] . '
549  </select></td>
550  </tr>
551  </table>
552  </form>
553  ';
554  }
555  return $selectClass;
556  }
557 
563  protected function getCurrentPageId()
564  {
565  return explode(':', $this->RTEtsConfigParams)[5];
566  }
567 
575  public function getConfiguration()
576  {
577  return $this->buttonConfig;
578  }
579 
585  protected function getBodyTagAttributes()
586  {
587  $parameters = parent::getBodyTagAttributes();
588  $parameters['data-site-url'] = $this->siteUrl;
589  return $parameters;
590  }
591 
597  public function getUrlParameters(array $overrides = null)
598  {
599  return [
600  'act' => isset($overrides['act']) ? $overrides['act'] : $this->displayedLinkHandlerId,
601  'bparams' => $this->bparams,
602  'editorNo' => $this->editorNo,
603  'contentTypo3Language' => $this->contentTypo3Language
604  ];
605  }
606 }
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
static getPagesTSconfig($id, $rootLine=null, $returnPartArray=false)
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static RTEsetup($RTEprop, $table, $field, $type= '')
static makeInstance($className,...$constructorArguments)