Created
October 28, 2019 10:21
-
-
Save georgringer/557b40b40d69d59db4bc52dbcd5ae584 to your computer and use it in GitHub Desktop.
Redirects to records XCLASS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types = 1); | |
namespace Vendor\Theme\Xclass; | |
use Psr\Http\Message\UriInterface; | |
use Psr\Log\LoggerAwareInterface; | |
use Psr\Log\LoggerAwareTrait; | |
use TYPO3\CMS\Core\Http\Uri; | |
use TYPO3\CMS\Core\LinkHandling\LinkService; | |
use TYPO3\CMS\Core\Resource\Exception\InvalidPathException; | |
use TYPO3\CMS\Core\Resource\File; | |
use TYPO3\CMS\Core\Resource\Folder; | |
use TYPO3\CMS\Core\Site\Entity\SiteInterface; | |
use TYPO3\CMS\Core\Utility\GeneralUtility; | |
use TYPO3\CMS\Core\Utility\HttpUtility; | |
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; | |
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; | |
use TYPO3\CMS\Frontend\Service\TypoLinkCodecService; | |
use TYPO3\CMS\Frontend\Typolink\AbstractTypolinkBuilder; | |
use TYPO3\CMS\Frontend\Typolink\UnableToLinkException; | |
use TYPO3\CMS\Redirects\Service\RedirectService; | |
/** | |
* Creates a proper URL to redirect from a matched redirect of a request | |
* | |
* @internal due to some possible refactorings in TYPO3 v9 | |
*/ | |
class XclassedRedirectService extends RedirectService implements LoggerAwareInterface | |
{ | |
use LoggerAwareTrait; | |
/** | |
* @param array $matchedRedirect | |
* @param array $queryParams | |
* @param SiteInterface|null $site | |
* @return UriInterface|null | |
*/ | |
public function getTargetUrl(array $matchedRedirect, array $queryParams, ?SiteInterface $site = null): ?UriInterface | |
{ | |
$this->logger->debug('Found a redirect to process', $matchedRedirect); | |
$linkParameterParts = GeneralUtility::makeInstance(TypoLinkCodecService::class)->decode((string)$matchedRedirect['target']); | |
$redirectTarget = $linkParameterParts['url']; | |
$linkDetails = $this->resolveLinkDetailsFromLinkTargetXclass($redirectTarget, $site, $queryParams); | |
$this->logger->debug('Resolved link details for redirect', $linkDetails); | |
// Do this for files, folders, external URLs | |
if (!empty($linkDetails['url'])) { | |
$url = new Uri($linkDetails['url']); | |
if ($matchedRedirect['force_https']) { | |
$url = $url->withScheme('https'); | |
} | |
if ($matchedRedirect['keep_query_parameters']) { | |
$url = $this->addQueryParams($queryParams, $url); | |
} | |
return $url; | |
} | |
// If it's a record or page, then boot up TSFE and use typolink | |
return $this->getUriFromCustomLinkDetails($matchedRedirect, $site, $linkDetails, $queryParams); | |
} | |
/** | |
* Check if the current request is actually a redirect, and then process the redirect. | |
* | |
* @param string $redirectTarget | |
* | |
* @param SiteInterface|null $site | |
* @param array $queryParams | |
* @return array the link details from the linkService | |
* @throws \TYPO3\CMS\Core\LinkHandling\Exception\UnknownLinkHandlerException | |
*/ | |
protected function resolveLinkDetailsFromLinkTargetXclass(string $redirectTarget, ?SiteInterface $site, array $queryParams): array | |
{ | |
// build the target URL, take force SSL into account etc. | |
$linkService = GeneralUtility::makeInstance(LinkService::class); | |
try { | |
$linkDetails = $linkService->resolve($redirectTarget); | |
switch ($linkDetails['type']) { | |
case LinkService::TYPE_URL: | |
// all set up, nothing to do | |
break; | |
case LinkService::TYPE_FILE: | |
/** @var File $file */ | |
$file = $linkDetails['file']; | |
if ($file instanceof File) { | |
$linkDetails['url'] = $file->getPublicUrl(); | |
} | |
break; | |
case LinkService::TYPE_FOLDER: | |
/** @var Folder $folder */ | |
$folder = $linkDetails['folder']; | |
if ($folder instanceof Folder) { | |
$linkDetails['url'] = $folder->getPublicUrl(); | |
} | |
break; | |
case LinkService::TYPE_RECORD: | |
$this->bootFrontendController($site, $queryParams); | |
$contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class); | |
$url = $contentObject->typoLink_URL([ | |
'parameter' => $linkService->asString($linkDetails), | |
'forceAbsoluteUrl' => true | |
]); | |
if ($url) { | |
$linkDetails['url'] =$url; | |
} | |
break; | |
default: | |
// we have to return the link details without having a "URL" parameter | |
} | |
} catch (InvalidPathException $e) { | |
return []; | |
} | |
return $linkDetails; | |
} | |
/** | |
* Finishing booting up TSFE, after that the following properties are available. | |
* | |
* Instantiating is done by the middleware stack (see Configuration/RequestMiddlewares.php) | |
* | |
* - TSFE->fe_user | |
* - TSFE->sys_page | |
* - TSFE->tmpl | |
* - TSFE->config | |
* - TSFE->cObj | |
* | |
* So a link to a page can be generated. | |
* | |
* @param SiteInterface|null $site | |
* @param array $queryParams | |
* @return TypoScriptFrontendController | |
*/ | |
protected function bootFrontendController(?SiteInterface $site, array $queryParams): TypoScriptFrontendController | |
{ | |
// disable page errors | |
$GLOBALS['TYPO3_CONF_VARS']['FE']['pageUnavailable_handling'] = false; | |
$controller = GeneralUtility::makeInstance( | |
TypoScriptFrontendController::class, | |
null, | |
$site ? $site->getRootPageId() : $GLOBALS['TSFE']->id, | |
0 | |
); | |
$controller->fe_user = $GLOBALS['TSFE']->fe_user ?? null; | |
$controller->fetch_the_id(); | |
$controller->calculateLinkVars($queryParams); | |
$controller->getConfigArray(); | |
$controller->settingLanguage(); | |
$controller->settingLocale(); | |
$controller->newCObj(); | |
$GLOBALS['TSFE'] = $controller; | |
return $controller; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment