[BUGFIX] Extend ResourceStorage API to check for applied filters
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Resource / FileRepository.php
1 <?php
2 namespace TYPO3\CMS\Core\Resource;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Backend\Utility\BackendUtility;
18 use TYPO3\CMS\Core\Database\ConnectionPool;
19 use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer;
20 use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
21 use TYPO3\CMS\Core\Database\RelationHandler;
22 use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
23 use TYPO3\CMS\Core\Resource\Index\FileIndexRepository;
24 use TYPO3\CMS\Core\Utility\GeneralUtility;
25 use TYPO3\CMS\Core\Utility\MathUtility;
26
27 /**
28 * Repository for accessing files
29 * it also serves as the public API for the indexing part of files in general
30 */
31 class FileRepository extends AbstractRepository
32 {
33 /**
34 * The main object type of this class. In some cases (fileReference) this
35 * repository can also return FileReference objects, implementing the
36 * common FileInterface.
37 *
38 * @var string
39 */
40 protected $objectType = File::class;
41
42 /**
43 * Main File object storage table. Note that this repository also works on
44 * the sys_file_reference table when returning FileReference objects.
45 *
46 * @var string
47 */
48 protected $table = 'sys_file';
49
50 /**
51 * Creates an object managed by this repository.
52 *
53 * @param array $databaseRow
54 * @return File
55 */
56 protected function createDomainObject(array $databaseRow)
57 {
58 return $this->factory->getFileObject($databaseRow['uid'], $databaseRow);
59 }
60
61 /**
62 * Find FileReference objects by relation to other records
63 *
64 * @param string $tableName Table name of the related record
65 * @param string $fieldName Field name of the related record
66 * @param int $uid The UID of the related record (needs to be the localized uid, as translated IRRE elements relate to them)
67 * @return array An array of objects, empty if no objects found
68 * @throws \InvalidArgumentException
69 * @api
70 */
71 public function findByRelation($tableName, $fieldName, $uid)
72 {
73 $itemList = [];
74 if (!MathUtility::canBeInterpretedAsInteger($uid)) {
75 throw new \InvalidArgumentException(
76 'UID of related record has to be an integer. UID given: "' . $uid . '"',
77 1316789798
78 );
79 }
80 $referenceUids = [];
81 if ($this->getEnvironmentMode() === 'FE' && !empty($GLOBALS['TSFE']->sys_page)) {
82 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
83 ->getQueryBuilderForTable('sys_file_reference');
84
85 $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
86 if ($GLOBALS['TSFE']->sys_page->showHiddenRecords) {
87 $queryBuilder->getRestrictions()->removeByType(HiddenRestriction::class);
88 }
89
90 $res = $queryBuilder
91 ->select('uid')
92 ->from('sys_file_reference')
93 ->where(
94 $queryBuilder->expr()->eq(
95 'uid_foreign',
96 $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
97 ),
98 $queryBuilder->expr()->eq(
99 'tablenames',
100 $queryBuilder->createNamedParameter($tableName, \PDO::PARAM_STR)
101 ),
102 $queryBuilder->expr()->eq(
103 'fieldname',
104 $queryBuilder->createNamedParameter($fieldName, \PDO::PARAM_STR)
105 )
106 )
107 ->orderBy('sorting_foreign')
108 ->execute();
109
110 while ($row = $res->fetch()) {
111 $referenceUids[] = $row['uid'];
112 }
113 } else {
114 /** @var $relationHandler RelationHandler */
115 $relationHandler = GeneralUtility::makeInstance(RelationHandler::class);
116 $relationHandler->start(
117 '',
118 'sys_file_reference',
119 '',
120 $uid,
121 $tableName,
122 BackendUtility::getTcaFieldConfiguration($tableName, $fieldName)
123 );
124 if (!empty($relationHandler->tableArray['sys_file_reference'])) {
125 $referenceUids = $relationHandler->tableArray['sys_file_reference'];
126 }
127 }
128 if (!empty($referenceUids)) {
129 foreach ($referenceUids as $referenceUid) {
130 try {
131 // Just passing the reference uid, the factory is doing workspace
132 // overlays automatically depending on the current environment
133 $itemList[] = $this->factory->getFileReferenceObject($referenceUid);
134 } catch (ResourceDoesNotExistException $exception) {
135 // No handling, just omit the invalid reference uid
136 }
137 }
138 }
139
140 return $itemList;
141 }
142
143 /**
144 * Find FileReference objects by uid
145 *
146 * @param int $uid The UID of the sys_file_reference record
147 * @return FileReference|bool
148 * @throws \InvalidArgumentException
149 * @api
150 */
151 public function findFileReferenceByUid($uid)
152 {
153 if (!MathUtility::canBeInterpretedAsInteger($uid)) {
154 throw new \InvalidArgumentException('The UID of record has to be an integer. UID given: "' . $uid . '"', 1316889798);
155 }
156 try {
157 $fileReferenceObject = $this->factory->getFileReferenceObject($uid);
158 } catch (\InvalidArgumentException $exception) {
159 $fileReferenceObject = false;
160 }
161 return $fileReferenceObject;
162 }
163
164 /**
165 * Search for files by name in a given folder
166 *
167 * @param Folder $folder
168 * @param string $fileName
169 * @return File[]
170 */
171 public function searchByName(Folder $folder, $fileName)
172 {
173 /** @var ResourceFactory $fileFactory */
174 $fileFactory = GeneralUtility::makeInstance(ResourceFactory::class);
175
176 $storage = $folder->getStorage();
177 $folders = $storage->getFoldersInFolder($folder, 0, 0, true, true);
178 $folders[$folder->getIdentifier()] = $folder;
179
180 $fileRecords = $this->getFileIndexRepository()->findByFolders($folders, false, $fileName);
181
182 $files = [];
183 foreach ($fileRecords as $fileRecord) {
184 try {
185 $file = $fileFactory->getFileObject($fileRecord['uid'], $fileRecord);
186 if ($storage->checkFileAndFolderNameFilters($file)) {
187 $files[] = $file;
188 }
189 } catch (Exception\FileDoesNotExistException $ignoredException) {
190 continue;
191 }
192 }
193
194 return $files;
195 }
196
197 /**
198 * Return a file index repository
199 *
200 * @return FileIndexRepository
201 */
202 protected function getFileIndexRepository()
203 {
204 return FileIndexRepository::getInstance();
205 }
206 }