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