2 namespace TYPO3\CMS\Fluid\ViewHelpers
;
5 * This file is part of the TYPO3 CMS project.
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
14 * The TYPO3 project - inspiring people to share!
17 use TYPO3\CMS\Core\Utility\GeneralUtility
;
18 use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
;
19 use TYPO3\CMS\Extbase\
Object\ObjectManager
;
20 use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
;
21 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
;
22 use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface
;
23 use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper
;
24 use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithContentArgumentAndRenderStatic
;
27 * This ViewHelper renders CObjects from the global TypoScript configuration.
28 * NOTE: You have to ensure proper escaping (htmlspecialchars/intval/etc.) on your own!
32 * <code title="Render lib object">
33 * <f:cObject typoscriptObjectPath="lib.someLibObject" />
36 * rendered lib.someLibObject
39 * <code title="Specify cObject data & current value">
40 * <f:cObject typoscriptObjectPath="lib.customHeader" data="{article}" currentValueKey="title" />
43 * rendered lib.customHeader. data and current value will be available in TypoScript
46 * <code title="inline notation">
47 * {article -> f:cObject(typoscriptObjectPath: 'lib.customHeader')}
50 * rendered lib.customHeader. data will be available in TypoScript
53 class CObjectViewHelper
extends AbstractViewHelper
55 use CompileWithContentArgumentAndRenderStatic
;
58 * Disable escaping of child nodes' output
62 protected $escapeChildren = false;
65 * Disable escaping of this node's output
69 protected $escapeOutput = false;
72 * @var \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController contains a backup of the current $GLOBALS['TSFE'] if used in BE mode
74 protected static $tsfeBackup;
77 * Initialize arguments.
79 * @throws \TYPO3Fluid\Fluid\Core\ViewHelper\Exception
81 public function initializeArguments()
83 $this->registerArgument('data', 'mixed', 'the data to be used for rendering the cObject. Can be an object, array or string. If this argument is not set, child nodes will be used');
84 $this->registerArgument('typoscriptObjectPath', 'string', 'the TypoScript setup path of the TypoScript object to render', true);
85 $this->registerArgument('currentValueKey', 'string', 'currentValueKey');
86 $this->registerArgument('table', 'string', 'the table name associated with "data" argument. Typically tt_content or one of your custom tables. This argument should be set if rendering a FILES cObject where file references are used, or if the data argument is a database record.', false, '');
90 * Renders the TypoScript object in the given TypoScript setup path.
92 * @param array $arguments
93 * @param \Closure $renderChildrenClosure
94 * @param RenderingContextInterface $renderingContext
96 * @throws \TYPO3\CMS\Fluid\Core\ViewHelper\Exception
98 public static function renderStatic(array $arguments, \Closure
$renderChildrenClosure, RenderingContextInterface
$renderingContext)
100 $data = $renderChildrenClosure();
101 $typoscriptObjectPath = $arguments['typoscriptObjectPath'];
102 $currentValueKey = $arguments['currentValueKey'];
103 $table = $arguments['table'];
104 $contentObjectRenderer = static::getContentObjectRenderer();
105 if (TYPO3_MODE
=== 'BE') {
106 static::simulateFrontendEnvironment();
108 $currentValue = null;
109 if (is_object($data)) {
110 $data = \TYPO3\CMS\Extbase\Reflection\ObjectAccess
::getGettableProperties($data);
111 } elseif (is_string($data) ||
is_numeric($data)) {
112 $currentValue = (string)$data;
115 $contentObjectRenderer->start($data, $table);
116 if ($currentValue !== null) {
117 $contentObjectRenderer->setCurrentVal($currentValue);
118 } elseif ($currentValueKey !== null && isset($data[$currentValueKey])) {
119 $contentObjectRenderer->setCurrentVal($data[$currentValueKey]);
121 $pathSegments = GeneralUtility
::trimExplode('.', $typoscriptObjectPath);
122 $lastSegment = array_pop($pathSegments);
123 $setup = static::getConfigurationManager()->getConfiguration(ConfigurationManagerInterface
::CONFIGURATION_TYPE_FULL_TYPOSCRIPT
);
124 foreach ($pathSegments as $segment) {
125 if (!array_key_exists($segment . '.', $setup)) {
126 throw new \TYPO3\CMS\Fluid\Core\ViewHelper\
Exception(
127 'TypoScript object path "' . $typoscriptObjectPath . '" does not exist',
131 $setup = $setup[$segment . '.'];
133 if (!isset($setup[$lastSegment])) {
134 throw new \TYPO3\CMS\Fluid\Core\ViewHelper\
Exception(
135 'No Content Object definition found at TypoScript object path "' . $typoscriptObjectPath . '"',
139 $content = $contentObjectRenderer->cObjGetSingle($setup[$lastSegment], $setup[$lastSegment . '.'] ??
[]);
140 if (TYPO3_MODE
=== 'BE') {
141 static::resetFrontendEnvironment();
147 * @return ConfigurationManagerInterface
149 protected static function getConfigurationManager()
151 return GeneralUtility
::makeInstance(ObjectManager
::class)->get(ConfigurationManagerInterface
::class);
155 * @return ContentObjectRenderer
157 protected static function getContentObjectRenderer()
159 return GeneralUtility
::makeInstance(
160 ContentObjectRenderer
::class,
161 $GLOBALS['TSFE'] ?? GeneralUtility
::makeInstance(TypoScriptFrontendController
::class, null, 0, 0)
166 * Sets the $TSFE->cObjectDepthCounter in Backend mode
167 * This somewhat hacky work around is currently needed because the cObjGetSingle() function of \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer relies on this setting
169 protected static function simulateFrontendEnvironment()
171 static::$tsfeBackup = $GLOBALS['TSFE'] ??
null;
172 $GLOBALS['TSFE'] = new \
stdClass();
173 $GLOBALS['TSFE']->cObj
= GeneralUtility
::makeInstance(ContentObjectRenderer
::class);
174 $GLOBALS['TSFE']->cObjectDepthCounter
= 100;
178 * Resets $GLOBALS['TSFE'] if it was previously changed by simulateFrontendEnvironment()
180 * @see simulateFrontendEnvironment()
182 protected static function resetFrontendEnvironment()
184 $GLOBALS['TSFE'] = static::$tsfeBackup;