3d46ed3240c58623a5f6b1d9d71cb1a501711d44
[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($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, $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($fileReferenceUids = array()) {
112 if (!empty($fileReferenceUids)) {
113 foreach ($fileReferenceUids as $fileReferenceUid) {
114 $fileObject = $this->getFileRepository()->findFileReferenceByUid($fileReferenceUid);
115 $this->addFileObject($fileObject);
116 }
117 }
118 }
119
120 /**
121 * Add files to the collection from multiple file collections
122 *
123 * @param array $fileCollectionUids The file collections uids
124 * @return void
125 */
126 public function addFilesFromFileCollections($fileCollectionUids = array()) {
127 if (!empty($fileCollectionUids)) {
128 foreach ($fileCollectionUids as $fileCollectionUid) {
129 $this->addFilesFromFileCollection($fileCollectionUid);
130 }
131 }
132 }
133
134 /**
135 * Add files to the collection from one single file collection
136 *
137 * @param int $fileCollectionUid The file collections uid
138 * @return void
139 */
140 public function addFilesFromFileCollection($fileCollectionUid = NULL) {
141 if (!empty($fileCollectionUid)) {
142 try {
143 $fileCollection = $this->getFileCollectionRepository()->findByUid($fileCollectionUid);
144
145 if ($fileCollection instanceof \TYPO3\CMS\Core\Resource\Collection\AbstractFileCollection) {
146 $fileCollection->loadContents();
147 $files = $fileCollection->getItems();
148
149 $this->addFileObjects($files);
150 }
151 } catch (Exception $e) {
152 $this->getLogger()->warning(
153 'The file-collection with uid "' . $fileCollectionUid
154 . '" could not be found or contents could not be loaded and won\'t be included in frontend output.',
155 array('exception' => $e)
156 );
157 }
158 }
159 }
160
161 /**
162 * Add files to the collection from multiple folders
163 *
164 * @param array $folderIdentifiers The folder identifiers
165 * @return void
166 */
167 public function addFilesFromFolders($folderIdentifiers = array()) {
168 if (!empty($folderIdentifiers)) {
169 foreach ($folderIdentifiers as $folderIdentifier) {
170 $this->addFilesFromFolder($folderIdentifier);
171 }
172 }
173 }
174
175 /**
176 * Add files to the collection from one single folder
177 *
178 * @param string $folderIdentifier The folder identifier
179 */
180 public function addFilesFromFolder($folderIdentifier) {
181 if ($folderIdentifier) {
182 try {
183 $folder = $this->getResourceFactory()->getFolderObjectFromCombinedIdentifier($folderIdentifier);
184 if ($folder instanceof Folder) {
185 $files = $folder->getFiles();
186
187 $this->addFileObjects($files);
188 }
189 } catch (Exception $e) {
190 $this->getLogger()->warning(
191 'The folder with identifier "' . $folderIdentifier
192 . '" could not be found and won\'t be included in frontend output',
193 array('exception' => $e)
194 );
195 }
196 }
197 }
198
199 /**
200 * Sort the file objects based on a property
201 *
202 * @param string $sortingProperty The sorting property
203 * @param string $sortingOrder can be ascending or descending or "random"
204 * @return void
205 */
206 public function sort($sortingProperty = '', $sortingOrder = 'ascending') {
207 if ($sortingProperty !== '' && count($this->files) > 1) {
208 @usort(
209 $this->files,
210 function(
211 FileInterface $a,
212 FileInterface $b
213 ) use($sortingProperty) {
214 if ($a->hasProperty($sortingProperty) && $b->hasProperty($sortingProperty)) {
215 return strnatcasecmp($a->getProperty($sortingProperty), $b->getProperty($sortingProperty));
216 } else {
217 return 0;
218 }
219 }
220 );
221
222 switch (strtolower($sortingOrder)) {
223 case 'descending':
224 case 'desc':
225 $this->files = array_reverse($this->files);
226 break;
227 case 'random':
228 case 'rand':
229 shuffle($this->files);
230 break;
231 }
232 }
233 }
234
235 /**
236 * Add a file object to the collection
237 *
238 * @param FileInterface $file The file object
239 * @return void
240 */
241 public function addFileObject(FileInterface $file) {
242 $this->files[] = $file;
243 }
244
245 /**
246 * Add multiple file objects to the collection
247 *
248 * @param FileInterface[] $files The file objects
249 * @return void
250 */
251 public function addFileObjects($files) {
252 $this->files = array_merge($this->files, $files);
253 }
254
255 /**
256 * Final getter method to fetch the accumulated data
257 *
258 * @return array
259 */
260 public function getFiles() {
261 return $this->files;
262 }
263
264 /**
265 * @return int
266 */
267 public function count() {
268 return count($this->files);
269 }
270
271 /**
272 * @return \TYPO3\CMS\Core\Log\Logger
273 */
274 protected function getLogger() {
275 return GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
276 }
277
278 /**
279 * @return ResourceFactory
280 */
281 protected function getResourceFactory() {
282 if ($this->resourceFactory === NULL) {
283 $this->resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
284 }
285 return $this->resourceFactory;
286 }
287
288 /**
289 * @return FileCollectionRepository
290 */
291 protected function getFileCollectionRepository() {
292 if ($this->fileCollectionRepository === NULL) {
293 $this->fileCollectionRepository = GeneralUtility::makeInstance(FileCollectionRepository::class);
294 }
295 return $this->fileCollectionRepository;
296 }
297
298 /**
299 * @return FileRepository
300 */
301 protected function getFileRepository() {
302 if ($this->fileRepository === NULL) {
303 $this->fileRepository = GeneralUtility::makeInstance(FileRepository::class);
304 }
305 return $this->fileRepository;
306 }
307 }