‪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->add(
80  'select',
81  [
82  'DISTINCT ' . $query->queryBuilder->quoteIdentifier(self::FILES_TABLE . '.identifier'),
83  $query->queryBuilder->quoteIdentifier(self::FILES_TABLE) . '.*',
84  ]
85  );
86 
87  if ($searchDemand->‪getFirstResult() !== null) {
88  $query->queryBuilder->setFirstResult($searchDemand->‪getFirstResult());
89  }
90  if ($searchDemand->‪getMaxResults() !== null) {
91  $query->queryBuilder->setMaxResults($searchDemand->‪getMaxResults());
92  }
93 
94  if ($searchDemand->‪getOrderings() === null) {
95  $orderBy = (‪$GLOBALS['TCA'][‪self::FILES_TABLE]['ctrl']['sortby'] ?? '') ?: (‪$GLOBALS['TCA'][self::FILES_TABLE]['ctrl']['default_sortby'] ?? '');
96  foreach (‪QueryHelper::parseOrderBy((string)$orderBy) as [$fieldName, $order]) {
97  $searchDemand = $searchDemand->‪addOrdering(self::FILES_TABLE, $fieldName, $order);
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->add(
107  'select',
108  $query->queryBuilder->quoteIdentifiersForSelect([
109  $tableName . '.' . $fieldName
110  . ' AS '
111  . preg_replace(
112  '/[^a-z0-9]/',
113  '',
114  ‪StringUtility::getUniqueId($tableName . $fieldName)
115  ),
116  ]),
117  true
118  );
119  $query->queryBuilder->addOrderBy($tableName . '.' . $fieldName, $direction);
120  }
121 
122  return $query;
123  }
124 
130  public static function ‪createCountForSearchDemand(‪FileSearchDemand $searchDemand, QueryBuilder ‪$queryBuilder = null): self
131  {
132  $query = new self(‪$queryBuilder);
133  $query->additionalRestriction(
134  new ‪SearchTermRestriction($searchDemand, $query->queryBuilder)
135  );
136  $folder = $searchDemand->‪getFolder();
137  if ($folder !== null) {
138  $query->additionalRestriction(
139  new ‪FolderRestriction($folder, $searchDemand->‪isRecursive())
140  );
141  }
142 
143  $query->queryBuilder->add(
144  'select',
145  'COUNT(DISTINCT ' . $query->queryBuilder->quoteIdentifier(self::FILES_TABLE . '.identifier') . ')'
146  );
147 
148  return $query;
149  }
150 
159  public function ‪additionalRestriction(‪QueryRestrictionInterface $additionalRestriction): void
160  {
161  $this->‪ensureQueryNotExecuted();
162  $this->additionalRestrictions[get_class($additionalRestriction)] = $additionalRestriction;
163  }
164 
168  public function ‪execute()
169  {
170  if ($this->result === null) {
171  $this->‪initializeQueryBuilder();
172  $this->result = $this->queryBuilder->executeQuery();
173  }
174 
175  return ‪$this->result;
176  }
177 
182  private function ‪initializeQueryBuilder(): void
183  {
184  $this->queryBuilder->from(self::FILES_TABLE);
185  $this->queryBuilder->join(
186  self::FILES_TABLE,
187  self::FILES_META_TABLE,
188  self::FILES_META_TABLE,
189  $this->queryBuilder->expr()->eq(self::FILES_META_TABLE . '.file', $this->queryBuilder->quoteIdentifier(self::FILES_TABLE . '.uid'))
190  );
191 
192  $restrictionContainer = $this->queryBuilder->getRestrictions()
193  ->add(new ‪ConsistencyRestriction($this->queryBuilder));
194  foreach ($this->additionalRestrictions as $additionalRestriction) {
195  $restrictionContainer->add($additionalRestriction);
196  }
197  }
198 
199  private function ‪ensureQueryNotExecuted(): void
200  {
201  if ($this->result !== null) {
202  throw new \RuntimeException('Cannot modify file query once it was executed. Create a new query instead.', 1555944032);
203  }
204  }
205 }
‪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:199
‪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:159
‪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:182
‪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:168
‪$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:48
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪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:130
‪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