[FOLLOWUP][FEATURE] Introduce Data Processor for Files
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / Resource / FileCollector.php
1 <?php
2 namespace TYPO3\CMS\Frontend\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\Log\LogManager;
18 use TYPO3\CMS\Core\Resource\Exception;
19 use TYPO3\CMS\Core\Resource\FileCollectionRepository;
20 use TYPO3\CMS\Core\Resource\FileInterface;
21 use TYPO3\CMS\Core\Resource\FileRepository;
22 use TYPO3\CMS\Core\Resource\Folder;
23 use TYPO3\CMS\Core\Resource\ResourceFactory;
24 use TYPO3\CMS\Core\Utility\GeneralUtility;
25
26 /**
27 * Object to collect files from various sources during runtime
28 * Sources can be file references, file collections or folders
29 *
30 * Use in FILES Content Object or for a Fluid Data Processor
31 *
32 * Is not persisted, use only in FE.
33 */
34 class FileCollector implements \Countable {
35
36 /**
37 * The files
38 *
39 * @var array
40 */
41 protected $files = array();
42
43 /**
44 * The file repository
45 *
46 * @var \TYPO3\CMS\Core\Resource\FileRepository
47 */
48 protected $fileRepository;
49
50 /**
51 * The file collection repository
52 *
53 * @var \TYPO3\CMS\Core\Resource\FileCollectionRepository
54 */
55 protected $fileCollectionRepository;
56
57 /**
58 * The resource factory
59 *
60 * @var \TYPO3\CMS\Core\Resource\ResourceFactory
61 */
62 protected $resourceFactory;
63
64 /**
65 * Add files
66 *
67 * @param array $fileUids
68 */
69 public function addFiles(array $fileUids = array()) {
70 if (!empty($fileUids)) {
71 foreach ($fileUids as $fileUid) {
72 try {
73 $this->addFileObject($this->getResourceFactory()->getFileObject($fileUid));
74 } catch (Exception $e) {
75 $this->getLogger()->warning(
76 'The file with uid "' . $fileUid
77 . '" could not be found and won\'t be included in frontend output',
78 array('exception' => $e)
79 );
80 }
81 }
82 }
83 }
84
85 /**
86 * Add files to the collection from a relation
87 *
88 * @param string $relationTable The table of the relation (e.g. tt_content or pages)
89 * @param string $relationField The field which holds the files (e.g. media or images)
90 * @param array $referenceRecord the record which is referencing the files
91 * @return void
92 */
93 public function addFilesFromRelation($relationTable, $relationField, array $referenceRecord) {
94 if (is_object($GLOBALS['TSFE']) && is_object($GLOBALS['TSFE']->sys_page)) {
95 $fileReferences = $GLOBALS['TSFE']->sys_page->getFileReferences($relationTable, $relationField, $referenceRecord);
96 } else {
97 $fileReferences = $this->getFileRepository()->findByRelation($relationTable, $relationField, $referenceRecord['uid']);
98 }
99
100 if (!empty($fileReferences)) {
101 $this->addFileObjects($fileReferences);
102 }
103 }
104
105 /**
106 * Add files from UIDs of a reference
107 *
108 * @param array $fileReferenceUids
109 * @return void
110 */
111 public function addFileReferences(array $fileReferenceUids = array()) {
112 foreach ($fileReferenceUids as $fileReferenceUid) {
113 $fileObject = $this->getFileRepository()->findFileReferenceByUid($fileReferenceUid);
114 $this->addFileObject($fileObject);
115 }
116 }
117
118 /**
119 * Add files to the collection from multiple file collections
120 *
121 * @param array $fileCollectionUids The file collections uids
122 * @return void
123 */
124 public function addFilesFromFileCollections(array $fileCollectionUids = array()) {
125 foreach ($fileCollectionUids as $fileCollectionUid) {
126 $this->addFilesFromFileCollection($fileCollectionUid);
127 }
128 }
129
130 /**
131 * Add files to the collection from one single file collection
132 *
133 * @param int $fileCollectionUid The file collections uid
134 * @return void
135 */
136 public function addFilesFromFileCollection($fileCollectionUid = NULL) {
137 if (!empty($fileCollectionUid)) {
138 try {
139 $fileCollection = $this->getFileCollectionRepository()->findByUid($fileCollectionUid);
140
141 if ($fileCollection instanceof \TYPO3\CMS\Core\Resource\Collection\AbstractFileCollection) {
142 $fileCollection->loadContents();
143 $files = $fileCollection->getItems();
144
145 $this->addFileObjects($files);
146 }
147 } catch (Exception $e) {
148 $this->getLogger()->warning(
149 'The file-collection with uid "' . $fileCollectionUid
150 . '" could not be found or contents could not be loaded and won\'t be included in frontend output.',
151 array('exception' => $e)
152 );
153 }
154 }
155 }
156
157 /**
158 * Add files to the collection from multiple folders
159 *
160 * @param array $folderIdentifiers The folder identifiers
161 * @return void
162 */
163 public function addFilesFromFolders(array $folderIdentifiers = array()) {
164 foreach ($folderIdentifiers as $folderIdentifier) {
165 $this->addFilesFromFolder($folderIdentifier);
166 }
167 }
168
169 /**
170 * Add files to the collection from one single folder
171 *
172 * @param string $folderIdentifier The folder identifier
173 */
174 public function addFilesFromFolder($folderIdentifier) {
175 if ($folderIdentifier) {
176 try {
177 $folder = $this->getResourceFactory()->getFolderObjectFromCombinedIdentifier($folderIdentifier);
178 if ($folder instanceof Folder) {
179 $files = $folder->getFiles();
180
181 $this->addFileObjects($files);
182 }
183 } catch (Exception $e) {
184 $this->getLogger()->warning(
185 'The folder with identifier "' . $folderIdentifier
186 . '" could not be found and won\'t be included in frontend output',
187 array('exception' => $e)
188 );
189 }
190 }
191 }
192
193 /**
194 * Sort the file objects based on a property
195 *
196 * @param string $sortingProperty The sorting property
197 * @param string $sortingOrder can be ascending or descending or "random"
198 * @return void
199 */
200 public function sort($sortingProperty = '', $sortingOrder = 'ascending') {
201 if ($sortingProperty !== '' && count($this->files) > 1) {
202 @usort(
203 $this->files,
204 function(
205 FileInterface $a,
206 FileInterface $b
207 ) use($sortingProperty) {
208 if ($a->hasProperty($sortingProperty) && $b->hasProperty($sortingProperty)) {
209 return strnatcasecmp($a->getProperty($sortingProperty), $b->getProperty($sortingProperty));
210 } else {
211 return 0;
212 }
213 }
214 );
215
216 switch (strtolower($sortingOrder)) {
217 case 'descending':
218 case 'desc':
219 $this->files = array_reverse($this->files);
220 break;
221 case 'random':
222 case 'rand':
223 shuffle($this->files);
224 break;
225 }
226 }
227 }
228
229 /**
230 * Add a file object to the collection
231 *
232 * @param FileInterface $file The file object
233 * @return void
234 */
235 public function addFileObject(FileInterface $file) {
236 $this->files[] = $file;
237 }
238
239 /**
240 * Add multiple file objects to the collection
241 *
242 * @param FileInterface[] $files The file objects
243 * @return void
244 */
245 public function addFileObjects($files) {
246 $this->files = array_merge($this->files, $files);
247 }
248
249 /**
250 * Final getter method to fetch the accumulated data
251 *
252 * @return array
253 */
254 public function getFiles() {
255 return $this->files;
256 }
257
258 /**
259 * @return int
260 */
261 public function count() {
262 return count($this->files);
263 }
264
265 /**
266 * @return \TYPO3\CMS\Core\Log\Logger
267 */
268 protected function getLogger() {
269 return GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
270 }
271
272 /**
273 * @return ResourceFactory
274 */
275 protected function getResourceFactory() {
276 if ($this->resourceFactory === NULL) {
277 $this->resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
278 }
279 return $this->resourceFactory;
280 }
281
282 /**
283 * @return FileCollectionRepository
284 */
285 protected function getFileCollectionRepository() {
286 if ($this->fileCollectionRepository === NULL) {
287 $this->fileCollectionRepository = GeneralUtility::makeInstance(FileCollectionRepository::class);
288 }
289 return $this->fileCollectionRepository;
290 }
291
292 /**
293 * @return FileRepository
294 */
295 protected function getFileRepository() {
296 if ($this->fileRepository === NULL) {
297 $this->fileRepository = GeneralUtility::makeInstance(FileRepository::class);
298 }
299 return $this->fileRepository;
300 }
301 }