From 0babc9f3c987d67ac28a83cebb682b0a0bfa3e86 Mon Sep 17 00:00:00 2001 From: Benni Mack <benni@typo3.org> Date: Wed, 1 Apr 2020 17:44:19 +0200 Subject: [PATCH] [TASK] Migrate checkPidArray into PageRepository The code in cObj->checkPidArray() and cObj->checkPid() is checking for valid page records, which semantically belongs to PageRepository. As this code is now added to PageRepository, it is built in a more flexible way now, and available for all core relevant parts, not just Frontend logic. The method cObj->checkPid(), previously marked as internal, is removed. Resolves: #90928 Releases: master Change-Id: I4e6c089ed7efcab208a1aa3bb79599cf2c719787 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/64042 Tested-by: TYPO3com <noreply@typo3.com> Tested-by: Georg Ringer <georg.ringer@gmail.com> Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de> Reviewed-by: Georg Ringer <georg.ringer@gmail.com> Reviewed-by: Oliver Bartsch <bo@cedev.de> Reviewed-by: Daniel Goerz <daniel.goerz@posteo.de> Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de> --- .../Domain/Repository/PageRepository.php | 35 ++++++++ .../ContentObject/ContentObjectRenderer.php | 87 +++---------------- .../ContentObject/RecordsContentObject.php | 3 +- 3 files changed, 47 insertions(+), 78 deletions(-) diff --git a/typo3/sysext/core/Classes/Domain/Repository/PageRepository.php b/typo3/sysext/core/Classes/Domain/Repository/PageRepository.php index cc46f1a9a0b9..ebfed28eb1f8 100644 --- a/typo3/sysext/core/Classes/Domain/Repository/PageRepository.php +++ b/typo3/sysext/core/Classes/Domain/Repository/PageRepository.php @@ -28,6 +28,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\Database\Query\Restriction\QueryRestrictionContainerInterface; use TYPO3\CMS\Core\Error\Http\ShortcutTargetPageNotFoundException; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\MathUtility; @@ -1116,6 +1117,40 @@ class PageRepository implements LoggerAwareInterface return $result; } + /** + * Removes Page UID numbers from the input array which are not available due to QueryRestrictions + * This is also very helpful to add a custom RestrictionContainer to add custom Restrictions such as "bad doktypes" e.g. RECYCLER doktypes + * + * @param int[] $pageIds Array of Page UID numbers to check + * @param QueryRestrictionContainerInterface|null $restrictionContainer + * @return int[] Returns the array of remaining page UID numbers + */ + public function filterAccessiblePageIds(array $pageIds, QueryRestrictionContainerInterface $restrictionContainer = null): array + { + if ($pageIds === []) { + return []; + } + $validPageIds = []; + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); + if ($restrictionContainer instanceof QueryRestrictionContainerInterface) { + $queryBuilder->setRestrictions($restrictionContainer); + } else { + $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class, $this->context)); + } + $statement = $queryBuilder->select('uid') + ->from('pages') + ->where( + $queryBuilder->expr()->in( + 'uid', + $queryBuilder->createNamedParameter($pageIds, Connection::PARAM_INT_ARRAY) + ) + ) + ->execute(); + while ($row = $statement->fetch()) { + $validPageIds[] = (int)$row['uid']; + } + return $validPageIds; + } /******************************** * * Selecting records in general diff --git a/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php b/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php index 5f482bf38bd6..8611996dedcb 100644 --- a/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php +++ b/typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php @@ -25,12 +25,12 @@ use TYPO3\CMS\Core\Cache\CacheManager; use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Context\LanguageAspect; use TYPO3\CMS\Core\Core\Environment; -use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder; use TYPO3\CMS\Core\Database\Query\QueryBuilder; use TYPO3\CMS\Core\Database\Query\QueryHelper; use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction; +use TYPO3\CMS\Core\Database\Query\Restriction\DocumentTypeExclusionRestriction; use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer; use TYPO3\CMS\Core\Domain\Repository\PageRepository; use TYPO3\CMS\Core\Html\HtmlParser; @@ -350,13 +350,6 @@ class ContentObjectRenderer implements LoggerAwareInterface */ public $parentRecord = []; - /** - * This is used by checkPid, that checks if pages are accessible. The $checkPid_cache['page_uid'] is set TRUE or FALSE upon this check featuring a caching function for the next request. - * - * @var array - */ - public $checkPid_cache = []; - /** * @var string|int */ @@ -6727,81 +6720,21 @@ class ContentObjectRenderer implements LoggerAwareInterface /** * Removes Page UID numbers from the input array which are not available due to enableFields() or the list of bad doktype numbers ($this->checkPid_badDoktypeList) * - * @param array $listArr Array of Page UID numbers for select and for which pages with enablefields and bad doktypes should be removed. + * @param int[] $pageIds Array of Page UID numbers for select and for which pages with enablefields and bad doktypes should be removed. * @return array Returns the array of remaining page UID numbers * @internal - * @see checkPid() */ - public function checkPidArray($listArr) + public function checkPidArray($pageIds) { - if (!is_array($listArr) || empty($listArr)) { + if (!is_array($pageIds) || empty($pageIds)) { return []; } - $outArr = []; - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); - $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class)); - $queryBuilder->select('uid') - ->from('pages') - ->where( - $queryBuilder->expr()->in( - 'uid', - $queryBuilder->createNamedParameter($listArr, Connection::PARAM_INT_ARRAY) - ), - $queryBuilder->expr()->notIn( - 'doktype', - $queryBuilder->createNamedParameter( - GeneralUtility::intExplode(',', $this->checkPid_badDoktypeList, true), - Connection::PARAM_INT_ARRAY - ) - ) - ); - try { - $result = $queryBuilder->execute(); - while ($row = $result->fetch()) { - $outArr[] = $row['uid']; - } - } catch (DBALException $e) { - $this->getTimeTracker()->setTSlogMessage($e->getMessage() . ': ' . $queryBuilder->getSQL(), 3); - } - - return $outArr; - } - - /** - * Checks if a page UID is available due to enableFields() AND the list of bad doktype numbers ($this->checkPid_badDoktypeList) - * - * @param int $uid Page UID to test - * @return bool TRUE if OK - * @internal - * @see checkPidArray() - */ - public function checkPid($uid) - { - $uid = (int)$uid; - if (!isset($this->checkPid_cache[$uid])) { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); - $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class)); - $count = $queryBuilder->count('*') - ->from('pages') - ->where( - $queryBuilder->expr()->eq( - 'uid', - $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT) - ), - $queryBuilder->expr()->notIn( - 'doktype', - $queryBuilder->createNamedParameter( - GeneralUtility::intExplode(',', $this->checkPid_badDoktypeList, true), - Connection::PARAM_INT_ARRAY - ) - ) - ) - ->execute() - ->fetchColumn(0); - - $this->checkPid_cache[$uid] = (bool)$count; - } - return $this->checkPid_cache[$uid]; + $restrictionContainer = GeneralUtility::makeInstance(FrontendRestrictionContainer::class); + $restrictionContainer->add(GeneralUtility::makeInstance( + DocumentTypeExclusionRestriction::class, + GeneralUtility::intExplode(',', $this->checkPid_badDoktypeList, true) + )); + return $this->getTypoScriptFrontendController()->sys_page->filterAccessiblePageIds($pageIds, $restrictionContainer); } /** diff --git a/typo3/sysext/frontend/Classes/ContentObject/RecordsContentObject.php b/typo3/sysext/frontend/Classes/ContentObject/RecordsContentObject.php index ae03d4882c31..999ffabe8a17 100644 --- a/typo3/sysext/frontend/Classes/ContentObject/RecordsContentObject.php +++ b/typo3/sysext/frontend/Classes/ContentObject/RecordsContentObject.php @@ -103,7 +103,8 @@ class RecordsContentObject extends AbstractContentObject if (is_array($row)) { $dontCheckPid = isset($conf['dontCheckPid.']) ? $this->cObj->stdWrap($conf['dontCheckPid'], $conf['dontCheckPid.']) : $conf['dontCheckPid']; if (!$dontCheckPid) { - $row = $this->cObj->checkPid($row['pid']) ? $row : ''; + $validPageId = $this->getPageRepository()->filterAccessiblePageIds([$row['pid']]); + $row = !empty($validPageId) ? $row : ''; } if ($row && !$GLOBALS['TSFE']->recordRegister[$val['table'] . ':' . $val['id']]) { $renderObjName = $conf['conf.'][$val['table']] ?: '<' . $val['table']; -- GitLab