‪TYPO3CMS  9.5
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 {
35  protected ‪$contentObjectRenderer;
36 
41 
49  {
50  $this->contentObjectRenderer = ‪$contentObjectRenderer;
51  $this->typoScriptFrontendController = ‪$typoScriptFrontendController ?? ‪$GLOBALS['TSFE'];
52  }
53 
66  abstract public function ‪build(array &$linkDetails, string $linkText, string $target, array $conf): array;
67 
75  protected function ‪forceAbsoluteUrl(string $url, array $configuration): string
76  {
77  if (!empty($url) && !empty($configuration['forceAbsoluteUrl']) && preg_match('#^(?:([a-z]+)(://)([^/]*)/?)?(.*)$#', $url, $matches)) {
78  $urlParts = [
79  'scheme' => $matches[1],
80  'delimiter' => '://',
81  'host' => $matches[3],
82  'path' => $matches[4]
83  ];
84  $isUrlModified = false;
85  // Set scheme and host if not yet part of the URL:
86  if (empty($urlParts['host'])) {
87  $urlParts['scheme'] = GeneralUtility::getIndpEnv('TYPO3_SSL') ? 'https' : 'http';
88  $urlParts['host'] = GeneralUtility::getIndpEnv('HTTP_HOST');
89  $urlParts['path'] = '/' . ltrim($urlParts['path'], '/');
90  // absRefPrefix has been prepended to $url beforehand
91  // so we only modify the path if no absRefPrefix has been set
92  // otherwise we would destroy the path
93  if ($this->‪getTypoScriptFrontendController()->absRefPrefix === '') {
94  $urlParts['path'] = GeneralUtility::getIndpEnv('TYPO3_SITE_PATH') . ltrim($urlParts['path'], '/');
95  }
96  $isUrlModified = true;
97  }
98  // Override scheme:
99  $forceAbsoluteUrl = &$configuration['forceAbsoluteUrl.']['scheme'];
100  if (!empty($forceAbsoluteUrl) && $urlParts['scheme'] !== $forceAbsoluteUrl) {
101  $urlParts['scheme'] = $forceAbsoluteUrl;
102  $isUrlModified = true;
103  }
104  // Recreate the absolute URL:
105  if ($isUrlModified) {
106  $url = implode('', $urlParts);
107  }
108  }
109  return $url;
110  }
111 
117  protected function ‪isLibParseFuncDefined(): bool
118  {
119  $configuration = $this->contentObjectRenderer->mergeTSRef(
120  ['parseFunc' => '< lib.parseFunc'],
121  'parseFunc'
122  );
123  return !empty($configuration['parseFunc.']) && is_array($configuration['parseFunc.']);
124  }
125 
133  protected function ‪parseFallbackLinkTextIfLinkTextIsEmpty(string $originalLinkText, string $fallbackLinkText): string
134  {
135  if ($originalLinkText !== '') {
136  return $originalLinkText;
137  }
138  if ($this->‪isLibParseFuncDefined()) {
139  return $this->contentObjectRenderer->parseFunc($fallbackLinkText, ['makelinks' => 0], '< lib.parseFunc');
140  }
141  // encode in case `lib.parseFunc` is not configured
142  return $this->‪encodeFallbackLinkTextIfLinkTextIsEmpty($originalLinkText, $fallbackLinkText);
143  }
144 
152  protected function ‪encodeFallbackLinkTextIfLinkTextIsEmpty(string $originalLinkText, string $fallbackLinkText): string
153  {
154  if ($originalLinkText !== '') {
155  return $originalLinkText;
156  }
157  return htmlspecialchars($fallbackLinkText, ENT_QUOTES);
158  }
159 
169  protected function ‪resolveTargetAttribute(array $conf, string $name, bool $respectFrameSetOption = false, string $fallbackTarget = ''): string
170  {
171  $tsfe = $this->‪getTypoScriptFrontendController();
172  $targetAttributeAllowed = !$respectFrameSetOption
173  || (!isset($tsfe->config['config']['doctype']) || !$tsfe->config['config']['doctype'])
174  || in_array((string)$tsfe->config['config']['doctype'], ['xhtml_trans', 'xhtml_basic', 'html5'], true);
175 
176  $target = '';
177  if (isset($conf[$name])) {
178  $target = $conf[$name];
179  } elseif ($targetAttributeAllowed && !$conf['directImageLink']) {
180  $target = $fallbackTarget;
181  }
182  if (isset($conf[$name . '.']) && $conf[$name . '.']) {
183  $target = (string)$this->contentObjectRenderer->stdWrap($target, $conf[$name . '.'] ?? []);
184  }
185  return $target;
186  }
187 
197  protected function ‪processUrl(string $context, string $url, array $typolinkConfiguration = [])
198  {
199  $urlProcessors = ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['urlProcessing']['urlProcessors'] ?? false;
200  if (!$urlProcessors) {
201  return $url;
202  }
203 
204  foreach ($urlProcessors as $identifier => $configuration) {
205  if (empty($configuration) || !is_array($configuration)) {
206  throw new \RuntimeException('Missing configuration for URI processor "' . $identifier . '".', 1491130459);
207  }
208  if (!is_string($configuration['processor']) || empty($configuration['processor']) || !class_exists($configuration['processor']) || !is_subclass_of($configuration['processor'], UrlProcessorInterface::class)) {
209  throw new \RuntimeException('The URI processor "' . $identifier . '" defines an invalid provider. Ensure the class exists and implements the "' . UrlProcessorInterface::class . '".', 1491130460);
210  }
211  }
212 
213  $orderedProcessors = GeneralUtility::makeInstance(DependencyOrderingService::class)->orderByDependencies($urlProcessors);
214  $keepProcessing = true;
215 
216  foreach ($orderedProcessors as $configuration) {
218  $urlProcessor = GeneralUtility::makeInstance($configuration['processor']);
219  $url = $urlProcessor->process($context, $url, $typolinkConfiguration, $this->contentObjectRenderer, $keepProcessing);
220  if (!$keepProcessing) {
221  break;
222  }
223  }
224 
225  return $url;
226  }
227 
232  {
233  if ($this->typoScriptFrontendController instanceof ‪TypoScriptFrontendController) {
235  }
236 
237  // This usually happens when typolink is created by the TYPO3 Backend, where no TSFE object
238  // is there. This functionality is currently completely internal, as these links cannot be
239  // created properly from the Backend.
240  // However, this is added to avoid any exceptions when trying to create a link
241  $this->typoScriptFrontendController = GeneralUtility::makeInstance(
242  TypoScriptFrontendController::class,
243  null,
244  GeneralUtility::_GP('id'),
245  (int)GeneralUtility::_GP('type')
246  );
247  $this->typoScriptFrontendController->sys_page = GeneralUtility::makeInstance(PageRepository::class);
248  $this->typoScriptFrontendController->tmpl = GeneralUtility::makeInstance(TemplateService::class);
250  }
251 }
‪TYPO3\CMS\Frontend\Http\UrlProcessorInterface
Definition: UrlProcessorInterface.php:24
‪TYPO3\CMS\Frontend\Page\PageRepository
Definition: PageRepository.php:53
‪TYPO3\CMS\Core\Service\DependencyOrderingService
Definition: DependencyOrderingService.php:31
‪TYPO3\CMS\Core\TypoScript\TemplateService
Definition: TemplateService.php:50
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
Definition: TypoScriptFrontendController.php:97
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
Definition: ContentObjectRenderer.php:91
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45