7652b8795583bf5d6ac8094a89eadb7edbeaf58e
[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 text file 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(
79 $this->getFileFactory()->getFileReferenceObject($referenceUid),
80 $fileObjects
81 );
82 } catch (\TYPO3\CMS\Core\Resource\Exception $e) {
83 /** @var \TYPO3\CMS\Core\Log\Logger $logger */
84 $logger = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Log\\LogManager')->getLogger(__CLASS__);
85 $logger->warning('The file-reference with uid "' . $referenceUid . '" could not be found and won\'t be included in frontend output');
86 }
87 }
88
89 // 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
90 if (!empty($conf['references.'])) {
91 $referencesFieldName = $this->stdWrapValue('fieldName', $conf['references.']);
92 if ($referencesFieldName) {
93 $table = $this->cObj->getCurrentTable();
94 if ($table === 'pages' && isset($this->cObj->data['_LOCALIZED_UID']) && (int)$this->cObj->data['sys_language_uid'] > 0) {
95 $table = 'pages_language_overlay';
96 }
97 $referencesForeignTable = $this->stdWrapValue('table', $conf['references.'], $table);
98 $referencesForeignUid = $this->stdWrapValue('uid', $conf['references.'], isset($this->cObj->data['_LOCALIZED_UID']) ? $this->cObj->data['_LOCALIZED_UID'] : $this->cObj->data['uid']);
99 $this->addToArray($this->getFileRepository()->findByRelation($referencesForeignTable, $referencesFieldName, $referencesForeignUid), $fileObjects);
100 }
101 }
102 }
103 if ($conf['files'] || $conf['files.']) {
104 /*
105 The TypoScript could look like this:
106 # with sys_file UIDs:
107 files = 12,14,15# using stdWrap:
108 files.field = some_field
109 */
110 $fileUids = GeneralUtility::intExplode(',', $this->stdWrapValue('files', $conf), TRUE);
111 foreach ($fileUids as $fileUid) {
112 try {
113 $this->addToArray($this->getFileFactory()->getFileObject($fileUid), $fileObjects);
114 } catch (\TYPO3\CMS\Core\Resource\Exception $e) {
115 /** @var \TYPO3\CMS\Core\Log\Logger $logger */
116 $logger = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Log\\LogManager')->getLogger(__CLASS__);
117 $logger->warning('The file with uid "' . $fileUid . '" could not be found and won\'t be included in frontend output');
118 }
119 }
120 }
121 if ($conf['collections'] || $conf['collections.']) {
122 $collectionUids = GeneralUtility::intExplode(',', $this->stdWrapValue('collections', $conf), TRUE);
123 foreach ($collectionUids as $collectionUid) {
124 try {
125 $fileCollection = $this->getCollectionRepository()->findByUid($collectionUid);
126 if ($fileCollection instanceof \TYPO3\CMS\Core\Resource\Collection\AbstractFileCollection) {
127 $fileCollection->loadContents();
128 $this->addToArray($fileCollection->getItems(), $fileObjects);
129 }
130 } catch (\TYPO3\CMS\Core\Resource\Exception $e) {
131 /** @var \TYPO3\CMS\Core\Log\Logger $logger */
132 $logger = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Log\\LogManager')->getLogger(__CLASS__);
133 $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');
134 }
135 }
136 }
137 if ($conf['folders'] || $conf['folders.']) {
138 $folderIdentifiers = GeneralUtility::trimExplode(',', $this->stdWrapValue('folders', $conf));
139 foreach ($folderIdentifiers as $folderIdentifier) {
140 if ($folderIdentifier) {
141 try {
142 $folder = $this->getFileFactory()->getFolderObjectFromCombinedIdentifier($folderIdentifier);
143 if ($folder instanceof \TYPO3\CMS\Core\Resource\Folder) {
144 $this->addToArray(array_values($folder->getFiles()), $fileObjects);
145 }
146 } catch (\TYPO3\CMS\Core\Resource\Exception $e) {
147 /** @var \TYPO3\CMS\Core\Log\Logger $logger */
148 $logger = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Log\\LogManager')->getLogger(__CLASS__);
149 $logger->warning('The folder with identifier "' . $folderIdentifier . '" could not be found and won\'t be included in frontend output');
150 }
151 }
152 }
153 }
154 // Rendering the files
155 $content = '';
156 // optionSplit applied to conf to allow differnt settings per file
157 $splitConf = $GLOBALS['TSFE']->tmpl->splitConfArray($conf, count($fileObjects));
158
159 // Enable sorting for multiple fileObjects
160 $sortingProperty = '';
161 if ($conf['sorting'] || $conf['sorting.']) {
162 $sortingProperty = $this->stdWrapValue('sorting', $conf);
163 }
164 if ($sortingProperty !== '' && count($fileObjects) > 1) {
165 @usort($fileObjects, function(\TYPO3\CMS\Core\Resource\FileInterface $a, \TYPO3\CMS\Core\Resource\FileInterface $b) use($sortingProperty) {
166 if ($a->hasProperty($sortingProperty) && $b->hasProperty($sortingProperty)) {
167 return strnatcasecmp($a->getProperty($sortingProperty), $b->getProperty($sortingProperty));
168 } else {
169 return 0;
170 }
171 });
172 if (is_array($conf['sorting.']) && isset($conf['sorting.']['direction']) && strtolower($conf['sorting.']['direction']) === 'desc') {
173 $fileObjects = array_reverse($fileObjects);
174 }
175 }
176
177 $availableFileObjectCount = count($fileObjects);
178
179 $start = 0;
180 if (!empty($conf['begin'])) {
181 $start = (int)$conf['begin'];
182 }
183 if (!empty($conf['begin.'])) {
184 $start = (int)$this->cObj->stdWrap($start, $conf['begin.']);
185 }
186 $start = MathUtility::forceIntegerInRange($start, 0, $availableFileObjectCount);
187
188 $limit = $availableFileObjectCount;
189 if (!empty($conf['maxItems'])) {
190 $limit = (int)$conf['maxItems'];
191 }
192 if (!empty($conf['maxItems.'])) {
193 $limit = (int)$this->cObj->stdWrap($limit, $conf['maxItems.']);
194 }
195
196 $end = MathUtility::forceIntegerInRange($start + $limit, $start, $availableFileObjectCount);
197
198 $GLOBALS['TSFE']->register['FILES_COUNT'] = min($limit, $availableFileObjectCount);
199 $fileObjectCounter = 0;
200 $keys = array_keys($fileObjects);
201 for ($i = $start; $i < $end; $i++) {
202 $key = $keys[$i];
203 $fileObject = $fileObjects[$key];
204
205 $GLOBALS['TSFE']->register['FILE_NUM_CURRENT'] = $fileObjectCounter;
206 $this->cObj->setCurrentFile($fileObject);
207 $content .= $this->cObj->cObjGetSingle($splitConf[$key]['renderObj'], $splitConf[$key]['renderObj.']);
208 $fileObjectCounter++;
209 }
210 $content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
211 return $content;
212 }
213
214 /**
215 * Sets the file factory.
216 *
217 * @param \TYPO3\CMS\Core\Resource\ResourceFactory $fileFactory
218 * @return void
219 */
220 public function setFileFactory($fileFactory) {
221 $this->fileFactory = $fileFactory;
222 }
223
224 /**
225 * Returns the file factory.
226 *
227 * @return \TYPO3\CMS\Core\Resource\ResourceFactory
228 */
229 public function getFileFactory() {
230 if ($this->fileFactory === NULL) {
231 $this->fileFactory = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\ResourceFactory');
232 }
233
234 return $this->fileFactory;
235 }
236
237 /**
238 * Sets the file repository.
239 *
240 * @param \TYPO3\CMS\Core\Resource\FileRepository $fileRepository
241 * @return void
242 */
243 public function setFileRepository($fileRepository) {
244 $this->fileRepository = $fileRepository;
245 }
246
247 /**
248 * Returns the file repository.
249 *
250 * @return \TYPO3\CMS\Core\Resource\FileRepository
251 */
252 public function getFileRepository() {
253 if ($this->fileRepository === NULL) {
254 $this->fileRepository = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\FileRepository');
255 }
256
257 return $this->fileRepository;
258 }
259
260 /**
261 * Sets the collection repository.
262 *
263 * @param \TYPO3\CMS\Core\Resource\FileCollectionRepository $collectionRepository
264 * @return void
265 */
266 public function setCollectionRepository($collectionRepository) {
267 $this->collectionRepository = $collectionRepository;
268 }
269
270 /**
271 * Returns the collection repository.
272 *
273 * @return \TYPO3\CMS\Core\Resource\FileCollectionRepository
274 */
275 public function getCollectionRepository() {
276 if ($this->collectionRepository === NULL) {
277 $this->collectionRepository = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\FileCollectionRepository');
278 }
279
280 return $this->collectionRepository;
281 }
282
283 /**
284 * Adds $newItems to $theArray, which is passed by reference. Array must only consist of numerical keys.
285 *
286 * @param mixed $newItems Array with new items or single object that's added.
287 * @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).
288 */
289 protected function addToArray($newItems, array &$theArray) {
290 if (is_array($newItems)) {
291 $theArray = array_merge($theArray, $newItems);
292 } elseif (is_object($newItems)) {
293 $theArray[] = $newItems;
294 }
295 }
296
297 /**
298 * Gets a configuration value by passing them through stdWrap first and taking a default value if stdWrap doesn't yield a result.
299 *
300 * @param string $key The config variable key (from TS array).
301 * @param array $config The TypoScript array.
302 * @param string $defaultValue Optional default value.
303 * @return string Value of the config variable
304 */
305 protected function stdWrapValue($key, array $config, $defaultValue = '') {
306 $stdWrapped = $this->cObj->stdWrap($config[$key], $config[$key . '.']);
307 return $stdWrapped ? $stdWrapped : $defaultValue;
308 }
309
310 }