Completed
Push — master ( 8e078a...edce3c )
by
unknown
15:28
created

FilesContentObject::addFileReferences()   B

Complexity

Conditions 7
Paths 13

Size

Total Lines 31
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 15
nc 13
nop 3
dl 0
loc 31
rs 8.8333
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
 * It is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License, either version 2
8
 * of the License, or any later version.
9
 *
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
 * The TYPO3 project - inspiring people to share!
14
 */
15
16
namespace TYPO3\CMS\Frontend\ContentObject;
17
18
use TYPO3\CMS\Core\TypoScript\TypoScriptService;
19
use TYPO3\CMS\Core\Utility\GeneralUtility;
20
use TYPO3\CMS\Core\Utility\MathUtility;
21
use TYPO3\CMS\Frontend\Resource\FileCollector;
22
23
/**
24
 * Contains FILES content object
25
 */
26
class FilesContentObject extends AbstractContentObject
27
{
28
    /**
29
     * Rendering the cObject FILES
30
     *
31
     * @param array $conf Array of TypoScript properties
32
     * @return string Output
33
     */
34
    public function render($conf = [])
35
    {
36
        if (!empty($conf['if.']) && !$this->cObj->checkIf($conf['if.'])) {
37
            return '';
38
        }
39
        // Store the original "currentFile" within a variable so it can be re-applied later-on
40
        $originalFileInContentObject = $this->cObj->getCurrentFile();
41
42
        $fileCollector = $this->findAndSortFiles($conf);
43
        $fileObjects = $fileCollector->getFiles();
44
        $availableFileObjectCount = count($fileObjects);
45
46
        // optionSplit applied to conf to allow different settings per file
47
        $splitConf = GeneralUtility::makeInstance(TypoScriptService::class)
48
            ->explodeConfigurationForOptionSplit($conf, $availableFileObjectCount);
49
50
        $start = (int)$this->cObj->stdWrapValue('begin', $conf, 0);
51
        $start = MathUtility::forceIntegerInRange($start, 0, $availableFileObjectCount);
52
53
        $limit = (int)$this->cObj->stdWrapValue('maxItems', $conf, $availableFileObjectCount);
54
        $end = MathUtility::forceIntegerInRange($start + $limit, $start, $availableFileObjectCount);
55
56
        if (isset($GLOBALS['TSFE'])) {
57
            $GLOBALS['TSFE']->register['FILES_COUNT'] = min($limit, $availableFileObjectCount);
58
        }
59
        $fileObjectCounter = 0;
60
        $keys = array_keys($fileObjects);
61
62
        $content = '';
63
        for ($i = $start; $i < $end; $i++) {
64
            $key = $keys[$i];
65
            $fileObject = $fileObjects[$key];
66
67
            if (isset($GLOBALS['TSFE'])) {
68
                $GLOBALS['TSFE']->register['FILE_NUM_CURRENT'] = $fileObjectCounter;
69
            }
70
            $this->cObj->setCurrentFile($fileObject);
71
            $content .= $this->cObj->cObjGetSingle($splitConf[$key]['renderObj'], $splitConf[$key]['renderObj.'], 'renderObj');
72
            $fileObjectCounter++;
73
        }
74
75
        // Reset current file within cObj to the original file after rendering output of FILES
76
        // so e.g. stdWrap is not working on the last current file applied, thus avoiding side-effects
77
        $this->cObj->setCurrentFile($originalFileInContentObject);
78
79
        return $this->cObj->stdWrap($content, $conf['stdWrap.'] ?? []);
80
    }
81
82
    /**
83
     * Function to check for references, collections, folders and
84
     * accumulates into one etc.
85
     *
86
     * @param array $conf
87
     * @return FileCollector
88
     */
89
    protected function findAndSortFiles(array $conf)
90
    {
91
        $fileCollector = $this->getFileCollector();
92
93
        // Getting the files
94
        if ((isset($conf['references']) && $conf['references']) || (isset($conf['references.']) && $conf['references.'])) {
95
            /*
96
            The TypoScript could look like this:
97
            # all items related to the page.media field:
98
            references {
99
                table = pages
100
                uid.data = page:uid
101
                fieldName = media
102
            }
103
            # or: sys_file_references with uid 27:
104
            references = 27
105
             */
106
            $referencesUidList = $this->cObj->stdWrapValue('references', $conf);
107
            $referencesUids = GeneralUtility::intExplode(',', $referencesUidList, true);
108
            $fileCollector->addFileReferences($referencesUids);
109
110
            if (!empty($conf['references.'])) {
111
                $this->addFileReferences($conf, (array)$this->cObj->data, $fileCollector);
112
            }
113
        }
114
115
        if ((isset($conf['files']) && $conf['files']) || (isset($conf['files.']) && $conf['files.'])) {
116
            /*
117
            The TypoScript could look like this:
118
            # with sys_file UIDs:
119
            files = 12,14,15# using stdWrap:
120
            files.field = some_field
121
             */
122
            $fileUids = GeneralUtility::intExplode(',', $this->cObj->stdWrapValue('files', $conf), true);
123
            $fileCollector->addFiles($fileUids);
124
        }
125
126
        if ((isset($conf['collections']) && $conf['collections']) || (isset($conf['collections.']) && $conf['collections.'])) {
127
            $collectionUids = GeneralUtility::intExplode(',', $this->cObj->stdWrapValue('collections', $conf), true);
128
            $fileCollector->addFilesFromFileCollections($collectionUids);
129
        }
130
131
        if ((isset($conf['folders']) && $conf['folders']) || (isset($conf['folders.']) && $conf['folders.'])) {
132
            $folderIdentifiers = GeneralUtility::trimExplode(',', $this->cObj->stdWrapValue('folders', $conf));
133
            $fileCollector->addFilesFromFolders($folderIdentifiers, !empty($conf['folders.']['recursive']));
134
        }
135
136
        // Enable sorting for multiple fileObjects
137
        $sortingProperty = $this->cObj->stdWrapValue('sorting', $conf);
138
        if ($sortingProperty !== '') {
139
            $sortingDirection = $this->cObj->stdWrapValue('direction', $conf['sorting.'] ?? []);
140
            $fileCollector->sort($sortingProperty, $sortingDirection);
141
        }
142
143
        return $fileCollector;
144
    }
145
146
    /**
147
     * Handles and resolves file references.
148
     *
149
     * @param array $configuration TypoScript configuration
150
     * @param array $element The parent element referencing to files
151
     * @param FileCollector $fileCollector
152
     */
153
    protected function addFileReferences(array $configuration, array $element, FileCollector $fileCollector)
154
    {
0 ignored issues
show
Coding Style introduced by
Expected 0 blank lines after opening function brace; 1 found
Loading history...
155
156
        // 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
157
        $referencesFieldName = $this->cObj->stdWrapValue('fieldName', $configuration['references.'] ?? []);
158
159
        // If no reference fieldName is set, there's nothing to do
160
        if (empty($referencesFieldName)) {
161
            return;
162
        }
163
164
        $currentId = !empty($element['uid']) ? $element['uid'] : 0;
165
        $tableName = $this->cObj->getCurrentTable();
166
167
        // Fetch the references of the default element
168
        $referencesForeignTable = $this->cObj->stdWrapValue('table', $configuration['references.'], $tableName);
169
        $referencesForeignUid = $this->cObj->stdWrapValue('uid', $configuration['references.'], $currentId);
170
171
        $pageRepository = $this->getPageRepository();
172
        // Fetch element if definition has been modified via TypoScript
173
        if ($referencesForeignTable !== $tableName || $referencesForeignUid !== $currentId) {
174
            $element = $pageRepository->getRawRecord($referencesForeignTable, $referencesForeignUid);
0 ignored issues
show
Bug introduced by
It seems like $referencesForeignUid can also be of type string; however, parameter $uid of TYPO3\CMS\Core\Domain\Re...ository::getRawRecord() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

174
            $element = $pageRepository->getRawRecord($referencesForeignTable, /** @scrutinizer ignore-type */ $referencesForeignUid);
Loading history...
175
176
            $pageRepository->versionOL($referencesForeignTable, $element, true);
0 ignored issues
show
Bug introduced by
It seems like $element can also be of type integer; however, parameter $row of TYPO3\CMS\Core\Domain\Re...Repository::versionOL() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

176
            $pageRepository->versionOL($referencesForeignTable, /** @scrutinizer ignore-type */ $element, true);
Loading history...
177
            if (is_array($element)) {
178
                $element = $pageRepository->getLanguageOverlay($referencesForeignTable, $element);
0 ignored issues
show
Bug introduced by
It seems like $referencesForeignTable can also be of type null; however, parameter $table of TYPO3\CMS\Core\Domain\Re...y::getLanguageOverlay() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

178
                $element = $pageRepository->getLanguageOverlay(/** @scrutinizer ignore-type */ $referencesForeignTable, $element);
Loading history...
179
            }
180
        }
181
182
        if (is_array($element)) {
183
            $fileCollector->addFilesFromRelation($referencesForeignTable, $referencesFieldName, $element);
184
        }
185
    }
186
187
    /**
188
     * @return \TYPO3\CMS\Core\Domain\Repository\PageRepository
189
     */
190
    protected function getPageRepository()
191
    {
192
        return $GLOBALS['TSFE']->sys_page;
193
    }
194
195
    /**
196
     * @return FileCollector
197
     */
198
    protected function getFileCollector()
199
    {
200
        return GeneralUtility::makeInstance(FileCollector::class);
201
    }
202
}
203