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