[BUGFIX] FILES.folder does not work
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / ContentObject / FilesContentObject.php
1 <?php
2 namespace TYPO3\CMS\Frontend\ContentObject;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2012-2013 Ingmar Schlecht <ingmar@typo3.org>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29
30 use TYPO3\CMS\Core\Utility\GeneralUtility;
31 use TYPO3\CMS\Core\Utility\MathUtility;
32
33 /**
34 * Contains FILES content object
35 *
36 * @author Ingmar Schlecht <ingmar@typo3.org>
37 */
38 class FilesContentObject extends \TYPO3\CMS\Frontend\ContentObject\AbstractContentObject {
39
40 /**
41 * @var \TYPO3\CMS\Core\Resource\FileCollectionRepository|NULL
42 */
43 protected $collectionRepository = NULL;
44
45 /**
46 * @var \TYPO3\CMS\Core\Resource\ResourceFactory|NULL
47 */
48 protected $fileFactory = NULL;
49
50 /**
51 * @var \TYPO3\CMS\Core\Resource\FileRepository|NULL
52 */
53 protected $fileRepository = NULL;
54
55 /**
56 * Rendering the cObject FILES
57 *
58 * @param array $conf Array of TypoScript properties
59 * @return string Output
60 */
61 public function render($conf = array()) {
62 $fileObjects = array();
63 // Getting the files
64 if ($conf['references'] || $conf['references.']) {
65 /*
66 The TypoScript could look like this:# all items related to the page.media field:
67 references {
68 table = pages
69 uid.data = page:uid
70 fieldName = media
71 }# or: sys_file_references with uid 27:
72 references = 27
73 */
74 $referencesUid = $this->stdWrapValue('references', $conf);
75 $referencesUidArray = GeneralUtility::intExplode(',', $referencesUid, TRUE);
76 foreach ($referencesUidArray as $referenceUid) {
77 try {
78 $this->addToArray($this->getFileRepository()->findFileReferenceByUid($referenceUid), $fileObjects);
79 } catch (\TYPO3\CMS\Core\Resource\Exception $e) {
80 /** @var \TYPO3\CMS\Core\Log\Logger $logger */
81 $logger = GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager')->getLogger();
82 $logger->warning('The file-reference with uid "' . $referenceUid . '" could not be found and won\'t be included in frontend output');
83 }
84 }
85
86 // It's important that this always stays "fieldName" and not be renamed to "field" as it would otherwise collide with the stdWrap key of that name
87 if (!empty($conf['references.'])) {
88 $referencesFieldName = $this->stdWrapValue('fieldName', $conf['references.']);
89 if ($referencesFieldName) {
90 $table = $this->cObj->getCurrentTable();
91 if ($table === 'pages' && isset($this->cObj->data['_LOCALIZED_UID']) && intval($this->cObj->data['sys_language_uid']) > 0) {
92 $table = 'pages_language_overlay';
93 }
94 $referencesForeignTable = $this->stdWrapValue('table', $conf['references.'], $table);
95 $referencesForeignUid = $this->stdWrapValue('uid', $conf['references.'], isset($this->cObj->data['_LOCALIZED_UID']) ? $this->cObj->data['_LOCALIZED_UID'] : $this->cObj->data['uid']);
96 $this->addToArray($this->getFileRepository()->findByRelation($referencesForeignTable, $referencesFieldName, $referencesForeignUid), $fileObjects);
97 }
98 }
99 }
100 if ($conf['files'] || $conf['files.']) {
101 /*
102 The TypoScript could look like this:
103 # with sys_file UIDs:
104 files = 12,14,15# using stdWrap:
105 files.field = some_field
106 */
107 $fileUids = GeneralUtility::intExplode(',', $this->stdWrapValue('files', $conf), TRUE);
108 foreach ($fileUids as $fileUid) {
109 try {
110 $this->addToArray($this->getFileRepository()->findByUid($fileUid), $fileObjects);
111 } catch (\TYPO3\CMS\Core\Resource\Exception $e) {
112 /** @var \TYPO3\CMS\Core\Log\Logger $logger */
113 $logger = GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager')->getLogger();
114 $logger->warning('The file with uid "' . $fileUid . '" could not be found and won\'t be included in frontend output');
115 }
116 }
117 }
118 if ($conf['collections'] || $conf['collections.']) {
119 $collectionUids = GeneralUtility::intExplode(',', $this->stdWrapValue('collections', $conf), TRUE);
120 foreach ($collectionUids as $collectionUid) {
121 try {
122 $fileCollection = $this->getCollectionRepository()->findByUid($collectionUid);
123 if ($fileCollection instanceof \TYPO3\CMS\Core\Resource\Collection\AbstractFileCollection) {
124 $fileCollection->loadContents();
125 $this->addToArray($fileCollection->getItems(), $fileObjects);
126 }
127 } catch (\TYPO3\CMS\Core\Resource\Exception $e) {
128 /** @var \TYPO3\CMS\Core\Log\Logger $logger */
129 $logger = GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager')->getLogger();
130 $logger->warning('The file-collection with uid "' . $collectionUid . '" could not be found or contents could not be loaded and won\'t be included in frontend output');
131 }
132 }
133 }
134 if ($conf['folders'] || $conf['folders.']) {
135 $folderIdentifiers = GeneralUtility::trimExplode(',', $this->stdWrapValue('folders', $conf));
136 foreach ($folderIdentifiers as $folderIdentifier) {
137 if ($folderIdentifier) {
138 try {
139 $folder = $this->getFileFactory()->getFolderObjectFromCombinedIdentifier($folderIdentifier);
140 if ($folder instanceof \TYPO3\CMS\Core\Resource\Folder) {
141 $this->addToArray(array_values($folder->getFiles()), $fileObjects);
142 }
143 } catch (\TYPO3\CMS\Core\Resource\Exception $e) {
144 /** @var \TYPO3\CMS\Core\Log\Logger $logger */
145 $logger = GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager')->getLogger();
146 $logger->warning('The folder with identifier "' . $folderIdentifier . '" could not be found and won\'t be included in frontend output');
147 }
148 }
149 }
150 }
151 // Rendering the files
152 $content = '';
153 // optionSplit applied to conf to allow differnt settings per file
154 $splitConf = $GLOBALS['TSFE']->tmpl->splitConfArray($conf, count($fileObjects));
155
156 // Enable sorting for multiple fileObjects
157 $sortingProperty = '';
158 if ($conf['sorting'] || $conf['sorting.']) {
159 $sortingProperty = $this->stdWrapValue('sorting', $conf);
160 }
161 if ($sortingProperty !== '' && count($fileObjects) > 1) {
162 @usort($fileObjects, function(\TYPO3\CMS\Core\Resource\FileInterface $a, \TYPO3\CMS\Core\Resource\FileInterface $b) use($sortingProperty) {
163 if ($a->hasProperty($sortingProperty) && $b->hasProperty($sortingProperty)) {
164 return strnatcasecmp($a->getProperty($sortingProperty), $b->getProperty($sortingProperty));
165 } else {
166 return 0;
167 }
168 });
169 if (is_array($conf['sorting.']) && isset($conf['sorting.']['direction']) && strtolower($conf['sorting.']['direction']) === 'desc') {
170 $fileObjects = array_reverse($fileObjects);
171 }
172 }
173
174 $availableFileObjectCount = count($fileObjects);
175
176 $start = 0;
177 if (!empty($conf['begin'])) {
178 $start = intval($conf['begin']);
179 }
180 if (!empty($conf['begin.'])) {
181 $start = intval($this->cObj->stdWrap($start, $conf['begin.']));
182 }
183 $start = MathUtility::forceIntegerInRange($start, 0, $availableFileObjectCount);
184
185 $limit = $availableFileObjectCount;
186 if (!empty($conf['maxItems'])) {
187 $limit = intval($conf['maxItems']);
188 }
189 if (!empty($conf['maxItems.'])) {
190 $limit = intval($this->cObj->stdWrap($limit, $conf['maxItems.']));
191 }
192
193 $end = MathUtility::forceIntegerInRange($start + $limit, $start, $availableFileObjectCount);
194
195 $GLOBALS['TSFE']->register['FILES_COUNT'] = min($limit, $availableFileObjectCount);
196 $fileObjectCounter = 0;
197 $keys = array_keys($fileObjects);
198 for ($i = $start; $i < $end; $i++) {
199 $key = $keys[$i];
200 $fileObject = $fileObjects[$key];
201
202 $GLOBALS['TSFE']->register['FILE_NUM_CURRENT'] = $fileObjectCounter;
203 $this->cObj->setCurrentFile($fileObject);
204 $content .= $this->cObj->cObjGetSingle($splitConf[$key]['renderObj'], $splitConf[$key]['renderObj.']);
205 $fileObjectCounter++;
206 }
207 $content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
208 return $content;
209 }
210
211 /**
212 * Sets the file factory.
213 *
214 * @param \TYPO3\CMS\Core\Resource\ResourceFactory $fileFactory
215 * @return void
216 */
217 public function setFileFactory($fileFactory) {
218 $this->fileFactory = $fileFactory;
219 }
220
221 /**
222 * Returns the file factory.
223 *
224 * @return \TYPO3\CMS\Core\Resource\ResourceFactory
225 */
226 public function getFileFactory() {
227 if ($this->fileFactory === NULL) {
228 $this->fileFactory = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\ResourceFactory');
229 }
230
231 return $this->fileFactory;
232 }
233
234 /**
235 * Sets the file repository.
236 *
237 * @param \TYPO3\CMS\Core\Resource\FileRepository $fileRepository
238 * @return void
239 */
240 public function setFileRepository($fileRepository) {
241 $this->fileRepository = $fileRepository;
242 }
243
244 /**
245 * Returns the file repository.
246 *
247 * @return \TYPO3\CMS\Core\Resource\FileRepository
248 */
249 public function getFileRepository() {
250 if ($this->fileRepository === NULL) {
251 $this->fileRepository = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\FileRepository');
252 }
253
254 return $this->fileRepository;
255 }
256
257 /**
258 * Sets the collection repository.
259 *
260 * @param \TYPO3\CMS\Core\Resource\FileCollectionRepository $collectionRepository
261 * @return void
262 */
263 public function setCollectionRepository($collectionRepository) {
264 $this->collectionRepository = $collectionRepository;
265 }
266
267 /**
268 * Returns the collection repository.
269 *
270 * @return \TYPO3\CMS\Core\Resource\FileCollectionRepository
271 */
272 public function getCollectionRepository() {
273 if ($this->collectionRepository === NULL) {
274 $this->collectionRepository = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\FileCollectionRepository');
275 }
276
277 return $this->collectionRepository;
278 }
279
280 /**
281 * Adds $newItems to $theArray, which is passed by reference. Array must only consist of numerical keys.
282 *
283 * @param mixed $newItems Array with new items or single object that's added.
284 * @param array $theArray The array the new items should be added to. Must only contain numeric keys (for array_merge() to add items instead of replacing).
285 */
286 protected function addToArray($newItems, array &$theArray) {
287 if (is_array($newItems)) {
288 $theArray = array_merge($theArray, $newItems);
289 } elseif (is_object($newItems)) {
290 $theArray[] = $newItems;
291 }
292 }
293
294 /**
295 * Gets a configuration value by passing them through stdWrap first and taking a default value if stdWrap doesn't yield a result.
296 *
297 * @param string $key The config variable key (from TS array).
298 * @param array $config The TypoScript array.
299 * @param string $defaultValue Optional default value.
300 * @return string Value of the config variable
301 */
302 protected function stdWrapValue($key, array $config, $defaultValue = '') {
303 $stdWrapped = $this->cObj->stdWrap($config[$key], $config[$key . '.']);
304 return $stdWrapped ? $stdWrapped : $defaultValue;
305 }
306
307 }