[FEATURE] Add begin/maxItems options to FILES ContentObject
[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 * Rendering the cObject FILES
42 *
43 * @param array $conf Array of TypoScript properties
44 * @return string Output
45 */
46 public function render($conf = array()) {
47 /** @var \TYPO3\CMS\Core\Resource\FileRepository $fileRepository */
48 $fileRepository = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\FileRepository');
49 $fileObjects = array();
50 // Getting the files
51 if ($conf['references'] || $conf['references.']) {
52 /*
53 The TypoScript could look like this:# all items related to the page.media field:
54 references {
55 table = pages
56 uid.data = page:uid
57 fieldName = media
58 }# or: sys_file_references with uid 27:
59 references = 27
60 */
61 $referencesUid = $this->stdWrapValue('references', $conf);
62 $referencesUidArray = GeneralUtility::intExplode(',', $referencesUid, TRUE);
63 foreach ($referencesUidArray as $referenceUid) {
64 try {
65 $this->addToArray($fileRepository->findFileReferenceByUid($referenceUid), $fileObjects);
66 } catch (\TYPO3\CMS\Core\Resource\Exception $e) {
67 /** @var \TYPO3\CMS\Core\Log\Logger $logger */
68 $logger = GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager')->getLogger();
69 $logger->warning('The file-reference with uid "' . $referenceUid . '" could not be found and won\'t be included in frontend output');
70 }
71 }
72
73 // 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
74 $referencesFieldName = $this->stdWrapValue('fieldName', $conf['references.']);
75 if ($referencesFieldName) {
76 $table = $this->cObj->getCurrentTable();
77 if ($table === 'pages' && isset($this->cObj->data['_LOCALIZED_UID']) && intval($this->cObj->data['sys_language_uid']) > 0) {
78 $table = 'pages_language_overlay';
79 }
80 $referencesForeignTable = $this->stdWrapValue('table', $conf['references.'], $table);
81 $referencesForeignUid = $this->stdWrapValue('uid', $conf['references.'], isset($this->cObj->data['_LOCALIZED_UID']) ? $this->cObj->data['_LOCALIZED_UID'] : $this->cObj->data['uid']);
82 $this->addToArray($fileRepository->findByRelation($referencesForeignTable, $referencesFieldName, $referencesForeignUid), $fileObjects);
83 }
84 }
85 if ($conf['files'] || $conf['files.']) {
86 /*
87 The TypoScript could look like this:
88 # with sys_file UIDs:
89 files = 12,14,15# using stdWrap:
90 files.field = some_field
91 */
92 $fileUids = GeneralUtility::trimExplode(',', $this->stdWrapValue('files', $conf), TRUE);
93 foreach ($fileUids as $fileUid) {
94 try {
95 $this->addToArray($fileRepository->findByUid($fileUid), $fileObjects);
96 } catch (\TYPO3\CMS\Core\Resource\Exception $e) {
97 /** @var \TYPO3\CMS\Core\Log\Logger $logger */
98 $logger = GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager')->getLogger();
99 $logger->warning('The file with uid "' . $fileUid . '" could not be found and won\'t be included in frontend output');
100 }
101 }
102 }
103 if ($conf['collections'] || $conf['collections.']) {
104 $collectionUids = GeneralUtility::trimExplode(',', $this->stdWrapValue('collections', $conf), TRUE);
105 /** @var \TYPO3\CMS\Core\Resource\FileCollectionRepository $collectionRepository */
106 $collectionRepository = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\FileCollectionRepository');
107 foreach ($collectionUids as $collectionUid) {
108 try {
109 $fileCollection = $collectionRepository->findByUid($collectionUid);
110 if ($fileCollection instanceof \TYPO3\CMS\Core\Resource\Collection\AbstractFileCollection) {
111 $fileCollection->loadContents();
112 $this->addToArray($fileCollection->getItems(), $fileObjects);
113 }
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();
117 $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');
118 }
119 }
120 }
121 if ($conf['folders'] || $conf['folders.']) {
122 $folderIdentifiers = GeneralUtility::trimExplode(',', $this->stdWrapValue('folders', $conf));
123 /** @var \TYPO3\CMS\Core\Resource\ResourceFactory $fileFactory */
124 $fileFactory = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\ResourceFactory');
125 foreach ($folderIdentifiers as $folderIdentifier) {
126 if ($folderIdentifier) {
127 try {
128 $folder = $fileFactory->getFolderObjectFromCombinedIdentifier($folderIdentifier);
129 if ($folder instanceof \TYPO3\CMS\Core\Resource\Folder) {
130 $this->addToArray($folder->getFiles(), $fileObjects);
131 }
132 } catch (\TYPO3\CMS\Core\Resource\Exception $e) {
133 /** @var \TYPO3\CMS\Core\Log\Logger $logger */
134 $logger = GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager')->getLogger();
135 $logger->warning('The folder with identifier "' . $folderIdentifier . '" could not be found and won\'t be included in frontend output');
136 }
137 }
138 }
139 }
140 // Rendering the files
141 $content = '';
142 // optionSplit applied to conf to allow differnt settings per file
143 $splitConf = $GLOBALS['TSFE']->tmpl->splitConfArray($conf, count($fileObjects));
144
145 // Enable sorting for multiple fileObjects
146 $sortingProperty = '';
147 if ($conf['sorting'] || $conf['sorting.']) {
148 $sortingProperty = $this->stdWrapValue('sorting', $conf);
149 }
150 if ($sortingProperty !== '' && count($fileObjects) > 1) {
151 usort($fileObjects, function(\TYPO3\CMS\Core\Resource\FileInterface $a, \TYPO3\CMS\Core\Resource\FileInterface $b) use($sortingProperty) {
152 if ($a->hasProperty($sortingProperty) && $b->hasProperty($sortingProperty)) {
153 return strnatcasecmp($a->getProperty($sortingProperty), $b->getProperty($sortingProperty));
154 } else {
155 return 0;
156 }
157 });
158 }
159
160 $availableFileObjectCount = count($fileObjects);
161
162 $start = 0;
163 if (array_key_exists('begin', $conf)) {
164 $start = intval($conf['begin']);
165 }
166 if (array_key_exists('begin.', $conf)) {
167 $start = intval($this->cObj->stdWrap($start, $conf['begin.']));
168 }
169 $start = MathUtility::forceIntegerInRange($start, 0, $availableFileObjectCount);
170
171 $limit = $availableFileObjectCount;
172 if (array_key_exists('maxItems', $conf)) {
173 $limit = intval($conf['maxItems']);
174 }
175 if (array_key_exists('maxItems.', $conf)) {
176 $limit = intval($this->cObj->stdWrap($limit, $conf['maxItems.']));
177 }
178
179 $end = MathUtility::forceIntegerInRange($start + $limit, 0, $availableFileObjectCount);
180
181 $GLOBALS['TSFE']->register['FILES_COUNT'] = $limit < $availableFileObjectCount ? $limit : $availableFileObjectCount;
182 $fileObjectCounter = 0;
183 $keys = array_keys($fileObjects);
184 for ($i = $start; $i < $end; $i++) {
185 $key = $keys[$i];
186 $fileObject = $fileObjects[$key];
187
188 $GLOBALS['TSFE']->register['FILE_NUM_CURRENT'] = $fileObjectCounter;
189 $this->cObj->setCurrentFile($fileObject);
190 $content .= $this->cObj->cObjGetSingle($splitConf[$key]['renderObj'], $splitConf[$key]['renderObj.']);
191 $fileObjectCounter++;
192 }
193 $content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
194 return $content;
195 }
196
197 /**
198 * Adds $newItems to $theArray, which is passed by reference. Array must only consist of numerical keys.
199 *
200 * @param mixed $newItems Array with new items or single object that's added.
201 * @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).
202 */
203 protected function addToArray($newItems, array &$theArray) {
204 if (is_array($newItems)) {
205 $theArray = array_merge($theArray, $newItems);
206 } elseif (is_object($newItems)) {
207 $theArray[] = $newItems;
208 }
209 }
210
211 /**
212 * Gets a configuration value by passing them through stdWrap first and taking a default value if stdWrap doesn't yield a result.
213 *
214 * @param string $key The config variable key (from TS array).
215 * @param array $config The TypoScript array.
216 * @param string $defaultValue Optional default value.
217 * @return string Value of the config variable
218 */
219 protected function stdWrapValue($key, array $config, $defaultValue = '') {
220 $stdWrapped = $this->cObj->stdWrap($config[$key], $config[$key . '.']);
221 return $stdWrapped ? $stdWrapped : $defaultValue;
222 }
223
224 }