c524f8299b6bf734771268e0708eec932be088b7
[Packages/TYPO3.CMS.git] / typo3 / sysext / fluid / Classes / Core / ViewHelper / AbstractViewHelper.php
1 <?php
2 namespace TYPO3\CMS\Fluid\Core\ViewHelper;
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
17 use Psr\Log\LoggerInterface;
18 use TYPO3\CMS\Core\Log\LogManager;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20
21 /**
22 * The abstract base class for all view helpers.
23 *
24 * @api
25 */
26 abstract class AbstractViewHelper extends \TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper implements \TYPO3Fluid\Fluid\Core\ViewHelper\ViewHelperInterface
27 {
28 /**
29 * Controller Context to use
30 *
31 * @var \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext
32 * @api
33 */
34 protected $controllerContext;
35
36 /**
37 * Reflection service
38 *
39 * @var \TYPO3\CMS\Extbase\Reflection\ReflectionService
40 */
41 private $reflectionService;
42
43 /**
44 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
45 */
46 protected $objectManager;
47
48 /**
49 * @param \TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface $renderingContext
50 */
51 public function setRenderingContext(\TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface $renderingContext)
52 {
53 parent::setRenderingContext($renderingContext);
54 if ($renderingContext instanceof \TYPO3\CMS\Fluid\Core\Rendering\RenderingContext) {
55 $this->controllerContext = $renderingContext->getControllerContext();
56 }
57 }
58
59 /**
60 * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
61 */
62 public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager)
63 {
64 $this->objectManager = $objectManager;
65 }
66
67 /**
68 * Inject a Reflection service
69 *
70 * @param \TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService Reflection service
71 */
72 public function injectReflectionService(\TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService)
73 {
74 $this->reflectionService = $reflectionService;
75 }
76
77 /**
78 * Call the render() method and handle errors.
79 *
80 * @return string the rendered ViewHelper
81 * @throws Exception
82 */
83 protected function callRenderMethod()
84 {
85 $renderMethodParameters = [];
86 foreach ($this->argumentDefinitions as $argumentName => $argumentDefinition) {
87 if ($argumentDefinition instanceof \TYPO3\CMS\Fluid\Core\ViewHelper\ArgumentDefinition && $argumentDefinition->isMethodParameter()) {
88 $renderMethodParameters[$argumentName] = $this->arguments[$argumentName];
89 }
90 }
91
92 try {
93 return call_user_func_array([$this, 'render'], $renderMethodParameters);
94 } catch (Exception $exception) {
95 if (GeneralUtility::getApplicationContext()->isProduction()) {
96 $this->getLogger()->error('A Fluid ViewHelper Exception was captured: ' . $exception->getMessage() . ' (' . $exception->getCode() . ')', ['exception' => $exception]);
97 return '';
98 } else {
99 throw $exception;
100 }
101 }
102 }
103
104 /**
105 * @return LoggerInterface
106 */
107 protected function getLogger()
108 {
109 return GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
110 }
111
112 /**
113 * Register method arguments for "render" by analysing the doc comment above.
114 *
115 * @throws \TYPO3Fluid\Fluid\Core\Parser\Exception
116 */
117 protected function registerRenderMethodArguments()
118 {
119 $methodParameters = $this->reflectionService->getMethodParameters(get_class($this), 'render');
120 if (count($methodParameters) === 0) {
121 return;
122 }
123
124 $methodTags = $this->reflectionService->getMethodTagsValues(get_class($this), 'render');
125
126 $paramAnnotations = [];
127 if (isset($methodTags['param'])) {
128 $paramAnnotations = $methodTags['param'];
129 }
130
131 $i = 0;
132 foreach ($methodParameters as $parameterName => $parameterInfo) {
133 $dataType = null;
134 if (isset($parameterInfo['type'])) {
135 $dataType = isset($parameterInfo['array']) && (bool)$parameterInfo['array'] ? 'array' : $parameterInfo['type'];
136 } else {
137 throw new \TYPO3\CMS\Fluid\Core\Exception('Could not determine type of argument "' . $parameterName . '" of the render-method in ViewHelper "' . get_class($this) . '". Either the methods docComment is invalid or some PHP optimizer strips off comments.', 1242292003);
138 }
139
140 $description = '';
141 if (isset($paramAnnotations[$i])) {
142 $explodedAnnotation = explode(' ', $paramAnnotations[$i]);
143 array_shift($explodedAnnotation);
144 array_shift($explodedAnnotation);
145 $description = implode(' ', $explodedAnnotation);
146 }
147 $defaultValue = null;
148 if (isset($parameterInfo['defaultValue'])) {
149 $defaultValue = $parameterInfo['defaultValue'];
150 }
151 $this->argumentDefinitions[$parameterName] = new ArgumentDefinition($parameterName, $dataType, $description, ($parameterInfo['optional'] === false), $defaultValue, true);
152 $i++;
153 }
154 }
155
156 /**
157 * @return \TYPO3Fluid\Fluid\Core\ViewHelper\ArgumentDefinition[]
158 * @throws \TYPO3Fluid\Fluid\Core\Parser\Exception
159 */
160 public function prepareArguments()
161 {
162 if (method_exists($this, 'registerRenderMethodArguments')) {
163 $this->registerRenderMethodArguments();
164 }
165 return parent::prepareArguments();
166 }
167 }