TYPO3 CMS  TYPO3_6-2
AbstractViewHelper.php
Go to the documentation of this file.
1 <?php
3 
4 /* *
5  * This script is backported from the TYPO3 Flow package "TYPO3.Fluid". *
6  * *
7  * It is free software; you can redistribute it and/or modify it under *
8  * the terms of the GNU Lesser General Public License, either version 3 *
9  * of the License, or (at your option) any later version. *
10  * *
11  * The TYPO3 project - inspiring people to share! *
12  * */
13 
19 abstract class AbstractViewHelper {
20 
26  private $argumentsInitialized = FALSE;
27 
33  private $argumentDefinitions = array();
34 
44  static private $argumentDefinitionCache = array();
45 
51  private $viewHelperNode;
52 
59  protected $arguments;
60 
68 
75  protected $controllerContext;
76 
80  protected $renderingContext;
81 
85  protected $renderChildrenClosure = NULL;
86 
94 
101 
106  protected $objectManager;
107 
113  protected $escapingInterceptorEnabled = TRUE;
114 
119  public function setArguments(array $arguments) {
120  $this->arguments = $arguments;
121  }
122 
127  public function setRenderingContext(\TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface $renderingContext) {
128  $this->renderingContext = $renderingContext;
129  $this->templateVariableContainer = $renderingContext->getTemplateVariableContainer();
130  if ($renderingContext->getControllerContext() !== NULL) {
131  $this->controllerContext = $renderingContext->getControllerContext();
132  }
133  $this->viewHelperVariableContainer = $renderingContext->getViewHelperVariableContainer();
134  }
135 
141  public function injectReflectionService(\TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService) {
142  $this->reflectionService = $reflectionService;
143  }
144 
152  public function isEscapingInterceptorEnabled() {
154  }
155 
169  protected function registerArgument($name, $type, $description, $required = FALSE, $defaultValue = NULL) {
170  if (array_key_exists($name, $this->argumentDefinitions)) {
171  throw new \TYPO3\CMS\Fluid\Core\ViewHelper\Exception('Argument "' . $name . '" has already been defined, thus it should not be defined again.', 1253036401);
172  }
173  $this->argumentDefinitions[$name] = new \TYPO3\CMS\Fluid\Core\ViewHelper\ArgumentDefinition($name, $type, $description, $required, $defaultValue);
174  return $this;
175  }
176 
191  protected function overrideArgument($name, $type, $description, $required = FALSE, $defaultValue = NULL) {
192  if (!array_key_exists($name, $this->argumentDefinitions)) {
193  throw new \TYPO3\CMS\Fluid\Core\ViewHelper\Exception('Argument "' . $name . '" has not been defined, thus it can\'t be overridden.', 1279212461);
194  }
195  $this->argumentDefinitions[$name] = new \TYPO3\CMS\Fluid\Core\ViewHelper\ArgumentDefinition($name, $type, $description, $required, $defaultValue);
196  return $this;
197  }
198 
207  public function setViewHelperNode(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ViewHelperNode $node) {
208  $this->viewHelperNode = $node;
209  }
210 
218  $this->renderChildrenClosure = $renderChildrenClosure;
219  }
220 
226  public function initializeArgumentsAndRender() {
227  $this->validateArguments();
228  $this->initialize();
229 
230  return $this->callRenderMethod();
231  }
232 
239  protected function callRenderMethod() {
240  $renderMethodParameters = array();
241  foreach ($this->argumentDefinitions as $argumentName => $argumentDefinition) {
242  if ($argumentDefinition->isMethodParameter()) {
243  $renderMethodParameters[$argumentName] = $this->arguments[$argumentName];
244  }
245  }
246 
247  try {
248  return call_user_func_array(array($this, 'render'), $renderMethodParameters);
249  } catch (\TYPO3\CMS\Fluid\Core\ViewHelper\Exception $exception) {
250  // @todo [BW] rethrow exception, log, ignore.. depending on the current context
251  return $exception->getMessage();
252  }
253  }
254 
263  public function initialize() {
264  }
265 
273  public function renderChildren() {
274  if ($this->renderChildrenClosure !== NULL) {
275  $closure = $this->renderChildrenClosure;
276  return $closure();
277  }
278  return $this->viewHelperNode->evaluateChildNodes($this->renderingContext);
279  }
280 
289  protected function buildRenderChildrenClosure() {
290  $self = $this;
291  return function () use ($self) {
292  return $self->renderChildren();
293  };
294  }
295 
301  public function prepareArguments() {
302  if (!$this->argumentsInitialized) {
303  $thisClassName = get_class($this);
304  if (isset(self::$argumentDefinitionCache[$thisClassName])) {
305  $this->argumentDefinitions = self::$argumentDefinitionCache[$thisClassName];
306  } else {
308  $this->initializeArguments();
309  self::$argumentDefinitionCache[$thisClassName] = $this->argumentDefinitions;
310  }
311  $this->argumentsInitialized = TRUE;
312  }
314  }
315 
322  private function registerRenderMethodArguments() {
323  $methodParameters = $this->reflectionService->getMethodParameters(get_class($this), 'render');
324  if (count($methodParameters) === 0) {
325  return;
326  }
327 
328  if (\TYPO3\CMS\Fluid\Fluid::$debugMode) {
329  $methodTags = $this->reflectionService->getMethodTagsValues(get_class($this), 'render');
330 
331  $paramAnnotations = array();
332  if (isset($methodTags['param'])) {
333  $paramAnnotations = $methodTags['param'];
334  }
335  }
336 
337  $i = 0;
338  foreach ($methodParameters as $parameterName => $parameterInfo) {
339  $dataType = NULL;
340  if (isset($parameterInfo['type'])) {
341  $dataType = $parameterInfo['type'];
342  } elseif ($parameterInfo['array']) {
343  $dataType = 'array';
344  }
345  if ($dataType === NULL) {
346  throw new \TYPO3\CMS\Fluid\Core\Parser\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);
347  }
348 
349  $description = '';
350  if (\TYPO3\CMS\Fluid\Fluid::$debugMode && isset($paramAnnotations[$i])) {
351  $explodedAnnotation = explode(' ', $paramAnnotations[$i]);
352  array_shift($explodedAnnotation);
353  array_shift($explodedAnnotation);
354  $description = implode(' ', $explodedAnnotation);
355  }
356  $defaultValue = NULL;
357  if (isset($parameterInfo['defaultValue'])) {
358  $defaultValue = $parameterInfo['defaultValue'];
359  }
360  $this->argumentDefinitions[$parameterName] = new \TYPO3\CMS\Fluid\Core\ViewHelper\ArgumentDefinition($parameterName, $dataType, $description, ($parameterInfo['optional'] === FALSE), $defaultValue, TRUE);
361  $i++;
362  }
363  }
364 
371  public function validateArguments() {
373  if (!count($argumentDefinitions)) {
374  return;
375  }
376  foreach ($argumentDefinitions as $argumentName => $registeredArgument) {
377  if ($this->hasArgument($argumentName)) {
378  if ($this->arguments[$argumentName] === $registeredArgument->getDefaultValue()) {
379  continue;
380  }
381 
382  $type = $registeredArgument->getType();
383  if ($type === 'array') {
384  if (!is_array($this->arguments[$argumentName]) && !$this->arguments[$argumentName] instanceof \ArrayAccess && !$this->arguments[$argumentName] instanceof \Traversable) {
385  throw new \InvalidArgumentException('The argument "' . $argumentName . '" was registered with type "array", but is of type "' . gettype($this->arguments[$argumentName]) . '" in view helper "' . get_class($this) . '"', 1237900529);
386  }
387  } elseif ($type === 'boolean') {
388  if (!is_bool($this->arguments[$argumentName])) {
389  throw new \InvalidArgumentException('The argument "' . $argumentName . '" was registered with type "boolean", but is of type "' . gettype($this->arguments[$argumentName]) . '" in view helper "' . get_class($this) . '".', 1240227732);
390  }
391  } elseif (class_exists($type, FALSE)) {
392  if (!($this->arguments[$argumentName] instanceof $type)) {
393  if (is_object($this->arguments[$argumentName])) {
394  throw new \InvalidArgumentException('The argument "' . $argumentName . '" was registered with type "' . $type . '", but is of type "' . get_class($this->arguments[$argumentName]) . '" in view helper "' . get_class($this) . '".', 1256475114);
395  } else {
396  throw new \InvalidArgumentException('The argument "' . $argumentName . '" was registered with type "' . $type . '", but is of type "' . gettype($this->arguments[$argumentName]) . '" in view helper "' . get_class($this) . '".', 1256475113);
397  }
398  }
399  }
400  }
401  }
402  }
403 
411  public function initializeArguments() {
412  }
413 
423  //abstract public function render();
424 
432  protected function hasArgument($argumentName) {
433  return isset($this->arguments[$argumentName]) && $this->arguments[$argumentName] !== NULL;
434  }
435 
452  public function compile($argumentsVariableName, $renderChildrenClosureVariableName, &$initializationPhpCode, \TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\AbstractNode $syntaxTreeNode, \TYPO3\CMS\Fluid\Core\Compiler\TemplateCompiler $templateCompiler) {
453  return sprintf('%s::renderStatic(%s, %s, $renderingContext)',
454  get_class($this), $argumentsVariableName, $renderChildrenClosureVariableName);
455  }
456 
467  static public function renderStatic(array $arguments, \Closure $renderChildrenClosure, \TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface $renderingContext) {
468  return NULL;
469  }
470 
478  public function resetState() {
479  }
480 }
registerArgument($name, $type, $description, $required=FALSE, $defaultValue=NULL)
injectReflectionService(\TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService)
overrideArgument($name, $type, $description, $required=FALSE, $defaultValue=NULL)
setViewHelperNode(\TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\ViewHelperNode $node)
setRenderingContext(\TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface $renderingContext)
setRenderChildrenClosure(\Closure $renderChildrenClosure)
compile($argumentsVariableName, $renderChildrenClosureVariableName, &$initializationPhpCode, \TYPO3\CMS\Fluid\Core\Parser\SyntaxTree\AbstractNode $syntaxTreeNode, \TYPO3\CMS\Fluid\Core\Compiler\TemplateCompiler $templateCompiler)
static renderStatic(array $arguments, \Closure $renderChildrenClosure, \TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface $renderingContext)