2 declare(strict_types = 1);
18 use Doctrine\DBAL\Connection;
111 $this->currentWorkspace = $workspaceId;
112 if (!empty($additionalFieldsToQuery)) {
113 $this->fields = array_merge($this->fields, $additionalFieldsToQuery);
133 callable $callback =
null,
134 array $dbMounts = [],
135 $resolveUserPermissions =
false
138 if ($entryPoint === 0) {
143 if (!empty($tree) && $callback !==
null) {
157 if (!isset($tree[
'_children'])) {
160 foreach ($tree[
'_children'] as $k => &$childPage) {
161 if (!call_user_func_array($callback, [$childPage])) {
162 unset($tree[
'_children'][$k]);
176 public function getTreeLevels(array $pageTree,
int $depth): array
178 $parentPageIds = [$pageTree[
'uid']];
179 $groupedAndSortedPagesByPid = [];
180 for ($i = 0; $i < $depth; $i++) {
181 if (empty($parentPageIds)) {
186 $groupedAndSortedPagesByPid = $this->
groupAndSortPages($pageRecords, $groupedAndSortedPagesByPid);
188 $parentPageIds = array_column($pageRecords,
'uid');
202 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
203 ->getQueryBuilderForTable(
'pages');
204 $queryBuilder->getRestrictions()
206 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
207 ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->currentWorkspace));
209 if (!empty($this->additionalQueryRestrictions)) {
210 foreach ($this->additionalQueryRestrictions as $additionalQueryRestriction) {
211 $queryBuilder->getRestrictions()->add($additionalQueryRestriction);
215 $pageRecords = $queryBuilder
216 ->select(...$this->fields)
219 $queryBuilder->expr()->eq(
'sys_language_uid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)),
220 $queryBuilder->expr()->in(
'pid', $queryBuilder->createNamedParameter($parentPageIds, Connection::PARAM_INT_ARRAY))
229 if ($this->currentWorkspace !== 0 && !empty($pageRecords)) {
232 $movePlaceholderData = [];
233 foreach ($pageRecords as $pageRecord) {
234 $livePageIds[] = (int)$pageRecord[
'uid'];
235 $livePagePids[(int)$pageRecord[
'uid']] = (
int)$pageRecord[
'pid'];
237 $movePlaceholderData[$pageRecord[
't3ver_move_id']] = [
238 'pid' => (int)$pageRecord[
'pid'],
239 'sorting' => (
int)$pageRecord[
'sorting']
245 $resolver = GeneralUtility::makeInstance(
246 PlainDataResolver::class,
250 $resolver->setWorkspaceId($this->currentWorkspace);
251 $resolver->setKeepDeletePlaceholder(
false);
252 $resolver->setKeepMovePlaceholder(
false);
253 $resolver->setKeepLiveIds(
false);
254 $recordIds = $resolver->get();
256 if (!empty($recordIds)) {
257 $queryBuilder->getRestrictions()->removeAll();
258 $pageRecords = $queryBuilder
259 ->select(...$this->fields)
262 $queryBuilder->expr()->in(
'uid', $queryBuilder->createNamedParameter($recordIds, Connection::PARAM_INT_ARRAY))
267 foreach ($pageRecords as &$pageRecord) {
270 $pageRecord[
'uid'] = (int)$liveRecord[
'uid'];
271 $pageRecord[
't3ver_oid'] = (int)$pageRecord[
't3ver_move_id'];
272 $pageRecord[
'title'] = $liveRecord[
'title'];
273 } elseif ((
int)$pageRecord[
't3ver_state'] ===
VersionState::MOVE_POINTER && !empty($movePlaceholderData[$pageRecord[
't3ver_oid']])) {
274 $pageRecord[
'uid'] = $pageRecord[
't3ver_oid'];
275 $pageRecord[
'sorting'] = (int)$movePlaceholderData[$pageRecord[
't3ver_oid']][
'sorting'];
277 $pageRecord[
'pid'] = (int)$movePlaceholderData[$pageRecord[
't3ver_oid']][
'pid'];
278 } elseif ((
int)$pageRecord[
't3ver_oid'] > 0) {
280 $pageRecord[
'sorting'] = (int)$liveRecord[
'sorting'];
281 $pageRecord[
'uid'] = (int)$liveRecord[
'uid'];
282 $pageRecord[
'pid'] = (int)$liveRecord[
'pid'];
289 foreach ($pageRecords as &$pageRecord) {
290 $pageRecord[
'uid'] = (int)$pageRecord[
'uid'];
299 return !empty($pageRecords);
309 protected function fetchAllPages(array $dbMounts,
bool $resolveUserPermissions =
false): array
311 if (!empty($this->fullPageTree)) {
314 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
315 ->getQueryBuilderForTable(
'pages');
316 $queryBuilder->getRestrictions()
318 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
319 ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->currentWorkspace));
321 if (!empty($this->additionalQueryRestrictions)) {
322 foreach ($this->additionalQueryRestrictions as $additionalQueryRestriction) {
323 $queryBuilder->getRestrictions()->add($additionalQueryRestriction);
327 $query = $queryBuilder
328 ->select(...$this->fields)
332 $queryBuilder->expr()->eq(
'sys_language_uid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))
335 if ($resolveUserPermissions) {
341 $pageRecords = $query->execute()->fetchAll();
343 $ids = array_column($pageRecords,
'uid');
344 foreach ($dbMounts as $mount) {
346 foreach ($entryPointRootLine as $page) {
347 $pageId = (int)$page[
'uid'];
348 if (in_array($pageId, $ids) || $pageId === 0) {
351 $pageRecords[] = $page;
357 $movePlaceholderData = [];
359 if ($this->currentWorkspace !== 0 && !empty($pageRecords)) {
361 foreach ($pageRecords as $pageRecord) {
362 $livePageIds[] = (int)$pageRecord[
'uid'];
363 $livePagePids[(int)$pageRecord[
'uid']] = (
int)$pageRecord[
'pid'];
365 $movePlaceholderData[$pageRecord[
't3ver_move_id']] = [
366 'pid' => (int)$pageRecord[
'pid'],
367 'sorting' => (
int)$pageRecord[
'sorting']
372 $resolver = GeneralUtility::makeInstance(
373 PlainDataResolver::class,
377 $resolver->setWorkspaceId($this->currentWorkspace);
378 $resolver->setKeepDeletePlaceholder(
false);
379 $resolver->setKeepMovePlaceholder(
false);
380 $resolver->setKeepLiveIds(
false);
381 $recordIds = $resolver->get();
383 $queryBuilder->getRestrictions()->removeAll();
384 $pageRecords = $queryBuilder
385 ->select(...$this->fields)
388 $queryBuilder->expr()->in(
'uid', $recordIds)
395 $groupedAndSortedPagesByPid = [];
396 foreach ($pageRecords as $pageRecord) {
397 $parentPageId = (int)$pageRecord[
'pid'];
401 if ($parentPageId === -1) {
406 $parentPageId = (int)$movePlaceholderData[$pageRecord[
't3ver_oid']][
'pid'];
407 $pageRecord[
'sorting'] = (int)$movePlaceholderData[$pageRecord[
't3ver_oid']][
'sorting'];
411 $parentPageId = (int)$livePagePids[$pageRecord[
't3ver_oid']];
414 $pageRecord[
'uid'] = (int)$pageRecord[
't3ver_oid'];
415 $pageRecord[
'pid'] = $parentPageId;
418 $sorting = (int)$pageRecord[
'sorting'];
419 while (isset($groupedAndSortedPagesByPid[$parentPageId][$sorting])) {
422 $groupedAndSortedPagesByPid[$parentPageId][$sorting] = $pageRecord;
425 $this->fullPageTree = [
427 'title' =>
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'sitename'] ?:
'TYPO3'
439 protected function addChildrenToPage(array &$page, array &$groupedAndSortedPagesByPid)
441 $page[
'_children'] = $groupedAndSortedPagesByPid[(int)$page[
'uid']] ?? [];
442 ksort($page[
'_children']);
443 foreach ($page[
'_children'] as &$child) {
457 foreach ($pages[
'_children'] as $childPage) {
458 if ((
int)$childPage[
'uid'] === $pageId) {
462 if (!empty($result)) {
477 public function fetchFilteredTree(
string $searchFilter, array $allowedMountPointPageIds,
string $additionalWhereClause): array
479 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
480 ->getQueryBuilderForTable(
'pages');
481 $queryBuilder->getRestrictions()
483 ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
485 if (!empty($this->additionalQueryRestrictions)) {
486 foreach ($this->additionalQueryRestrictions as $additionalQueryRestriction) {
487 $queryBuilder->getRestrictions()->add($additionalQueryRestriction);
491 $expressionBuilder = $queryBuilder->expr();
493 if ($this->currentWorkspace === 0) {
495 $workspaceIdExpression = $expressionBuilder->eq(
't3ver_wsid', 0);
498 $workspaceIdExpression = $expressionBuilder->in(
500 [0, $this->currentWorkspace]
504 $queryBuilder = $queryBuilder
505 ->select(...$this->fields)
509 $expressionBuilder->eq(
'sys_language_uid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)),
510 $workspaceIdExpression,
514 $searchParts = $expressionBuilder->orX();
515 if (is_numeric($searchFilter) && $searchFilter > 0) {
517 $expressionBuilder->eq(
'uid', $queryBuilder->createNamedParameter($searchFilter, \PDO::PARAM_INT))
520 $searchFilter =
'%' . $queryBuilder->escapeLikeWildcards($searchFilter) .
'%';
522 $searchWhereAlias = $expressionBuilder->orX(
523 $expressionBuilder->like(
525 $queryBuilder->createNamedParameter($searchFilter, \PDO::PARAM_STR)
527 $expressionBuilder->like(
529 $queryBuilder->createNamedParameter($searchFilter, \PDO::PARAM_STR)
532 $searchParts->add($searchWhereAlias);
534 $queryBuilder->andWhere($searchParts);
535 $pageRecords = $queryBuilder
540 if ($this->currentWorkspace !== 0 && !empty($pageRecords)) {
542 foreach ($pageRecords as $pageRecord) {
543 $livePageIds[] = (int)$pageRecord[
'uid'];
544 $livePagePids[(int)$pageRecord[
'uid']] = (
int)$pageRecord[
'pid'];
547 $movePlaceholderData[$pageRecord[
't3ver_oid']] = [
548 'pid' => (int)$movePlaceholder[
'pid'],
549 'sorting' => (
int)$movePlaceholder[
'sorting']
553 $movePlaceholderData[$pageRecord[
't3ver_move_id']] = [
554 'pid' => (int)$pageRecord[
'pid'],
555 'sorting' => (
int)$pageRecord[
'sorting']
560 $resolver = GeneralUtility::makeInstance(
561 PlainDataResolver::class,
565 $resolver->setWorkspaceId($this->currentWorkspace);
566 $resolver->setKeepDeletePlaceholder(
false);
567 $resolver->setKeepMovePlaceholder(
false);
568 $resolver->setKeepLiveIds(
false);
569 $recordIds = $resolver->get();
572 if (!empty($recordIds)) {
573 $queryBuilder->getRestrictions()->removeAll();
575 ->select(...$this->fields)
578 $queryBuilder->expr()->in(
'uid', $queryBuilder->createNamedParameter($recordIds, Connection::PARAM_INT_ARRAY))
580 $queryBuilder->andWhere($searchParts);
581 $pageRecords = $queryBuilder
588 foreach ($pageRecords as $pageRecord) {
589 $parentPageId = (int)$pageRecord[
'pid'];
593 if ($parentPageId === -1) {
602 $parentPageId = (int)$movePlaceholderData[$pageRecord[
't3ver_oid']][
'pid'];
603 $pageRecord[
'sorting'] = (int)$movePlaceholderData[$pageRecord[
't3ver_oid']][
'sorting'];
607 if (isset($livePagePids[$pageRecord[
't3ver_oid']])) {
608 $parentPageId = (int)$livePagePids[$pageRecord[
't3ver_oid']];
611 $parentPageId = (int)$liveRecord[
'pid'];
615 $pageRecord[
'uid'] = (int)$pageRecord[
't3ver_oid'];
616 $pageRecord[
'pid'] = $parentPageId;
618 $pages[(int)$pageRecord[
'uid']] = $pageRecord;
626 $this->fullPageTree = [
628 'title' =>
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'sitename'] ?:
'TYPO3'
644 foreach ($pages as $key => $pageRecord) {
648 $this->currentWorkspace !== 0,
651 $rootline = array_reverse($rootline);
652 if (!in_array(0, $mountPoints,
true)) {
653 $isInsideMountPoints =
false;
654 foreach ($rootline as $rootlineElement) {
655 if (in_array((
int)$rootlineElement[
'uid'], $mountPoints,
true)) {
656 $isInsideMountPoints =
true;
660 if (!$isInsideMountPoints) {
667 $inFilteredRootline =
false;
668 $amountOfRootlineElements = count($rootline);
669 for ($i = 0; $i < $amountOfRootlineElements; ++$i) {
670 $rootlineElement = $rootline[$i];
671 $rootlineElement[
'uid'] = (int)$rootlineElement[
'uid'];
672 $isInWebMount =
false;
673 if ($rootlineElement[
'uid'] > 0) {
678 || ($rootlineElement[
'uid'] === (
int)$mountPoints[0]
679 && $rootlineElement[
'uid'] !== $isInWebMount)
683 if ($this->
getBackendUser()->
isAdmin() || ($rootlineElement[
'uid'] === $isInWebMount && in_array($rootlineElement[
'uid'], $mountPoints,
true))) {
684 $inFilteredRootline =
true;
686 if (!$inFilteredRootline) {
690 if (!isset($pages[$rootlineElement[
'uid']])) {
691 $pages[$rootlineElement[
'uid']] = $rootlineElement;
696 foreach ($mountPoints as $mountPoint) {
697 if ($mountPoint !== 0) {
698 if (!array_key_exists($mountPoint, $pages)) {
700 $pages[$mountPoint][
'uid'] = (int)$pages[$mountPoint][
'uid'];
702 $pages[$mountPoint][
'pid'] = 0;
716 protected function groupAndSortPages(array $pages, $groupedAndSortedPagesByPid = []): array
718 foreach ($pages as $key => $pageRecord) {
719 $parentPageId = (int)$pageRecord[
'pid'];
720 $sorting = (int)$pageRecord[
'sorting'];
721 while (isset($groupedAndSortedPagesByPid[$parentPageId][$sorting])) {
724 $groupedAndSortedPagesByPid[$parentPageId][$sorting] = $pageRecord;
727 return $groupedAndSortedPagesByPid;