‪TYPO3CMS  ‪main
FileSearchQuery.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 Doctrine\DBAL\Result;
22 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
31 
38 {
39  private const ‪FILES_TABLE = 'sys_file';
40 
41  private const ‪FILES_META_TABLE = 'sys_file_metadata';
42 
43  private QueryBuilder ‪$queryBuilder;
44 
48  private array ‪$additionalRestrictions = [];
49 
50  private ?Result ‪$result = null;
51 
52  public function ‪__construct(QueryBuilder ‪$queryBuilder = null)
53  {
54  $this->queryBuilder = ‪$queryBuilder ?? GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(self::FILES_TABLE);
55  }
56 
62  public static function ‪createForSearchDemand(‪FileSearchDemand $searchDemand, QueryBuilder ‪$queryBuilder = null): self
63  {
64  $query = new self(‪$queryBuilder);
65  $query->additionalRestriction(
66  new ‪SearchTermRestriction($searchDemand, $query->queryBuilder)
67  );
68  $folder = $searchDemand->‪getFolder();
69  if ($folder !== null) {
70  $query->additionalRestriction(
71  new ‪FolderRestriction($folder, $searchDemand->‪isRecursive())
72  );
73  } else {
74  $query->additionalRestriction(
76  );
77  }
78 
79  $query->queryBuilder->getConcreteQueryBuilder()->select(
80  'DISTINCT ' . $query->queryBuilder->quoteIdentifier(self::FILES_TABLE . '.identifier'),
81  $query->queryBuilder->quoteIdentifier(self::FILES_TABLE) . '.*',
82  );
83 
84  if ($searchDemand->‪getFirstResult() !== null) {
85  $query->queryBuilder->setFirstResult($searchDemand->‪getFirstResult());
86  }
87  if ($searchDemand->‪getMaxResults() !== null) {
88  $query->queryBuilder->setMaxResults($searchDemand->‪getMaxResults());
89  }
90 
91  if ($searchDemand->‪getOrderings() === null) {
92  $orderBy = (‪$GLOBALS['TCA'][‪self::FILES_TABLE]['ctrl']['sortby'] ?? '') ?: (‪$GLOBALS['TCA'][self::FILES_TABLE]['ctrl']['default_sortby'] ?? '');
93  foreach (‪QueryHelper::parseOrderBy((string)$orderBy) as [$fieldName, $order]) {
94  if (is_string($fieldName) && $fieldName !== '') {
95  // Call add ordering only for valid field names
96  $searchDemand = $searchDemand->‪addOrdering(self::FILES_TABLE, $fieldName, $order ?? 'ASC');
97  }
98  }
99  }
100  foreach ($searchDemand->‪getOrderings() as [$tableName, $fieldName, $direction]) {
101  if (!isset(‪$GLOBALS['TCA'][$tableName]['columns'][$fieldName]) || !in_array($direction, ['ASC', 'DESC'], true)) {
102  // This exception is essential to avoid SQL injections based on ordering field names, which could be input controlled by an attacker.
103  throw new \RuntimeException(sprintf('Invalid file search ordering given table: "%s", field: "%s", direction: "%s".', $tableName, $fieldName, $direction), 1555850106);
104  }
105  // Add order by fields to select, to make postgres happy and use random names to make sure to not interfere with file fields
106  $query->queryBuilder->getConcreteQueryBuilder()->addSelect(
107  ...$query->queryBuilder->quoteIdentifiersForSelect([
108  $tableName . '.' . $fieldName
109  . ' AS '
110  . preg_replace(
111  '/[^a-z0-9]/',
112  '',
113  ‪StringUtility::getUniqueId($tableName . $fieldName)
114  ),
115  ])
116  );
117  $query->queryBuilder->addOrderBy($tableName . '.' . $fieldName, $direction);
118  }
119 
120  return $query;
121  }
122 
128  public static function ‪createCountForSearchDemand(‪FileSearchDemand $searchDemand, QueryBuilder ‪$queryBuilder = null): self
129  {
130  $query = new self(‪$queryBuilder);
131  $query->additionalRestriction(
132  new ‪SearchTermRestriction($searchDemand, $query->queryBuilder)
133  );
134  $folder = $searchDemand->‪getFolder();
135  if ($folder !== null) {
136  $query->additionalRestriction(
137  new ‪FolderRestriction($folder, $searchDemand->‪isRecursive())
138  );
139  }
140 
141  $query->queryBuilder->getConcreteQueryBuilder()->select(
142  'COUNT(DISTINCT ' . $query->queryBuilder->quoteIdentifier(self::FILES_TABLE . '.identifier') . ')'
143  );
144 
145  return $query;
146  }
147 
156  public function ‪additionalRestriction(‪QueryRestrictionInterface $additionalRestriction): void
157  {
158  $this->‪ensureQueryNotExecuted();
159  $this->additionalRestrictions[get_class($additionalRestriction)] = $additionalRestriction;
160  }
161 
165  public function ‪execute()
166  {
167  if ($this->result === null) {
168  $this->‪initializeQueryBuilder();
169  $this->result = $this->queryBuilder->executeQuery();
170  }
171 
172  return ‪$this->result;
173  }
174 
179  private function ‪initializeQueryBuilder(): void
180  {
181  $this->queryBuilder->from(self::FILES_TABLE);
182  $this->queryBuilder->join(
183  self::FILES_TABLE,
184  self::FILES_META_TABLE,
185  self::FILES_META_TABLE,
186  $this->queryBuilder->expr()->eq(self::FILES_META_TABLE . '.file', $this->queryBuilder->quoteIdentifier(self::FILES_TABLE . '.uid'))
187  );
188 
189  $restrictionContainer = $this->queryBuilder->getRestrictions()
190  ->add(new ‪ConsistencyRestriction($this->queryBuilder));
191  foreach ($this->additionalRestrictions as $additionalRestriction) {
192  $restrictionContainer->add($additionalRestriction);
193  }
194  }
195 
196  private function ‪ensureQueryNotExecuted(): void
197  {
198  if ($this->result !== null) {
199  throw new \RuntimeException('Cannot modify file query once it was executed. Create a new query instead.', 1555944032);
200  }
201  }
202 }
‪TYPO3\CMS\Core\Resource\Search\FileSearchQuery\__construct
‪__construct(QueryBuilder $queryBuilder=null)
Definition: FileSearchQuery.php:52
‪TYPO3\CMS\Core\Resource\Search\FileSearchQuery
Definition: FileSearchQuery.php:38
‪TYPO3\CMS\Core\Resource\Search\FileSearchQuery\$additionalRestrictions
‪array $additionalRestrictions
Definition: FileSearchQuery.php:48
‪TYPO3\CMS\Core\Database\Query\QueryHelper\parseOrderBy
‪static array array[] parseOrderBy(string $input)
Definition: QueryHelper.php:44
‪TYPO3\CMS\Core\Database\Query\Restriction\QueryRestrictionInterface
Definition: QueryRestrictionInterface.php:27
‪TYPO3\CMS\Core\Resource\Search\FileSearchDemand\isRecursive
‪isRecursive()
Definition: FileSearchDemand.php:105
‪TYPO3\CMS\Core\Resource\Search\FileSearchDemand\addOrdering
‪addOrdering(string $tableName, string $fieldName, string $direction='ASC')
Definition: FileSearchDemand.php:154
‪TYPO3\CMS\Core\Resource\Search\FileSearchDemand\getFirstResult
‪getFirstResult()
Definition: FileSearchDemand.php:85
‪TYPO3\CMS\Core\Resource\Search\FileSearchQuery\createForSearchDemand
‪static createForSearchDemand(FileSearchDemand $searchDemand, QueryBuilder $queryBuilder=null)
Definition: FileSearchQuery.php:62
‪TYPO3\CMS\Core\Resource\Search\FileSearchQuery\ensureQueryNotExecuted
‪ensureQueryNotExecuted()
Definition: FileSearchQuery.php:196
‪TYPO3\CMS\Core\Resource\Search\FileSearchQuery\$queryBuilder
‪QueryBuilder $queryBuilder
Definition: FileSearchQuery.php:43
‪TYPO3\CMS\Core\Resource\Search\FileSearchQuery\additionalRestriction
‪additionalRestriction(QueryRestrictionInterface $additionalRestriction)
Definition: FileSearchQuery.php:156
‪TYPO3\CMS\Core\Resource\Search\QueryRestrictions\ConsistencyRestriction
Definition: ConsistencyRestriction.php:30
‪TYPO3\CMS\Core\Database\Query\QueryHelper
Definition: QueryHelper.php:32
‪TYPO3\CMS\Core\Resource\Search\FileSearchQuery\initializeQueryBuilder
‪initializeQueryBuilder()
Definition: FileSearchQuery.php:179
‪TYPO3\CMS\Core\Resource\Search\FileSearchDemand
Definition: FileSearchDemand.php:26
‪TYPO3\CMS\Core\Resource\Search\FileSearchQuery\FILES_TABLE
‪const FILES_TABLE
Definition: FileSearchQuery.php:39
‪TYPO3\CMS\Core\Resource\Search\FileSearchQuery\FILES_META_TABLE
‪const FILES_META_TABLE
Definition: FileSearchQuery.php:41
‪TYPO3\CMS\Core\Resource\Search
Definition: FileSearchDemand.php:18
‪TYPO3\CMS\Core\Resource\Search\FileSearchDemand\getFolder
‪getFolder()
Definition: FileSearchDemand.php:80
‪TYPO3\CMS\Core\Resource\Search\FileSearchQuery\execute
‪Result execute()
Definition: FileSearchQuery.php:165
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Resource\Search\FileSearchDemand\getMaxResults
‪getMaxResults()
Definition: FileSearchDemand.php:90
‪TYPO3\CMS\Core\Resource\Search\FileSearchDemand\getOrderings
‪getOrderings()
Definition: FileSearchDemand.php:100
‪TYPO3\CMS\Core\Resource\Search\QueryRestrictions\FolderMountsRestriction
Definition: FolderMountsRestriction.php:33
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Utility\StringUtility
Definition: StringUtility.php:24
‪TYPO3\CMS\Core\Resource\Search\QueryRestrictions\FolderRestriction
Definition: FolderRestriction.php:30
‪TYPO3\CMS\Core\Resource\Search\FileSearchQuery\createCountForSearchDemand
‪static createCountForSearchDemand(FileSearchDemand $searchDemand, QueryBuilder $queryBuilder=null)
Definition: FileSearchQuery.php:128
‪TYPO3\CMS\Core\Resource\Search\QueryRestrictions\SearchTermRestriction
Definition: SearchTermRestriction.php:31
‪TYPO3\CMS\Core\Resource\Search\FileSearchQuery\$result
‪Result $result
Definition: FileSearchQuery.php:50
‪TYPO3\CMS\Core\Utility\StringUtility\getUniqueId
‪static getUniqueId(string $prefix='')
Definition: StringUtility.php:57