17 use Doctrine\DBAL\DBALException;
18 use Doctrine\DBAL\FetchMode;
100 'backend_layout_next_level'
137 trigger_error(
'Calling RootlineUtility with PageRepository as third parameter will be unsupported with TYPO3 v10.0. Use a Context object directly.', E_USER_DEPRECATED);
139 $this->context = GeneralUtility::makeInstance(Context::class);
142 $context = GeneralUtility::makeInstance(Context::class);
145 $this->pageContext = GeneralUtility::makeInstance(PageRepository::class,
$context);
148 $this->languageUid = $this->context->getPropertyFromAspect(
'language',
'id', 0);
149 $this->workspaceUid = $this->context->getPropertyFromAspect(
'workspace',
'id', 0);
150 if ($this->mountPointParameter !==
'') {
151 if (!
$GLOBALS[
'TYPO3_CONF_VARS'][
'FE'][
'enable_mount_pids']) {
152 throw new MountPointsDisabledException(
'Mount-Point Pages are disabled for this installation. Cannot resolve a Rootline for a page with Mount-Points', 1343462896);
159 (
int)$this->workspaceUid
162 if (self::$cache ===
null) {
163 self::$cache = GeneralUtility::makeInstance(\
TYPO3\CMS\Core\Cache\CacheManager::class)->getCache(
'cache_rootline');
165 self::$rootlineFields = array_merge(self::$rootlineFields, GeneralUtility::trimExplode(
',',
$GLOBALS[
'TYPO3_CONF_VARS'][
'FE'][
'addRootLineFields'],
true));
166 self::$rootlineFields = array_unique(self::$rootlineFields);
178 self::$localCache = [];
179 self::$pageRecordCache = [];
195 return implode(
'_', [
196 $otherUid !==
null ? (
int)$otherUid : $this->pageUid,
208 public function get()
210 if ($this->pageUid === 0) {
214 if (!isset(static::$localCache[$this->cacheIdentifier])) {
215 $entry = static::$cache->get($this->cacheIdentifier);
220 $depth = count($entry);
228 if (isset(static::$localCache[$parentCacheIdentifier])) {
233 $entry = array_slice($entry, 1,
null,
true);
234 static::$localCache[$parentCacheIdentifier] = $entry;
251 if (!isset(self::$pageRecordCache[$currentCacheIdentifier])) {
252 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(
'pages');
253 $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
254 $row = $queryBuilder->select(...self::$rootlineFields)
257 $queryBuilder->expr()->eq(
'uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT))
262 throw new PageNotFoundException(
'Could not fetch page data for uid ' . $uid .
'.', 1343589451);
264 $this->pageContext->versionOL(
'pages', $row,
false,
true);
265 $this->pageContext->fixVersioningPid(
'pages', $row);
266 if (is_array($row)) {
267 if ($this->languageUid > 0) {
268 $row = $this->pageContext->getPageOverlay($row, $this->languageUid);
271 self::$pageRecordCache[$currentCacheIdentifier] = $row;
274 if (!is_array(self::$pageRecordCache[$currentCacheIdentifier])) {
275 throw new PageNotFoundException(
'Broken rootline. Could not resolve page with uid ' . $uid .
'.', 1343464101);
277 return self::$pageRecordCache[$currentCacheIdentifier];
290 $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
293 foreach (
$GLOBALS[
'TCA'][
'pages'][
'columns'] as $column => $configuration) {
296 $configuration = $configuration[
'config'];
297 if ($configuration[
'MM']) {
299 $loadDBGroup = GeneralUtility::makeInstance(\
TYPO3\CMS\Core\Database\RelationHandler::class);
301 $pageRecord[$column],
303 $configuration[
'allowed'] ?? $configuration[
'foreign_table'],
304 $configuration[
'MM'],
309 $relatedUids = $loadDBGroup->tableArray[$configuration[
'foreign_table']] ?? [];
312 $table = $configuration[
'foreign_table'];
314 $queryBuilder = $connectionPool->getQueryBuilderForTable($table);
315 $queryBuilder->getRestrictions()->removeAll()
316 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
317 ->add(GeneralUtility::makeInstance(HiddenRestriction::class));
318 $queryBuilder->select(
'uid')
321 $queryBuilder->expr()->eq(
322 $configuration[
'foreign_field'],
323 $queryBuilder->createNamedParameter(
330 if (isset($configuration[
'foreign_match_fields']) && is_array($configuration[
'foreign_match_fields'])) {
331 foreach ($configuration[
'foreign_match_fields'] as $field => $value) {
332 $queryBuilder->andWhere(
333 $queryBuilder->expr()->eq(
335 $queryBuilder->createNamedParameter($value, \PDO::PARAM_STR)
340 if (isset($configuration[
'foreign_table_field'])) {
341 $queryBuilder->andWhere(
342 $queryBuilder->expr()->eq(
343 trim($configuration[
'foreign_table_field']),
344 $queryBuilder->createNamedParameter(
351 if (isset($configuration[
'foreign_sortby'])) {
352 $queryBuilder->orderBy($configuration[
'foreign_sortby']);
355 $statement = $queryBuilder->execute();
356 }
catch (DBALException $e) {
357 throw new PagePropertyRelationNotFoundException(
'Could to resolve related records for page ' . $uid .
' and foreign_table ' . htmlspecialchars($table), 1343589452);
360 while ($row = $statement->fetch()) {
361 $relatedUids[] = $row[
'uid'];
364 $pageRecord[$column] = implode(
',', $relatedUids);
379 $configuration = $configuration[
'config'] ??
null;
380 if (!empty($configuration[
'MM']) && !empty($configuration[
'type']) && in_array($configuration[
'type'], [
'select',
'inline',
'group'])) {
383 if (!empty($configuration[
'foreign_field']) && !empty($configuration[
'type']) && in_array($configuration[
'type'], [
'select',
'inline'])) {
399 $mountPoint = $this->
getRecordArray($this->parsedMountPointParameters[$this->pageUid]);
401 $parentUid = $mountPoint[
'pid'];
403 unset($this->parsedMountPointParameters[$this->pageUid]);
405 $parentUid = $page[
'pid'];
407 $cacheTags = [
'pageId_' . $page[
'uid']];
408 if ($parentUid > 0) {
411 $rootline = GeneralUtility::makeInstance(self::class, $parentUid,
$mountPointParameter, $this->context)->get();
413 foreach ($rootline as $entry) {
414 $cacheTags[] =
'pageId_' . $entry[
'uid'];
415 if ($entry[
'uid'] == $this->pageUid) {
416 throw new CircularRootLineException(
'Circular connection in rootline for page with uid ' . $this->pageUid .
' found. Check your mountpoint configuration.', 1343464103);
424 static::$cache->set($this->cacheIdentifier, $rootline, $cacheTags);
436 return array_key_exists($this->pageUid, $this->parsedMountPointParameters);
449 $mountPid = $mountPointPageData[
'mount_pid'] ??
null;
450 $uid = $mountedPageData[
'uid'] ??
null;
451 if ($mountPid != $uid) {
452 throw new BrokenRootLineException(
'Broken rootline. Mountpoint parameter does not match the actual rootline. mount_pid (' . $mountPid .
') does not match page uid (' . $uid .
').', 1343464100);
455 $mountUid = $mountPointPageData[
'uid'] ??
null;
456 if (!empty($mountPointPageData[
'mount_pid_ol'])) {
457 $mountedPageData[
'_MOUNT_OL'] =
true;
458 $mountedPageData[
'_MOUNT_PAGE'] = [
460 'pid' => $mountPointPageData[
'pid'] ??
null,
461 'title' => $mountPointPageData[
'title'] ?? null
465 $mountedPageData = $mountPointPageData;
468 $mountedPageData[
'_MP_PARAM'] = $this->pageUid .
'-' . $mountUid;
469 return $mountedPageData;
479 $mountPoints = GeneralUtility::trimExplode(
',', $this->mountPointParameter);
480 foreach ($mountPoints as $mP) {
481 list($mountedPageUid, $mountPageUid) = GeneralUtility::intExplode(
'-', $mP);
482 $this->parsedMountPointParameters[$mountedPageUid] = $mountPageUid;
491 protected function resolvePageId(
int $pageId,
int $workspaceId): int
493 if ($pageId === 0 || $workspaceId === 0) {
499 [
'uid',
't3ver_oid',
't3ver_state']
507 (
int)$page[
't3ver_oid'],
511 if (empty($movePlaceholder[
'uid'])) {
515 return (
int)$movePlaceholder[
'uid'];
526 $queryBuilder->getRestrictions()->removeAll()
527 ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
529 $statement = $queryBuilder
531 ->select(...$fieldNames)
533 $queryBuilder->expr()->eq(
535 $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
541 $record = $statement->fetch(FetchMode::ASSOCIATIVE);
542 return $record ?:
null;
554 $queryBuilder->getRestrictions()->removeAll()
555 ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
557 $statement = $queryBuilder
559 ->select(...$fieldNames)
562 $queryBuilder->expr()->eq(
564 $queryBuilder->createNamedParameter($workspaceId, \PDO::PARAM_INT)
566 $queryBuilder->expr()->eq(
570 $queryBuilder->expr()->eq(
572 $queryBuilder->createNamedParameter($liveId, \PDO::PARAM_INT)
577 $record = $statement->fetch(FetchMode::ASSOCIATIVE);
578 return $record ?:
null;
587 return GeneralUtility::makeInstance(ConnectionPool::class)
588 ->getQueryBuilderForTable($tableName);