‪TYPO3CMS  ‪main
SysTemplateRepository.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\EventDispatcher\EventDispatcherInterface;
21 use Psr\Http\Message\ServerRequestInterface;
29 
38 {
39  public function ‪__construct(
40  private readonly EventDispatcherInterface $eventDispatcher,
41  private readonly ‪ConnectionPool $connectionPool,
42  private readonly ‪Context $context,
43  ) {}
44 
60  public function ‪getSysTemplateRowsByRootline(array $rootline, ?ServerRequestInterface $request = null): array
61  {
62  // Site-root node first!
63  $rootLinePageIds = array_reverse(array_column($rootline, 'uid'));
64  $sysTemplateRows = [];
65  $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_template');
66  $queryBuilder->setRestrictions($this->‪getSysTemplateQueryRestrictionContainer());
67  $queryBuilder->select('sys_template.*')->from('sys_template');
68  // Build a value list as joined table to have sorting based on list sorting
69  $valueList = [];
70  foreach ($rootLinePageIds as $sorting => $rootLinePageId) {
71  $valueList[] = sprintf(
72  '%s, %s',
73  $queryBuilder->expr()->castInt(
74  $queryBuilder->createNamedParameter($rootLinePageId, ‪Connection::PARAM_INT),
75  'uid',
76  ),
77  $queryBuilder->expr()->castInt(
78  $queryBuilder->createNamedParameter($sorting, ‪Connection::PARAM_INT),
79  'sorting',
80  )
81  );
82  }
83  $valueList = 'SELECT ' . implode(' UNION ALL SELECT ', $valueList);
84  $queryBuilder->getConcreteQueryBuilder()->innerJoin(
85  $queryBuilder->quoteIdentifier('sys_template'),
86  sprintf('(%s)', $valueList),
87  $queryBuilder->quoteIdentifier('pidlist'),
88  '(' . $queryBuilder->expr()->eq(
89  'sys_template.pid',
90  $queryBuilder->quoteIdentifier('pidlist.uid')
91  ) . ')'
92  );
93  // Sort by rootline determined depth as sort criteria
94  $queryBuilder->orderBy('pidlist.sorting', 'ASC')
95  ->addOrderBy('sys_template.root', 'DESC')
96  ->addOrderBy('sys_template.sorting', 'ASC');
97  $lastPid = null;
98  $queryResult = $queryBuilder->executeQuery();
99  while ($sysTemplateRow = $queryResult->fetchAssociative()) {
100  // We're retrieving *all* templates per pid, but need the first one only. The
101  // order restriction above at least takes care they're after-each-other per pid.
102  if ($lastPid === (int)$sysTemplateRow['pid']) {
103  continue;
104  }
105  $lastPid = (int)$sysTemplateRow['pid'];
106  $sysTemplateRows[] = $sysTemplateRow;
107  }
108  $event = new ‪AfterTemplatesHaveBeenDeterminedEvent($rootline, $request, $sysTemplateRows);
109  $this->eventDispatcher->dispatch($event);
110  return $event->getTemplateRows();
111  }
112 
125  public function ‪getSysTemplateRowsByRootlineWithUidOverride(array $rootline, ?ServerRequestInterface $request, int $templateUidOnDeepestRootline): array
126  {
127  // Site-root node first!
128  $rootLinePageIds = array_reverse(array_column($rootline, 'uid'));
129  $templatePidOnDeepestRootline = $rootline[array_key_first($rootline)]['uid'];
130  $sysTemplateRows = [];
131  $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_template');
132  $queryBuilder->setRestrictions($this->‪getSysTemplateQueryRestrictionContainer());
133  $queryBuilder->select('sys_template.*')->from('sys_template');
134  if ($templateUidOnDeepestRootline && $templatePidOnDeepestRootline) {
135  $queryBuilder->andWhere(
136  $queryBuilder->expr()->or(
137  $queryBuilder->expr()->neq('sys_template.pid', $queryBuilder->createNamedParameter($templatePidOnDeepestRootline, ‪Connection::PARAM_INT)),
138  $queryBuilder->expr()->and(
139  $queryBuilder->expr()->eq('sys_template.pid', $queryBuilder->createNamedParameter($templatePidOnDeepestRootline, ‪Connection::PARAM_INT)),
140  $queryBuilder->expr()->eq('sys_template.uid', $queryBuilder->createNamedParameter($templateUidOnDeepestRootline, ‪Connection::PARAM_INT)),
141  ),
142  ),
143  );
144  }
145  // Build a value list as joined table to have sorting based on list sorting
146  $valueList = [];
147  foreach ($rootLinePageIds as $sorting => $rootLinePageId) {
148  $valueList[] = sprintf(
149  '%s, %s',
150  $queryBuilder->expr()->castInt(
151  $queryBuilder->createNamedParameter($rootLinePageId, ‪Connection::PARAM_INT),
152  'uid',
153  ),
154  $queryBuilder->expr()->castInt(
155  $queryBuilder->createNamedParameter($sorting, ‪Connection::PARAM_INT),
156  'sorting',
157  ),
158  );
159  }
160  $valueList = 'SELECT ' . implode(' UNION ALL SELECT ', $valueList);
161  $queryBuilder->getConcreteQueryBuilder()->innerJoin(
162  $queryBuilder->quoteIdentifier('sys_template'),
163  sprintf('(%s)', $valueList),
164  $queryBuilder->quoteIdentifier('pidlist'),
165  '(' . $queryBuilder->expr()->eq(
166  'sys_template.pid',
167  $queryBuilder->quoteIdentifier('pidlist.uid')
168  ) . ')'
169  );
170  // Sort by rootline determined depth as sort criteria
171  $queryBuilder->orderBy('pidlist.sorting', 'ASC')
172  ->addOrderBy('sys_template.root', 'DESC')
173  ->addOrderBy('sys_template.sorting', 'ASC');
174  $lastPid = null;
175  $queryResult = $queryBuilder->executeQuery();
176  while ($sysTemplateRow = $queryResult->fetchAssociative()) {
177  // We're retrieving *all* templates per pid, but need the first one only. The
178  // order restriction above at least takes care they're after-each-other per pid.
179  if ($lastPid === (int)$sysTemplateRow['pid']) {
180  continue;
181  }
182  $lastPid = (int)$sysTemplateRow['pid'];
183  $sysTemplateRows[] = $sysTemplateRow;
184  }
185  // @todo: This event should be able to be fired even if the sys_template resolving is
186  // merged into an early middleware like "SiteResolver" which could join / sub-select
187  // pages together with sys_template directly, which would be possible if we manage
188  // to switch away from RootlineUtility usage in SiteResolver by using a CTE instead.
189  $event = new ‪AfterTemplatesHaveBeenDeterminedEvent($rootline, $request, $sysTemplateRows);
190  $this->eventDispatcher->dispatch($event);
191  return $event->getTemplateRows();
192  }
193 
199  {
200  $restrictionContainer = GeneralUtility::makeInstance(DefaultRestrictionContainer::class);
201  if ($this->context->getPropertyFromAspect('visibility', 'includeHiddenContent', false)) {
202  $restrictionContainer->removeByType(HiddenRestriction::class);
203  }
204  return $restrictionContainer;
205  }
206 }
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateRepository
Definition: SysTemplateRepository.php:38
‪TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction
Definition: HiddenRestriction.php:27
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:52
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateRepository\getSysTemplateQueryRestrictionContainer
‪getSysTemplateQueryRestrictionContainer()
Definition: SysTemplateRepository.php:198
‪TYPO3\CMS\Core\TypoScript\IncludeTree
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateRepository\getSysTemplateRowsByRootline
‪getSysTemplateRowsByRootline(array $rootline, ?ServerRequestInterface $request=null)
Definition: SysTemplateRepository.php:60
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateRepository\__construct
‪__construct(private readonly EventDispatcherInterface $eventDispatcher, private readonly ConnectionPool $connectionPool, private readonly Context $context,)
Definition: SysTemplateRepository.php:39
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:54
‪TYPO3\CMS\Core\TypoScript\IncludeTree\Event\AfterTemplatesHaveBeenDeterminedEvent
Definition: AfterTemplatesHaveBeenDeterminedEvent.php:29
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:41
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateRepository\getSysTemplateRowsByRootlineWithUidOverride
‪getSysTemplateRowsByRootlineWithUidOverride(array $rootline, ?ServerRequestInterface $request, int $templateUidOnDeepestRootline)
Definition: SysTemplateRepository.php:125
‪TYPO3\CMS\Core\Database\Query\Restriction\DefaultRestrictionContainer
Definition: DefaultRestrictionContainer.php:24