Commit 6ddd76d0 authored by Fabian Galinski's avatar Fabian Galinski

[FEATURE] Extends the page not found handling by a page id wizard. Also...

[FEATURE] Extends the page not found handling by a page id wizard. Also respect the pid on direct match
parent 7dc3e357
......@@ -28,18 +28,28 @@ namespace SGalinski\SgRoutes\Service;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Controller\ErrorPageController;
use TYPO3\CMS\Core\Core\Bootstrap;
use TYPO3\CMS\Core\Database\DatabaseConnection;
use TYPO3\CMS\Core\Error\Http\ServiceUnavailableException;
use TYPO3\CMS\Core\TypoScript\TemplateService;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\VersionNumberUtility;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
use TYPO3\CMS\Frontend\Page\PageGenerator;
use TYPO3\CMS\Frontend\Page\PageRepository;
/**
* Class SGalinski\SgRoutes\Service\RoutingService
*/
class RoutingService {
const PAGE_ID_URL_ID = 'id=';
const URL_WIZARD_ID = 't3://page?uid=';
/**
* @var ObjectManager
*/
......@@ -59,12 +69,14 @@ class RoutingService {
*
* @param array $parameters
* @param TypoScriptFrontendController $controller
*
* @return int
* @throws \ReflectionException
* @throws \TYPO3\CMS\Core\Package\Exception
* @throws \BadFunctionCallException
* @throws \InvalidArgumentException
* @throws \UnexpectedValueException
* @throws ServiceUnavailableException
*/
public function hook(
/** @noinspection PhpUnusedParameterInspection */
......@@ -72,11 +84,30 @@ class RoutingService {
): int {
$start = microtime(TRUE);
$requestUri = GeneralUtility::getIndpEnv('REQUEST_URI');
list($requestUri, $requestParameters) = GeneralUtility::trimExplode('?', $requestUri, TRUE);
list($requestPath, $requestParameters) = GeneralUtility::trimExplode('?', $requestUri, TRUE);
$requestParameterPageId = NULL;
$filteredRequestParameters = [];
foreach (GeneralUtility::trimExplode('&', $requestParameters, TRUE) as $splitedParameter) {
if (strpos($splitedParameter, self::PAGE_ID_URL_ID) === 0) {
$requestParameterPageId = $splitedParameter;
continue;
}
$filteredRequestParameters[] = $splitedParameter;
}
$requestParameters = implode('&', $filteredRequestParameters);
if ($requestParameterPageId !== NULL) {
$requestUri = $requestPath . '?' . $requestParameterPageId;
} else {
$requestUri = $requestPath;
}
if (substr($requestUri, -1) === '/') {
$requestUri = substr($requestUri, 0, -1);
}
$rootUid = $this->getRootUid($controller);
if ($rootUid) {
if ($GLOBALS['TYPO3_CONF_VARS']['FE']['tx_routes_executed'][$rootUid]) {
......@@ -110,18 +141,31 @@ class RoutingService {
if ($redirect['use_regular_expression'] && LicensingService::checkKey()) {
$pattern = '/' . str_replace('/', '\\/', $redirect['source_url']) . '/is';
if ($requestParameters && !$redirect['redirect_url_parameters']) {
$requestUri .= '?' . $requestParameters;
}
if (preg_match($pattern, $requestUri)) {
$redirectUri = preg_replace($pattern, $redirect['destination_url'], $requestUri) .
$appendParameters;
$end = microtime(TRUE);
$this->logRedirect($redirect, $requestUri, $redirectUri, $start, $end);
$this->logRedirect($redirect, $requestUri, $redirectUri, $start, microtime(TRUE));
header('Location: ' . $redirectUri, TRUE, $redirect['redirect_code']);
exit();
}
} elseif ($requestUri === $trimmedSourceUrl) {
$end = microtime(TRUE);
$redirectUri = $redirect['destination_url'] . $appendParameters;
$this->logRedirect($redirect, $requestUri, $redirectUri, $start, $end);
$destinationUrl = $redirect['destination_url'];
if (strpos($destinationUrl, self::URL_WIZARD_ID) === 0) {
$destinationUrl = (int) substr($destinationUrl, 14);
}
if (\is_numeric($destinationUrl)) {
// Get destination url from controller if target is a page id
$redirectUri = $this->getUrlFromPageId($destinationUrl) . $appendParameters;
} else {
$redirectUri = $destinationUrl . $appendParameters;
}
$this->logRedirect($redirect, $requestUri, $redirectUri, $start, microtime(TRUE));
header('Location: ' . $redirectUri, TRUE, $redirect['redirect_code']);
exit();
}
......@@ -131,6 +175,85 @@ class RoutingService {
return $rootUid;
}
/**
* Get the url from the given page id.
*
* @param int $pageId
* @return string
* @throws ServiceUnavailableException
*/
protected function getUrlFromPageId($pageId): string {
$redirectUri = '';
$controller = $this->getTypoScriptFrontendController($pageId);
if ($controller !== NULL) {
$redirectUri = $controller->cObj->typoLink_URL(['parameter' => $pageId]);
}
return $redirectUri;
}
/**
* Get TypoScriptFrontendController from the given page id.
*
* @param int $pageId
* @return TypoScriptFrontendController
* @throws ServiceUnavailableException
*/
protected function getTypoScriptFrontendController($pageId = 0): TypoScriptFrontendController {
// Check if GLOBALS['TSFE'] is initiated correctly.
static::initializeTypoScriptFrontendController($pageId);
return $GLOBALS['TSFE'];
}
/**
* Initialize TypoScriptFrontendController from the given page id.
*
* @param int $pageId
*
* @return void
* @throws \InvalidArgumentException
* @throws ServiceUnavailableException
*/
public static function initializeTypoScriptFrontendController($pageId = 0): void {
global $TYPO3_CONF_VARS;
$controller = &$GLOBALS['TSFE'];
if (!($controller instanceof TypoScriptFrontendController)) {
$controller = GeneralUtility::makeInstance(
TypoScriptFrontendController::class,
$TYPO3_CONF_VARS,
$pageId,
0
);
$bootstrap = Bootstrap::getInstance();
if (\is_callable([$bootstrap, 'loadExtensionTables'])) {
$bootstrap->loadExtensionTables();
} elseif (\is_callable([$bootstrap, 'loadCachedTca'])) {
$bootstrap->loadCachedTca();
}
}
if (!($controller->fe_user instanceof FrontendUserAuthentication)) {
$controller->initFEuser();
}
if (!($controller->sys_page instanceof PageRepository)) {
$controller->determineId();
}
if (!($controller->tmpl instanceof TemplateService)) {
$controller->initTemplate();
}
$controller->getConfigArray();
if (!($controller->cObj instanceof ContentObjectRenderer)) {
$controller->newCObj();
}
if (empty($controller->indexedDocTitle)) {
PageGenerator::pagegenInit();
}
}
/**
* Error handler called by the pageErrorHandler()-method in TypoScriptFrontendController
*
......@@ -169,10 +292,10 @@ class RoutingService {
$handling = $databaseConnection->exec_SELECTgetSingleRow(
'function, header', $tableName, 'pid = ' . (int) $rootUid
);
if ($handling) {
if ($handling && $handling['function'] !== '') {
$configurationFound = TRUE;
$function = $handling['function'];
$isFunctionStartsWithT3Prefix = (strpos($function, 't3://page?uid=') === 0);
$isFunctionStartsWithT3Prefix = (strpos($function, self::URL_WIZARD_ID) === 0);
$evaluationFunctionThatItsNotStartedWithNumbers = ((string) (int) $function);
if ((($evaluationFunctionThatItsNotStartedWithNumbers === $function) && (int) $function) ||
$isFunctionStartsWithT3Prefix
......@@ -370,25 +493,43 @@ class RoutingService {
}
}
if (!$rootUid && !$controller->sys_page) {
$controller->sys_page = GeneralUtility::makeInstance(PageRepository::class);
$controller->sys_page->versioningPreview =
$controller->fePreview === 2 || (int) $controller->workspacePreview ||
(bool) GeneralUtility::_GP('ADMCMD_view');
$controller->sys_page->versioningWorkspaceId = $controller->whichWorkspace();
$controller->sys_page->init($controller->showHiddenPage);
$controller->initUserGroups();
$controller->setSysPageWhereClause();
$controller->domainStartPage = $controller->findDomainRecord(
$GLOBALS['TYPO3_CONF_VARS']['SYS']['recursiveDomainSearch']
);
$rootUid = (int) $controller->domainStartPage;
$rootUid = $this->getRootUidFromController($controller);
}
} else {
$rootUid = self::getRootUidByPageUid((int) $controller->id);
// Get rootId for non-existing page id
if (!$rootUid) {
$rootUid = $this->getRootUidFromController($controller);
}
}
return $rootUid;
}
/**
* Returns the rootUid from frontend controller.
*
* @param TypoScriptFrontendController $controller
*
* @return int
* @throws \InvalidArgumentException
*/
private function getRootUidFromController(TypoScriptFrontendController $controller): int {
$controller->sys_page = GeneralUtility::makeInstance(PageRepository::class);
$controller->sys_page->versioningPreview =
$controller->fePreview === 2 || (int) $controller->workspacePreview ||
(bool) GeneralUtility::_GP('ADMCMD_view');
$controller->sys_page->versioningWorkspaceId = $controller->whichWorkspace();
$controller->sys_page->init($controller->showHiddenPage);
$controller->initUserGroups();
$controller->setSysPageWhereClause();
$controller->domainStartPage = $controller->findDomainRecord(
$GLOBALS['TYPO3_CONF_VARS']['SYS']['recursiveDomainSearch']
);
return (int) $controller->domainStartPage;
}
/**
* Returns the current language id
*
......
......@@ -90,7 +90,23 @@ return [
'config' => [
'type' => 'input',
'size' => 30,
'eval' => 'trim'
'eval' => 'trim',
'wizards' => [
'link' => [
'type' => 'popup',
'title' => 'LLL:EXT:sg_routes/Resources/Private/Language/locallang_db.xlf:tx_sgroutes_domain_model_pagenotfoundhandling.functionBrowsePages',
'icon' => 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_list.gif',
'module' => [
'name' => 'wizard_link',
],
'params' => [
'blindLinkOptions' => 'mail,file,folder,url',
'blindLinkFields' => 'target,title,class,params',
],
'JSopenParams' => 'height=800,width=600,status=0,menubar=0,scrollbars=1'
]
],
'softref' => 'typolink'
],
],
'redirect_url_parameters' => [
......
......@@ -86,8 +86,8 @@
<target>Beschreibung</target>
</trans-unit>
<trans-unit id="tx_sgroutes_domain_model_route.destination_url" approved="yes">
<source>Destination URL (Examples: "/contact-us/" , "/contact-us/$1")</source>
<target>Ziel-URL (Beispiele: "/kontaktiere-uns/" , "/kontaktiere-uns/$1")</target>
<source>Destination URL (Examples: "/contact-us/" , "/contact-us/$1") or Page Id</source>
<target>Ziel-URL (Beispiele: "/kontaktiere-uns/" , "/kontaktiere-uns/$1") oder Seiten Id</target>
</trans-unit>
<trans-unit id="tx_sgroutes_domain_model_route.permanently" approved="yes">
<source>301 (Permanent Redirect)</source>
......
......@@ -67,7 +67,7 @@
<source>Description</source>
</trans-unit>
<trans-unit id="tx_sgroutes_domain_model_route.destination_url">
<source>Destination URL (Examples: "/contact-us/" , "/contact-us/$1")</source>
<source>Destination URL (Examples: "/contact-us/" , "/contact-us/$1") or Page Id</source>
</trans-unit>
<trans-unit id="tx_sgroutes_domain_model_route.permanently">
<source>301 (Permanent Redirect)</source>
......@@ -107,4 +107,4 @@
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
</xliff>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment