621a08d0b3b3570433ce5df72a6f32cd3f71c6a0
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / ContentObject / FluidTemplateContentObject.php
1 <?php
2 namespace TYPO3\CMS\Frontend\ContentObject;
3
4 /**
5 * This file is part of the TYPO3 CMS project.
6 *
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.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16 use TYPO3\CMS\Core\Utility\GeneralUtility;
17 use TYPO3\CMS\Extbase\Service\TypoScriptService;
18 use TYPO3\CMS\Fluid\View\StandaloneView;
19
20 /**
21 * Contains TEMPLATE class object.
22 *
23 * @author Xavier Perseguers <typo3@perseguers.ch>
24 * @author Steffen Kamper <steffen@typo3.org>
25 * @author Bastian Waidelich <bastian@typo3.org>
26 * @author Steffen Ritter <info@steffen-ritter.net>
27 * @author Benjamin Mack <benni@typo3.org>
28 */
29 class FluidTemplateContentObject extends AbstractContentObject {
30
31 /**
32 * @var StandaloneView
33 */
34 protected $view = NULL;
35
36 /**
37 * Constructor
38 *
39 * @param ContentObjectRenderer $contentObjectRenderer
40 */
41 public function __construct(ContentObjectRenderer $contentObjectRenderer) {
42 parent::__construct($contentObjectRenderer);
43 }
44
45 /**
46 * Rendering the cObject, FLUIDTEMPLATE
47 *
48 * Configuration properties:
49 * - file string+stdWrap The FLUID template file
50 * - layoutRootPath filepath+stdWrap Root path to layouts
51 * - partialRootPath filepath+stdWrap Root path to partial
52 * - variable array of cObjects, the keys are the variable names in fluid
53 * - extbase.pluginName
54 * - extbase.controllerExtensionName
55 * - extbase.controllerName
56 * - extbase.controllerActionName
57 *
58 * Example:
59 * 10 = FLUIDTEMPLATE
60 * 10.template = FILE
61 * 10.template.file = fileadmin/templates/mytemplate.html
62 * 10.partialRootPath = fileadmin/templates/partial/
63 * 10.variables {
64 * mylabel = TEXT
65 * mylabel.value = Label from TypoScript coming
66 * }
67 *
68 * @param array $conf Array of TypoScript properties
69 * @return string The HTML output
70 */
71 public function render($conf = array()) {
72 $parentView = $this->view;
73 $this->initializeStandaloneViewInstance();
74
75 if (!is_array($conf)) {
76 $conf = array();
77 }
78
79 $this->setTemplate($conf);
80 $this->setLayoutRootPath($conf);
81 $this->setPartialRootPath($conf);
82 $this->setFormat($conf);
83 $this->setExtbaseVariables($conf);
84 $this->assignSettings($conf);
85 $this->assignContentObjectVariables($conf);
86 $this->assignContentObjectDataAndCurrent();
87
88 $content = $this->renderFluidView();
89 $content = $this->applyStandardWrapToRenderedContent($content, $conf);
90
91 $this->view = $parentView;
92 return $content;
93 }
94
95 /**
96 * Creating standalone view instance must not be done in construct() as
97 * it can lead to a nasty cache issue since content object instances
98 * are not always re-created by the content object rendered for every
99 * usage, but can be re-used. Thus, we need a fresh instance of
100 * StandaloneView every time render() is called.
101 *
102 * @return void
103 */
104 protected function initializeStandaloneViewInstance() {
105 $this->view = GeneralUtility::makeInstance(StandaloneView::class);
106 }
107
108 /**
109 * Set template
110 *
111 * @param array $conf With possibly set file resource
112 * @return void
113 * @throws \InvalidArgumentException
114 */
115 protected function setTemplate(array $conf) {
116 // Fetch the Fluid template
117 if (!empty($conf['template']) && !empty($conf['template.'])) {
118 $templateSource = $this->cObj->cObjGetSingle($conf['template'], $conf['template.']);
119 $this->view->setTemplateSource($templateSource);
120 } else {
121 $file = isset($conf['file.']) ? $this->cObj->stdWrap($conf['file'], $conf['file.']) : $conf['file'];
122 /** @var $templateService \TYPO3\CMS\Core\TypoScript\TemplateService */
123 $templateService = $GLOBALS['TSFE']->tmpl;
124 $templatePathAndFilename = $templateService->getFileName($file);
125 $this->view->setTemplatePathAndFilename($templatePathAndFilename);
126 }
127 }
128
129 /**
130 * Set layout root path if given in configuration
131 *
132 * @param array $conf Configuration array
133 * @return void
134 */
135 protected function setLayoutRootPath(array $conf) {
136 // Override the default layout path via typoscript
137 $layoutRootPath = isset($conf['layoutRootPath.']) ? $this->cObj->stdWrap($conf['layoutRootPath'], $conf['layoutRootPath.']) : $conf['layoutRootPath'];
138 if ($layoutRootPath) {
139 $layoutRootPath = GeneralUtility::getFileAbsFileName($layoutRootPath);
140 $this->view->setLayoutRootPaths(array($layoutRootPath));
141 }
142 }
143
144 /**
145 * Set partial root path if given in configuration
146 *
147 * @param array $conf Configuration array
148 * @return void
149 */
150 protected function setPartialRootPath(array $conf) {
151 $partialRootPath = isset($conf['partialRootPath.']) ? $this->cObj->stdWrap($conf['partialRootPath'], $conf['partialRootPath.']) : $conf['partialRootPath'];
152 if ($partialRootPath) {
153 $partialRootPath = GeneralUtility::getFileAbsFileName($partialRootPath);
154 $this->view->setPartialRootPaths(array($partialRootPath));
155 }
156 }
157
158 /**
159 * Set different format if given in configuration
160 *
161 * @param array $conf Configuration array
162 * @return void
163 */
164 protected function setFormat(array $conf) {
165 $format = isset($conf['format.']) ? $this->cObj->stdWrap($conf['format'], $conf['format.']) : $conf['format'];
166 if ($format) {
167 $this->view->setFormat($format);
168 }
169 }
170
171 /**
172 * Set some extbase variables if given
173 *
174 * @param array $conf Configuration array
175 * @return void
176 */
177 protected function setExtbaseVariables(array $conf) {
178 /** @var $request \TYPO3\CMS\Extbase\Mvc\Request */
179 $requestPluginName = isset($conf['extbase.']['pluginName.']) ? $this->cObj->stdWrap($conf['extbase.']['pluginName'], $conf['extbase.']['pluginName.']) : $conf['extbase.']['pluginName'];
180 if ($requestPluginName) {
181 $this->view->getRequest()->setPluginName($requestPluginName);
182 }
183 $requestControllerExtensionName = isset($conf['extbase.']['controllerExtensionName.']) ? $this->cObj->stdWrap($conf['extbase.']['controllerExtensionName'], $conf['extbase.']['controllerExtensionName.']) : $conf['extbase.']['controllerExtensionName'];
184 if ($requestControllerExtensionName) {
185 $this->view->getRequest()->setControllerExtensionName($requestControllerExtensionName);
186 }
187 $requestControllerName = isset($conf['extbase.']['controllerName.']) ? $this->cObj->stdWrap($conf['extbase.']['controllerName'], $conf['extbase.']['controllerName.']) : $conf['extbase.']['controllerName'];
188 if ($requestControllerName) {
189 $this->view->getRequest()->setControllerName($requestControllerName);
190 }
191 $requestControllerActionName = isset($conf['extbase.']['controllerActionName.']) ? $this->cObj->stdWrap($conf['extbase.']['controllerActionName'], $conf['extbase.']['controllerActionName.']) : $conf['extbase.']['controllerActionName'];
192 if ($requestControllerActionName) {
193 $this->view->getRequest()->setControllerActionName($requestControllerActionName);
194 }
195 }
196
197 /**
198 * Assign rendered content objects in variables array to view
199 *
200 * @param array $conf Configuration array
201 * @return void
202 * @throws \InvalidArgumentException
203 */
204 protected function assignContentObjectVariables(array $conf) {
205 $reservedVariables = array('data', 'current');
206 // Accumulate the variables to be replaced and loop them through cObjGetSingle
207 $variables = (array)$conf['variables.'];
208 foreach ($variables as $variableName => $cObjType) {
209 if (is_array($cObjType)) {
210 continue;
211 }
212 if (!in_array($variableName, $reservedVariables)) {
213 $this->view->assign(
214 $variableName,
215 $this->cObj->cObjGetSingle($cObjType, $variables[$variableName . '.'])
216 );
217 } else {
218 throw new \InvalidArgumentException(
219 'Cannot use reserved name "' . $variableName . '" as variable name in FLUIDTEMPLATE.',
220 1288095720
221 );
222 }
223 }
224 }
225
226 /**
227 * Set any TypoScript settings to the view. This is similar to a
228 * default MVC action controller in extbase.
229 *
230 * @param array $conf Configuration
231 * @return void
232 */
233 protected function assignSettings(array $conf) {
234 if (array_key_exists('settings.', $conf)) {
235 /** @var $typoScriptService TypoScriptService */
236 $typoScriptService = GeneralUtility::makeInstance(TypoScriptService::class);
237 $settings = $typoScriptService->convertTypoScriptArrayToPlainArray($conf['settings.']);
238 $this->view->assign('settings', $settings);
239 }
240 }
241
242 /**
243 * Assign content object renderer data and current to view
244 *
245 * @return void
246 */
247 protected function assignContentObjectDataAndCurrent() {
248 $this->view->assign('data', $this->cObj->data);
249 $this->view->assign('current', $this->cObj->data[$this->cObj->currentValKey]);
250 }
251
252 /**
253 * Render fluid standalone view
254 *
255 * @return string
256 */
257 protected function renderFluidView() {
258 return $this->view->render();
259 }
260
261 /**
262 * Apply standard wrap to content
263 *
264 * @param string $content Rendered HTML content
265 * @param array $conf Configuration array
266 * @return string Standard wrapped content
267 */
268 protected function applyStandardWrapToRenderedContent($content, array $conf) {
269 if (isset($conf['stdWrap.'])) {
270 $content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
271 }
272 return $content;
273 }
274
275 }