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
16namespace TYPO3\CMS\Frontend\ContentObject;
17
18use TYPO3\CMS\Core\TimeTracker\TimeTracker;
19use TYPO3\CMS\Core\Utility\GeneralUtility;
20use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
21
22/**
23 * Contains CONTENT class object.
24 */
25class ContentContentObject extends AbstractContentObject
26{
27    /**
28     * Rendering the cObject, CONTENT
29     *
30     * @param array $conf Array of TypoScript properties
31     * @return string Output
32     */
33    public function render($conf = [])
34    {
35        if (!empty($conf['if.']) && !$this->cObj->checkIf($conf['if.'])) {
36            return '';
37        }
38
39        $frontendController = $this->getFrontendController();
40        $theValue = '';
41        $originalRec = $frontendController->currentRecord;
42        // If the currentRecord is set, we register, that this record has invoked this function.
43        // It's should not be allowed to do this again then!!
44        if ($originalRec) {
45            ++$frontendController->recordRegister[$originalRec];
46        }
47        $conf['table'] = isset($conf['table.']) ? trim($this->cObj->stdWrap($conf['table'], $conf['table.'])) : trim($conf['table']);
48        $conf['select.'] = !empty($conf['select.']) ? $conf['select.'] : [];
49        $renderObjName = $conf['renderObj'] ?: '<' . $conf['table'];
50        $renderObjKey = $conf['renderObj'] ? 'renderObj' : '';
51        $renderObjConf = $conf['renderObj.'];
52        $slide = isset($conf['slide.']) ? (int)$this->cObj->stdWrap($conf['slide'], $conf['slide.']) : (int)$conf['slide'];
53        if (!$slide) {
54            $slide = 0;
55        }
56        $slideCollect = isset($conf['slide.']['collect.']) ? (int)$this->cObj->stdWrap($conf['slide.']['collect'], $conf['slide.']['collect.']) : (int)$conf['slide.']['collect'];
57        if (!$slideCollect) {
58            $slideCollect = 0;
59        }
60        $slideCollectReverse = isset($conf['slide.']['collectReverse.']) ? (int)$this->cObj->stdWrap($conf['slide.']['collectReverse'], $conf['slide.']['collectReverse.']) : (int)$conf['slide.']['collectReverse'];
61        $slideCollectReverse = (bool)$slideCollectReverse;
62        $slideCollectFuzzy = isset($conf['slide.']['collectFuzzy.'])
63            ? (bool)$this->cObj->stdWrap($conf['slide.']['collectFuzzy'], $conf['slide.']['collectFuzzy.'])
64            : (bool)$conf['slide.']['collectFuzzy'];
65        if (!$slideCollect) {
66            $slideCollectFuzzy = true;
67        }
68        $again = false;
69        $tmpValue = '';
70
71        do {
72            $records = $this->cObj->getRecords($conf['table'], $conf['select.']);
73            $cobjValue = '';
74            if (!empty($records)) {
75                $this->cObj->currentRecordTotal = count($records);
76                $this->getTimeTracker()->setTSlogMessage('NUMROWS: ' . count($records));
77
78                /** @var ContentObjectRenderer $cObj */
79                $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
80                $cObj->setParent($this->cObj->data, $this->cObj->currentRecord);
81                $this->cObj->currentRecordNumber = 0;
82
83                foreach ($records as $row) {
84                    // Call hook for possible manipulation of database row for cObj->data
85                    foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content_content.php']['modifyDBRow'] ?? [] as $className) {
86                        $_procObj = GeneralUtility::makeInstance($className);
87                        $_procObj->modifyDBRow($row, $conf['table']);
88                    }
89                    if (!$frontendController->recordRegister[$conf['table'] . ':' . $row['uid']]) {
90                        $this->cObj->currentRecordNumber++;
91                        $cObj->parentRecordNumber = $this->cObj->currentRecordNumber;
92                        $frontendController->currentRecord = $conf['table'] . ':' . $row['uid'];
93                        $this->cObj->lastChanged($row['tstamp']);
94                        $cObj->start($row, $conf['table']);
95                        $tmpValue = $cObj->cObjGetSingle($renderObjName, $renderObjConf, $renderObjKey);
96                        $cobjValue .= $tmpValue;
97                    }
98                }
99            }
100            if ($slideCollectReverse) {
101                $theValue = $cobjValue . $theValue;
102            } else {
103                $theValue .= $cobjValue;
104            }
105            if ($slideCollect > 0) {
106                $slideCollect--;
107            }
108            if ($slide) {
109                if ($slide > 0) {
110                    $slide--;
111                }
112                $conf['select.']['pidInList'] = $this->cObj->getSlidePids($conf['select.']['pidInList'], $conf['select.']['pidInList.']);
113                if (isset($conf['select.']['pidInList.'])) {
114                    unset($conf['select.']['pidInList.']);
115                }
116                $again = (string)$conf['select.']['pidInList'] !== '';
117            }
118        } while ($again && $slide && ((string)$tmpValue === '' && $slideCollectFuzzy || $slideCollect));
119
120        $wrap = isset($conf['wrap.']) ? $this->cObj->stdWrap($conf['wrap'], $conf['wrap.']) : $conf['wrap'];
121        if ($wrap) {
122            $theValue = $this->cObj->wrap($theValue, $wrap);
123        }
124        if (isset($conf['stdWrap.'])) {
125            $theValue = $this->cObj->stdWrap($theValue, $conf['stdWrap.']);
126        }
127        // Restore
128        $frontendController->currentRecord = $originalRec;
129        if ($originalRec) {
130            --$frontendController->recordRegister[$originalRec];
131        }
132        return $theValue;
133    }
134
135    /**
136     * Returns the frontend controller
137     *
138     * @return TypoScriptFrontendController
139     */
140    protected function getFrontendController()
141    {
142        return $GLOBALS['TSFE'];
143    }
144
145    /**
146     * Returns Time Tracker
147     *
148     * @return TimeTracker
149     */
150    protected function getTimeTracker()
151    {
152        return GeneralUtility::makeInstance(TimeTracker::class);
153    }
154}
155