‪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;
22 use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
30 
38 #[Autoconfigure(public: true)]
40 {
41  public function ‪__construct(
42  private readonly EventDispatcherInterface $eventDispatcher,
43  private readonly ‪ConnectionPool $connectionPool,
44  private readonly ‪Context $context,
45  ) {}
46 
62  public function ‪getSysTemplateRowsByRootline(array $rootline, ?ServerRequestInterface $request = null): array
63  {
64  // Site-root node first!
65  $rootLinePageIds = array_reverse(array_column($rootline, 'uid'));
66  $sysTemplateRows = [];
67  $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_template');
68  $queryBuilder->setRestrictions($this->‪getSysTemplateQueryRestrictionContainer());
69  $queryBuilder->select('sys_template.*')->from('sys_template');
70  // Build a value list as joined table to have sorting based on list sorting
71  $valueList = [];
72  foreach ($rootLinePageIds as $sorting => $rootLinePageId) {
73  $valueList[] = sprintf(
74  '%s, %s',
75  $queryBuilder->expr()->castInt(
76  $queryBuilder->createNamedParameter($rootLinePageId, ‪Connection::PARAM_INT),
77  'uid',
78  ),
79  $queryBuilder->expr()->castInt(
80  $queryBuilder->createNamedParameter($sorting, ‪Connection::PARAM_INT),
81  'sorting',
82  )
83  );
84  }
85  $valueList = 'SELECT ' . implode(' UNION ALL SELECT ', $valueList);
86  $queryBuilder->getConcreteQueryBuilder()->innerJoin(
87  $queryBuilder->quoteIdentifier('sys_template'),
88  sprintf('(%s)', $valueList),
89  $queryBuilder->quoteIdentifier('pidlist'),
90  '(' . $queryBuilder->expr()->eq(
91  'sys_template.pid',
92  $queryBuilder->quoteIdentifier('pidlist.uid')
93  ) . ')'
94  );
95  // Sort by rootline determined depth as sort criteria
96  $queryBuilder->orderBy('pidlist.sorting', 'ASC')
97  ->addOrderBy('sys_template.root', 'DESC')
98  ->addOrderBy('sys_template.sorting', 'ASC');
99  $lastPid = null;
100  $queryResult = $queryBuilder->executeQuery();
101  while ($sysTemplateRow = $queryResult->fetchAssociative()) {
102  // We're retrieving *all* templates per pid, but need the first one only. The
103  // order restriction above at least takes care they're after-each-other per pid.
104  if ($lastPid === (int)$sysTemplateRow['pid']) {
105  continue;
106  }
107  $lastPid = (int)$sysTemplateRow['pid'];
108  $sysTemplateRows[] = $sysTemplateRow;
109  }
110  $event = new ‪AfterTemplatesHaveBeenDeterminedEvent($rootline, $request, $sysTemplateRows);
111  $this->eventDispatcher->dispatch($event);
112  return $event->getTemplateRows();
113  }
114 
127  public function ‪getSysTemplateRowsByRootlineWithUidOverride(array $rootline, ?ServerRequestInterface $request, int $templateUidOnDeepestRootline): array
128  {
129  // Site-root node first!
130  $rootLinePageIds = array_reverse(array_column($rootline, 'uid'));
131  $templatePidOnDeepestRootline = $rootline[array_key_first($rootline)]['uid'];
132  $sysTemplateRows = [];
133  $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_template');
134  $queryBuilder->setRestrictions($this->‪getSysTemplateQueryRestrictionContainer());
135  $queryBuilder->select('sys_template.*')->from('sys_template');
136  if ($templateUidOnDeepestRootline && $templatePidOnDeepestRootline) {
137  $queryBuilder->andWhere(
138  $queryBuilder->expr()->or(
139  $queryBuilder->expr()->neq('sys_template.pid', $queryBuilder->createNamedParameter($templatePidOnDeepestRootline, ‪Connection::PARAM_INT)),
140  $queryBuilder->expr()->and(
141  $queryBuilder->expr()->eq('sys_template.pid', $queryBuilder->createNamedParameter($templatePidOnDeepestRootline, ‪Connection::PARAM_INT)),
142  $queryBuilder->expr()->eq('sys_template.uid', $queryBuilder->createNamedParameter($templateUidOnDeepestRootline, ‪Connection::PARAM_INT)),
143  ),
144  ),
145  );
146  }
147  // Build a value list as joined table to have sorting based on list sorting
148  $valueList = [];
149  foreach ($rootLinePageIds as $sorting => $rootLinePageId) {
150  $valueList[] = sprintf(
151  '%s, %s',
152  $queryBuilder->expr()->castInt(
153  $queryBuilder->createNamedParameter($rootLinePageId, ‪Connection::PARAM_INT),
154  'uid',
155  ),
156  $queryBuilder->expr()->castInt(
157  $queryBuilder->createNamedParameter($sorting, ‪Connection::PARAM_INT),
158  'sorting',
159  ),
160  );
161  }
162  $valueList = 'SELECT ' . implode(' UNION ALL SELECT ', $valueList);
163  $queryBuilder->getConcreteQueryBuilder()->innerJoin(
164  $queryBuilder->quoteIdentifier('sys_template'),
165  sprintf('(%s)', $valueList),
166  $queryBuilder->quoteIdentifier('pidlist'),
167  '(' . $queryBuilder->expr()->eq(
168  'sys_template.pid',
169  $queryBuilder->quoteIdentifier('pidlist.uid')
170  ) . ')'
171  );
172  // Sort by rootline determined depth as sort criteria
173  $queryBuilder->orderBy('pidlist.sorting', 'ASC')
174  ->addOrderBy('sys_template.root', 'DESC')
175  ->addOrderBy('sys_template.sorting', 'ASC');
176  $lastPid = null;
177  $queryResult = $queryBuilder->executeQuery();
178  while ($sysTemplateRow = $queryResult->fetchAssociative()) {
179  // We're retrieving *all* templates per pid, but need the first one only. The
180  // order restriction above at least takes care they're after-each-other per pid.
181  if ($lastPid === (int)$sysTemplateRow['pid']) {
182  continue;
183  }
184  $lastPid = (int)$sysTemplateRow['pid'];
185  $sysTemplateRows[] = $sysTemplateRow;
186  }
187  // @todo: This event should be able to be fired even if the sys_template resolving is
188  // merged into an early middleware like "SiteResolver" which could join / sub-select
189  // pages together with sys_template directly, which would be possible if we manage
190  // to switch away from RootlineUtility usage in SiteResolver by using a CTE instead.
191  $event = new ‪AfterTemplatesHaveBeenDeterminedEvent($rootline, $request, $sysTemplateRows);
192  $this->eventDispatcher->dispatch($event);
193  return $event->getTemplateRows();
194  }
195 
201  {
202  $restrictionContainer = GeneralUtility::makeInstance(DefaultRestrictionContainer::class);
203  if ($this->context->getPropertyFromAspect('visibility', 'includeHiddenContent', false)) {
204  $restrictionContainer->removeByType(HiddenRestriction::class);
205  }
206  return $restrictionContainer;
207  }
208 }
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateRepository
Definition: SysTemplateRepository.php:40
‪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:200
‪TYPO3\CMS\Core\TypoScript\IncludeTree
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateRepository\getSysTemplateRowsByRootline
‪getSysTemplateRowsByRootline(array $rootline, ?ServerRequestInterface $request=null)
Definition: SysTemplateRepository.php:62
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateRepository\__construct
‪__construct(private readonly EventDispatcherInterface $eventDispatcher, private readonly ConnectionPool $connectionPool, private readonly Context $context,)
Definition: SysTemplateRepository.php:41
‪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:127
‪TYPO3\CMS\Core\Database\Query\Restriction\DefaultRestrictionContainer
Definition: DefaultRestrictionContainer.php:24