TYPO3 CMS  TYPO3_8-7
AbstractTypolinkBuilder.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
25 
31 {
36 
43  {
44  $this->contentObjectRenderer = $contentObjectRenderer;
45  }
46 
59  abstract public function build(array &$linkDetails, string $linkText, string $target, array $conf): array;
60 
68  protected function forceAbsoluteUrl(string $url, array $configuration): string
69  {
70  if (!empty($url) && !empty($configuration['forceAbsoluteUrl']) && preg_match('#^(?:([a-z]+)(://)([^/]*)/?)?(.*)$#', $url, $matches)) {
71  $urlParts = [
72  'scheme' => $matches[1],
73  'delimiter' => '://',
74  'host' => $matches[3],
75  'path' => $matches[4]
76  ];
77  $isUrlModified = false;
78  // Set scheme and host if not yet part of the URL:
79  if (empty($urlParts['host'])) {
80  $urlParts['scheme'] = GeneralUtility::getIndpEnv('TYPO3_SSL') ? 'https' : 'http';
81  $urlParts['host'] = GeneralUtility::getIndpEnv('HTTP_HOST');
82  $urlParts['path'] = '/' . ltrim($urlParts['path'], '/');
83  // absRefPrefix has been prepended to $url beforehand
84  // so we only modify the path if no absRefPrefix has been set
85  // otherwise we would destroy the path
86  if ($this->getTypoScriptFrontendController()->absRefPrefix === '') {
87  $urlParts['path'] = GeneralUtility::getIndpEnv('TYPO3_SITE_PATH') . ltrim($urlParts['path'], '/');
88  }
89  $isUrlModified = true;
90  }
91  // Override scheme:
92  $forceAbsoluteUrl = &$configuration['forceAbsoluteUrl.']['scheme'];
93  if (!empty($forceAbsoluteUrl) && $urlParts['scheme'] !== $forceAbsoluteUrl) {
94  $urlParts['scheme'] = $forceAbsoluteUrl;
95  $isUrlModified = true;
96  }
97  // Recreate the absolute URL:
98  if ($isUrlModified) {
99  $url = implode('', $urlParts);
100  }
101  }
102  return $url;
103  }
104 
110  protected function isLibParseFuncDefined(): bool
111  {
112  $configuration = $this->contentObjectRenderer->mergeTSRef(
113  ['parseFunc' => '< lib.parseFunc'],
114  'parseFunc'
115  );
116  return !empty($configuration['parseFunc.']) && is_array($configuration['parseFunc.']);
117  }
118 
126  protected function parseFallbackLinkTextIfLinkTextIsEmpty(string $originalLinkText, string $fallbackLinkText): string
127  {
128  if ($originalLinkText !== '') {
129  return $originalLinkText;
130  }
131  if ($this->isLibParseFuncDefined()) {
132  return $this->contentObjectRenderer->parseFunc($fallbackLinkText, ['makelinks' => 0], '< lib.parseFunc');
133  }
134  // encode in case `lib.parseFunc` is not configured
135  return $this->encodeFallbackLinkTextIfLinkTextIsEmpty($originalLinkText, $fallbackLinkText);
136  }
137 
145  protected function encodeFallbackLinkTextIfLinkTextIsEmpty(string $originalLinkText, string $fallbackLinkText): string
146  {
147  if ($originalLinkText !== '') {
148  return $originalLinkText;
149  }
150  return htmlspecialchars($fallbackLinkText, ENT_QUOTES);
151  }
152 
162  protected function resolveTargetAttribute(array $conf, string $name, bool $respectFrameSetOption = false, string $fallbackTarget = ''): string
163  {
164  $tsfe = $this->getTypoScriptFrontendController();
165  $targetAttributeAllowed = (!$respectFrameSetOption || !$tsfe->config['config']['doctype'] ||
166  in_array((string)$tsfe->config['config']['doctype'], ['xhtml_trans', 'xhtml_frames', 'xhtml_basic', 'html5'], true));
167 
168  $target = '';
169  if (isset($conf[$name])) {
170  $target = $conf[$name];
171  } elseif ($targetAttributeAllowed) {
172  $target = $fallbackTarget;
173  }
174  if ($conf[$name . '.']) {
175  $target = (string)$this->contentObjectRenderer->stdWrap($target, $conf[$name . '.']);
176  }
177  return $target;
178  }
179 
189  protected function processUrl(string $context, string $url, array $typolinkConfiguration = [])
190  {
191  if (
192  empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['urlProcessing']['urlProcessors'])
193  || !is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['urlProcessing']['urlProcessors'])
194  ) {
195  return $url;
196  }
197 
198  $urlProcessors = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['urlProcessing']['urlProcessors'];
199  foreach ($urlProcessors as $identifier => $configuration) {
200  if (empty($configuration) || !is_array($configuration)) {
201  throw new \RuntimeException('Missing configuration for URI processor "' . $identifier . '".', 1491130459);
202  }
203  if (!is_string($configuration['processor']) || empty($configuration['processor']) || !class_exists($configuration['processor']) || !is_subclass_of($configuration['processor'], UrlProcessorInterface::class)) {
204  throw new \RuntimeException('The URI processor "' . $identifier . '" defines an invalid provider. Ensure the class exists and implements the "' . UrlProcessorInterface::class . '".', 1491130460);
205  }
206  }
207 
208  $orderedProcessors = GeneralUtility::makeInstance(DependencyOrderingService::class)->orderByDependencies($urlProcessors);
209  $keepProcessing = true;
210 
211  foreach ($orderedProcessors as $configuration) {
213  $urlProcessor = GeneralUtility::makeInstance($configuration['processor']);
214  $url = $urlProcessor->process($context, $url, $typolinkConfiguration, $this->contentObjectRenderer, $keepProcessing);
215  if (!$keepProcessing) {
216  break;
217  }
218  }
219 
220  return $url;
221  }
222 
227  {
228  if (!$GLOBALS['TSFE']) {
229  // This usually happens when typolink is created by the TYPO3 Backend, where no TSFE object
230  // is there. This functionality is currently completely internal, as these links cannot be
231  // created properly from the Backend.
232  // However, this is added to avoid any exceptions when trying to create a link
234  TypoScriptFrontendController::class,
235  [],
236  (int)GeneralUtility::_GP('id'),
237  (int)GeneralUtility::_GP('type')
238  );
239  $GLOBALS['TSFE']->sys_page = GeneralUtility::makeInstance(PageRepository::class);
240  $GLOBALS['TSFE']->sys_page->init(false);
241  $GLOBALS['TSFE']->tmpl = GeneralUtility::makeInstance(TemplateService::class);
242  $GLOBALS['TSFE']->tmpl->init();
243  }
244  return $GLOBALS['TSFE'];
245  }
246 }
static makeInstance($className,... $constructorArguments)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']