diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-85130-TSFE-getPageShortcutMovedToPageRepository.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-85130-TSFE-getPageShortcutMovedToPageRepository.rst new file mode 100644 index 0000000000000000000000000000000000000000..bd86f600fe1f1aa95cf1bf14c19e7377ea0cb869 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-85130-TSFE-getPageShortcutMovedToPageRepository.rst @@ -0,0 +1,35 @@ +.. include:: ../../Includes.txt + +====================================================================== +Deprecation: #85130 - $TSFE->getPageShortcut() moved to PageRepository +====================================================================== + +See :issue:`85130` + +Description +=========== + +The method :php:`TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::getPageShortcut()` has been +moved to :php:`TYPO3\CMS\Frontend\Page\PageRepository::getPageShortcut()`, as it conceptually belongs in +this class. + + +Impact +====== + +Calling the method will trigger a deprecation message. + + +Affected Installations +====================== + +TYPO3 installations using the method directly in an extension. + + +Migration +========= + +Switch the call :php:`$GLOBALS['TSFE']->getPageShortcut()` to :php:`$GLOBALS['TSFE']->sys_page->getPageShortcut()` to receive the exact +same result without a deprecation message. + +.. index:: Frontend, PHP-API, PartiallyScanned diff --git a/typo3/sysext/frontend/Classes/ContentObject/Menu/AbstractMenuContentObject.php b/typo3/sysext/frontend/Classes/ContentObject/Menu/AbstractMenuContentObject.php index d9ea71018a4c5c637032a1aff4e0a4c3fc7ba6b7..fbae0f3b178b846cb2a22a77c9426cf50117f92f 100644 --- a/typo3/sysext/frontend/Classes/ContentObject/Menu/AbstractMenuContentObject.php +++ b/typo3/sysext/frontend/Classes/ContentObject/Menu/AbstractMenuContentObject.php @@ -1657,7 +1657,7 @@ abstract class AbstractMenuContentObject if ($this->menuArr[$key]['doktype'] == PageRepository::DOKTYPE_SHORTCUT && $this->menuArr[$key]['shortcut_mode'] != PageRepository::SHORTCUT_MODE_RANDOM_SUBPAGE) { $menuItem = $this->determineOriginalShortcutPage($this->menuArr[$key]); try { - $shortcut = $tsfe->getPageShortcut( + $shortcut = $tsfe->sys_page->getPageShortcut( $menuItem['shortcut'], $menuItem['shortcut_mode'], $menuItem['uid'], diff --git a/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php b/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php index e005d0a9b92520ea3b97252d6e211de7fb7da2c6..5014b517b7f2b06c0b88a73c6cbcd20da8073f3f 100644 --- a/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php +++ b/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php @@ -1444,7 +1444,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface // whether a translation of the page overwrites the shortcut // target and we need to follow the new target $this->originalShortcutPage = $this->page; - $this->page = $this->getPageShortcut($this->page['shortcut'], $this->page['shortcut_mode'], $this->page['uid']); + $this->page = $this->sys_page->getPageShortcut($this->page['shortcut'], $this->page['shortcut_mode'], $this->page['uid']); $this->id = $this->page['uid']; } // If the page is a mountpoint which should be overlaid with the contents of the mounted page, @@ -1516,7 +1516,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface } /** - * Get page shortcut; Finds the records pointed to by input value $SC (the shortcut value) + * Get page shortcut; Finds the records pointed to by input value $SC (the shortcut value). * * @param int $SC The value of the "shortcut" field from the pages record * @param int $mode The shortcut mode: 1 will select first subpage, 2 a random subpage, 3 the parent page; default is the page pointed to by $SC @@ -1529,64 +1529,12 @@ class TypoScriptFrontendController implements LoggerAwareInterface * @return mixed Returns the page record of the page that the shortcut pointed to. * @access private * @see getPageAndRootline() + * @deprecated As this method conceptually belongs to PageRepository, it is moved in PageRepository, and will be removed in TYPO3 v10.0. */ public function getPageShortcut($SC, $mode, $thisUid, $itera = 20, $pageLog = [], $disableGroupCheck = false) { - $idArray = GeneralUtility::intExplode(',', $SC); - // Find $page record depending on shortcut mode: - switch ($mode) { - case PageRepository::SHORTCUT_MODE_FIRST_SUBPAGE: - - case PageRepository::SHORTCUT_MODE_RANDOM_SUBPAGE: - $pageArray = $this->sys_page->getMenu($idArray[0] ? $idArray[0] : $thisUid, '*', 'sorting', 'AND pages.doktype<199 AND pages.doktype!=' . PageRepository::DOKTYPE_BE_USER_SECTION); - $pO = 0; - if ($mode == PageRepository::SHORTCUT_MODE_RANDOM_SUBPAGE && !empty($pageArray)) { - $randval = (int)rand(0, count($pageArray) - 1); - $pO = $randval; - } - $c = 0; - $page = []; - foreach ($pageArray as $pV) { - if ($c === $pO) { - $page = $pV; - break; - } - $c++; - } - if (empty($page)) { - $message = 'This page (ID ' . $thisUid . ') is of type "Shortcut" and configured to redirect to a subpage. ' . 'However, this page has no accessible subpages.'; - throw new ShortcutTargetPageNotFoundException($message, 1301648328); - } - break; - case PageRepository::SHORTCUT_MODE_PARENT_PAGE: - $parent = $this->sys_page->getPage($idArray[0] ? $idArray[0] : $thisUid, $disableGroupCheck); - $page = $this->sys_page->getPage($parent['pid'], $disableGroupCheck); - if (empty($page)) { - $message = 'This page (ID ' . $thisUid . ') is of type "Shortcut" and configured to redirect to its parent page. ' . 'However, the parent page is not accessible.'; - throw new ShortcutTargetPageNotFoundException($message, 1301648358); - } - break; - default: - $page = $this->sys_page->getPage($idArray[0], $disableGroupCheck); - if (empty($page)) { - $message = 'This page (ID ' . $thisUid . ') is of type "Shortcut" and configured to redirect to a page, which is not accessible (ID ' . $idArray[0] . ').'; - throw new ShortcutTargetPageNotFoundException($message, 1301648404); - } - } - // Check if short cut page was a shortcut itself, if so look up recursively: - if ($page['doktype'] == PageRepository::DOKTYPE_SHORTCUT) { - if (!in_array($page['uid'], $pageLog) && $itera > 0) { - $pageLog[] = $page['uid']; - $page = $this->getPageShortcut($page['shortcut'], $page['shortcut_mode'], $page['uid'], $itera - 1, $pageLog, $disableGroupCheck); - } else { - $pageLog[] = $page['uid']; - $message = 'Page shortcuts were looping in uids ' . implode(',', $pageLog) . '...!'; - $this->logger->error($message); - throw new \RuntimeException($message, 1294587212); - } - } - // Return resulting page: - return $page; + trigger_error('Method "TypoScriptFrontendController::getPageShortcut()" as been moved to PageRepository - use the page repository directly to call this functionality, as this method will be removed in TYPO3 v10.0.', E_USER_DEPRECATED); + return $this->sys_page->getPageShortcut($SC, $mode, $thisUid, $itera, $pageLog, $disableGroupCheck); } /** @@ -2731,7 +2679,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface if (!empty($originalShortcutPageOverlay['shortcut']) && $originalShortcutPageOverlay['shortcut'] != $this->id) { // the translation of the original shortcut page has a different shortcut target! // set the correct page and id - $shortcut = $this->getPageShortcut($originalShortcutPageOverlay['shortcut'], $originalShortcutPageOverlay['shortcut_mode'], $originalShortcutPageOverlay['uid']); + $shortcut = $this->sys_page->getPageShortcut($originalShortcutPageOverlay['shortcut'], $originalShortcutPageOverlay['shortcut_mode'], $originalShortcutPageOverlay['uid']); $this->id = ($this->contentPid = $shortcut['uid']); $this->page = $this->sys_page->getPage($this->id); // Fix various effects on things like menus f.e. diff --git a/typo3/sysext/frontend/Classes/Page/PageRepository.php b/typo3/sysext/frontend/Classes/Page/PageRepository.php index 48e2fe8bc7b945c79571bc1cbd686f3ae608d933..5c82755afadb9633176f8b016071bb4d2213d57e 100644 --- a/typo3/sysext/frontend/Classes/Page/PageRepository.php +++ b/typo3/sysext/frontend/Classes/Page/PageRepository.php @@ -23,6 +23,7 @@ use TYPO3\CMS\Core\Database\Query\QueryHelper; use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction; use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer; use TYPO3\CMS\Core\Database\Query\Restriction\FrontendWorkspaceRestriction; +use TYPO3\CMS\Core\Error\Http\ShortcutTargetPageNotFoundException; use TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException; use TYPO3\CMS\Core\Resource\FileRepository; use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; @@ -654,7 +655,7 @@ class PageRepository implements LoggerAwareInterface * @param string $additionalWhereClause Optional additional where clauses. Like "AND title like '%blabla%'" for instance. * @param bool $checkShortcuts Check if shortcuts exist, checks by default * @return array Array with key/value pairs; keys are page-uid numbers. values are the corresponding page records (with overlaid localized fields, if any) - * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::getPageShortcut(), \TYPO3\CMS\Frontend\ContentObject\Menu\AbstractMenuContentObject::makeMenu() + * @see self::getPageShortcut(), \TYPO3\CMS\Frontend\ContentObject\Menu\AbstractMenuContentObject::makeMenu() */ public function getMenu($pageId, $fields = '*', $sortField = 'sorting', $additionalWhereClause = '', $checkShortcuts = true) { @@ -711,7 +712,7 @@ class PageRepository implements LoggerAwareInterface * @param bool $parentPages Switch to load pages (false) or child pages (true). * @return array page records * - * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::getPageShortcut() + * @see self::getPageShortcut() * @see \TYPO3\CMS\Frontend\ContentObject\Menu\AbstractMenuContentObject::makeMenu() */ protected function getSubpagesForPages( @@ -883,6 +884,79 @@ class PageRepository implements LoggerAwareInterface return $page; } + /** + * Get page shortcut; Finds the records pointed to by input value $SC (the shortcut value) + * + * @param int $shortcutFieldValue The value of the "shortcut" field from the pages record + * @param int $shortcutMode The shortcut mode: 1 will select first subpage, 2 a random subpage, 3 the parent page; default is the page pointed to by $SC + * @param int $thisUid The current page UID of the page which is a shortcut + * @param int $iteration Safety feature which makes sure that the function is calling itself recursively max 20 times (since this function can find shortcuts to other shortcuts to other shortcuts...) + * @param array $pageLog An array filled with previous page uids tested by the function - new page uids are evaluated against this to avoid going in circles. + * @param bool $disableGroupCheck If true, the group check is disabled when fetching the target page (needed e.g. for menu generation) + * + * @throws \RuntimeException + * @throws ShortcutTargetPageNotFoundException + * @return mixed Returns the page record of the page that the shortcut pointed to. + * @access private + * @see getPageAndRootline() + */ + public function getPageShortcut($shortcutFieldValue, $shortcutMode, $thisUid, $iteration = 20, $pageLog = [], $disableGroupCheck = false) + { + $idArray = GeneralUtility::intExplode(',', $shortcutFieldValue); + // Find $page record depending on shortcut mode: + switch ($shortcutMode) { + case self::SHORTCUT_MODE_FIRST_SUBPAGE: + case self::SHORTCUT_MODE_RANDOM_SUBPAGE: + $pageArray = $this->getMenu($idArray[0] ?: $thisUid, '*', 'sorting', 'AND pages.doktype<199 AND pages.doktype!=' . self::DOKTYPE_BE_USER_SECTION); + $pO = 0; + if ($shortcutMode == self::SHORTCUT_MODE_RANDOM_SUBPAGE && !empty($pageArray)) { + $pO = (int)rand(0, count($pageArray) - 1); + } + $c = 0; + $page = []; + foreach ($pageArray as $pV) { + if ($c === $pO) { + $page = $pV; + break; + } + $c++; + } + if (empty($page)) { + $message = 'This page (ID ' . $thisUid . ') is of type "Shortcut" and configured to redirect to a subpage. However, this page has no accessible subpages.'; + throw new ShortcutTargetPageNotFoundException($message, 1301648328); + } + break; + case self::SHORTCUT_MODE_PARENT_PAGE: + $parent = $this->getPage($idArray[0] ?: $thisUid, $disableGroupCheck); + $page = $this->getPage($parent['pid'], $disableGroupCheck); + if (empty($page)) { + $message = 'This page (ID ' . $thisUid . ') is of type "Shortcut" and configured to redirect to its parent page. However, the parent page is not accessible.'; + throw new ShortcutTargetPageNotFoundException($message, 1301648358); + } + break; + default: + $page = $this->getPage($idArray[0], $disableGroupCheck); + if (empty($page)) { + $message = 'This page (ID ' . $thisUid . ') is of type "Shortcut" and configured to redirect to a page, which is not accessible (ID ' . $idArray[0] . ').'; + throw new ShortcutTargetPageNotFoundException($message, 1301648404); + } + } + // Check if short cut page was a shortcut itself, if so look up recursively: + if ($page['doktype'] == self::DOKTYPE_SHORTCUT) { + if (!in_array($page['uid'], $pageLog) && $iteration > 0) { + $pageLog[] = $page['uid']; + $page = $this->getPageShortcut($page['shortcut'], $page['shortcut_mode'], $page['uid'], $iteration - 1, $pageLog, $disableGroupCheck); + } else { + $pageLog[] = $page['uid']; + $message = 'Page shortcuts were looping in uids ' . implode(',', $pageLog) . '...!'; + $this->logger->error($message); + throw new \RuntimeException($message, 1294587212); + } + } + // Return resulting page: + return $page; + } + /** * Will find the page carrying the domain record matching the input domain. * diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php index 3eaa562f6e5c59a35fe8f5a9ecbdb840c26b7a89..60266cd5d3c50fd6ed51217d270ed417f4ae0be4 100644 --- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php +++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php @@ -2324,6 +2324,13 @@ return [ 'maximumNumberOfArguments' => 3, 'restFiles' => [ 'Deprecation-85113-LegacyBackendModuleRoutingMethods.rst', - ] + ], + ], + 'TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->getPageShortcut' => [ + 'numberOfMandatoryArguments' => 3, + 'maximumNumberOfArguments' => 6, + 'restFiles' => [ + 'Deprecation-85130-TSFE-getPageShortcutMovedToPageRepository.rst', + ], ], ];