[TASK] Cleanup and deprecate TYPO3_DB occurrences
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Resource / ProcessedFileRepository.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\Core\Database\ConnectionPool;
18 use TYPO3\CMS\Core\Log\LogManager;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20
21 /**
22 * Repository for accessing files
23 * it also serves as the public API for the indexing part of files in general
24 */
25 class ProcessedFileRepository extends AbstractRepository
26 {
27 /**
28 * The main object type of this class. In some cases (fileReference) this
29 * repository can also return FileReference objects, implementing the
30 * common FileInterface.
31 *
32 * @var string
33 */
34 protected $objectType = ProcessedFile::class;
35
36 /**
37 * Main File object storage table. Note that this repository also works on
38 * the sys_file_reference table when returning FileReference objects.
39 *
40 * @var string
41 */
42 protected $table = 'sys_file_processedfile';
43
44 /**
45 * Creates this object.
46 */
47 public function __construct()
48 {
49 parent::__construct();
50 }
51
52 /**
53 * Creates a ProcessedFile object from a file object and a processing configuration
54 *
55 * @param FileInterface $originalFile
56 * @param string $taskType
57 * @param array $configuration
58 * @return ProcessedFile
59 */
60 public function createNewProcessedFileObject(FileInterface $originalFile, $taskType, array $configuration)
61 {
62 return GeneralUtility::makeInstance(
63 $this->objectType,
64 $originalFile,
65 $taskType,
66 $configuration
67 );
68 }
69
70 /**
71 * @param array $databaseRow
72 * @return ProcessedFile
73 */
74 protected function createDomainObject(array $databaseRow)
75 {
76 $originalFile = $this->factory->getFileObject((int)$databaseRow['original']);
77 $originalFile->setStorage($this->factory->getStorageObject($originalFile->getProperty('storage')));
78 $taskType = $databaseRow['task_type'];
79 $configuration = unserialize($databaseRow['configuration']);
80
81 return GeneralUtility::makeInstance(
82 $this->objectType,
83 $originalFile,
84 $taskType,
85 $configuration,
86 $databaseRow
87 );
88 }
89
90 /**
91 * @param ResourceStorage $storage
92 * @param string $identifier
93 *
94 * @return null|ProcessedFile
95 */
96 public function findByStorageAndIdentifier(ResourceStorage $storage, $identifier)
97 {
98 $processedFileObject = null;
99 if ($storage->hasFile($identifier)) {
100 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
101 $databaseRow = $queryBuilder
102 ->select('*')
103 ->from($this->table)
104 ->where(
105 $queryBuilder->expr()->eq('storage', (int)$storage->getUid()),
106 $queryBuilder->expr()->eq('identifier', $queryBuilder->createNamedParameter($identifier))
107 )
108 ->execute()
109 ->fetch();
110
111 if ($databaseRow) {
112 $processedFileObject = $this->createDomainObject($databaseRow);
113 }
114 }
115 return $processedFileObject;
116 }
117 /**
118 * Adds a processedfile object in the database
119 *
120 * @param ProcessedFile $processedFile
121 * @return void
122 */
123 public function add($processedFile)
124 {
125 if ($processedFile->isPersisted()) {
126 $this->update($processedFile);
127 } else {
128 $insertFields = $processedFile->toArray();
129 $insertFields['crdate'] = $insertFields['tstamp'] = time();
130 $insertFields = $this->cleanUnavailableColumns($insertFields);
131
132 $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->table);
133
134 $connection->insert(
135 $this->table,
136 $insertFields
137 );
138
139 $uid = $connection->lastInsertId($this->table);
140 $processedFile->updateProperties(['uid' => $uid]);
141 }
142 }
143
144 /**
145 * Updates an existing file object in the database
146 *
147 * @param ProcessedFile $processedFile
148 * @return void
149 */
150 public function update($processedFile)
151 {
152 if ($processedFile->isPersisted()) {
153 $uid = (int)$processedFile->getUid();
154 $updateFields = $this->cleanUnavailableColumns($processedFile->toArray());
155 $updateFields['tstamp'] = time();
156
157 $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->table);
158 $connection->update(
159 $this->table,
160 $updateFields,
161 [
162 'uid' => (int)$uid
163 ]
164 );
165 }
166 }
167
168 /**
169 * @param \TYPO3\CMS\Core\Resource\File|\TYPO3\CMS\Core\Resource\FileInterface $file
170 * @param string $taskType The task that should be executed on the file
171 * @param array $configuration
172 *
173 * @return ProcessedFile
174 */
175 public function findOneByOriginalFileAndTaskTypeAndConfiguration(FileInterface $file, $taskType, array $configuration)
176 {
177 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
178
179 $databaseRow = $queryBuilder
180 ->select('*')
181 ->from($this->table)
182 ->where(
183 $queryBuilder->expr()->eq('original', (int)$file->getUid()),
184 $queryBuilder->expr()->eq('task_type', $queryBuilder->createNamedParameter($taskType)),
185 $queryBuilder->expr()->eq('configurationsha1', $queryBuilder->createNamedParameter(sha1(serialize($configuration))))
186 )
187 ->execute()
188 ->fetch();
189
190 if (is_array($databaseRow)) {
191 $processedFile = $this->createDomainObject($databaseRow);
192 } else {
193 $processedFile = $this->createNewProcessedFileObject($file, $taskType, $configuration);
194 }
195 return $processedFile;
196 }
197
198 /**
199 * @param FileInterface $file
200 * @return ProcessedFile[]
201 * @throws \InvalidArgumentException
202 */
203 public function findAllByOriginalFile(FileInterface $file)
204 {
205 if (!$file instanceof File) {
206 throw new \InvalidArgumentException('Parameter is no File object but got type "'
207 . (is_object($file) ? get_class($file) : gettype($file)) . '"', 1382006142);
208 }
209
210 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
211 $result = $queryBuilder
212 ->select('*')
213 ->from($this->table)
214 ->where(
215 $queryBuilder->expr()->eq('original', (int)$file->getUid())
216 )
217 ->execute();
218
219 $itemList = [];
220 while ($row = $result->fetch()) {
221 $itemList[] = $this->createDomainObject($row);
222 }
223 return $itemList;
224 }
225
226 /**
227 * Removes all processed files and also deletes the associated physical files
228 *
229 * @param int|NULL $storageUid If not NULL, only the processed files of the given storage are removed
230 * @return int Number of failed deletions
231 */
232 public function removeAll($storageUid = null)
233 {
234 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
235 $result = $queryBuilder
236 ->select('*')
237 ->from($this->table)
238 ->where(
239 $queryBuilder->expr()->neq('identifier', $queryBuilder->quote(''))
240 )
241 ->execute();
242
243 $logger = $this->getLogger();
244 $errorCount = 0;
245
246 while ($row = $result->fetch()) {
247 if ($storageUid && (int)$storageUid !== (int)$row['storage']) {
248 continue;
249 }
250 try {
251 $file = $this->createDomainObject($row);
252 $file->getStorage()->setEvaluatePermissions(false);
253 $file->delete(true);
254 } catch (\Exception $e) {
255 $logger->error(
256 'Failed to delete file "' . $row['identifier'] . '" in storage uid ' . $row['storage'] . '.',
257 [
258 'exception' => $e
259 ]
260 );
261 ++$errorCount;
262 }
263 }
264
265 GeneralUtility::makeInstance(ConnectionPool::class)
266 ->getConnectionForTable($this->table)
267 ->truncate($this->table);
268
269 return $errorCount;
270 }
271
272 /**
273 * Removes all array keys which cannot be persisted
274 *
275 * @param array $data
276 *
277 * @return array
278 */
279 protected function cleanUnavailableColumns(array $data)
280 {
281 $tableColumns = GeneralUtility::makeInstance(ConnectionPool::class)
282 ->getConnectionForTable($this->table)
283 ->getSchemaManager()
284 ->listTableColumns($this->table);
285 return array_intersect_key($data, $tableColumns);
286 }
287
288 /**
289 * @return \TYPO3\CMS\Core\Log\Logger
290 */
291 protected function getLogger()
292 {
293 return GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
294 }
295 }