/** * Returns the JavaScript to declare the Ext Direct provider for all * controller actions that are annotated with "@TYPO3\ExtJS\Annotations\ExtDirect" * * = Examples = * * <code title="Simple"> * {namespace ext=TYPO3\ExtJS\ViewHelpers} * ... * <script type="text/javascript"> * <ext:extdirect.provider /> * </script> * ... * </code> * * TODO Cache ext direct provider config * @param string $namespace The base ExtJS namespace (with dots) for the direct provider methods * @return string JavaScript needed to include Ext Direct provider * @api */ public function render($namespace = NULL) { $providerConfig = array('url' => '?TYPO3_ExtJS_ExtDirectRequest=1&__csrfToken=' . $this->securityContext->getCsrfProtectionToken(), 'type' => 'remoting', 'actions' => array()); if (!empty($namespace)) { $providerConfig['namespace'] = $namespace; } $controllerClassNames = $this->localReflectionService->getAllImplementationClassNamesForInterface('TYPO3\\Flow\\Mvc\\Controller\\ControllerInterface'); foreach ($controllerClassNames as $controllerClassName) { $methodNames = get_class_methods($controllerClassName); foreach ($methodNames as $methodName) { $methodTagsValues = $this->localReflectionService->getMethodTagsValues($controllerClassName, $methodName); if (isset($methodTagsValues['extdirect'])) { $methodParameters = $this->localReflectionService->getMethodParameters($controllerClassName, $methodName); $requiredMethodParametersCount = 0; foreach ($methodParameters as $methodParameter) { if ($methodParameter['optional'] === TRUE) { break; } $requiredMethodParametersCount++; } $extDirectAction = str_replace('\\', '_', $controllerClassName); $providerConfig['actions'][$extDirectAction][] = array('name' => substr($methodName, 0, -6), 'len' => $requiredMethodParametersCount); } } } return 'Ext.Direct.addProvider(' . json_encode($providerConfig) . ');' . chr(10); }
/** * Builds the method documentation block for the specified method keeping the vital annotations * * @param string $className Name of the class the method is declared in * @param string $methodName Name of the method to create the parameters code for * @return string $methodDocumentation DocComment for the given method */ protected function buildMethodDocumentation($className, $methodName) { $methodDocumentation = "\t/**\n\t * Autogenerated Proxy Method\n"; if ($this->reflectionService->hasMethod($className, $methodName)) { $methodTags = $this->reflectionService->getMethodTagsValues($className, $methodName); $allowedTags = array('param', 'return', 'throws'); foreach ($methodTags as $tag => $values) { if (in_array($tag, $allowedTags)) { if (count($values) === 0) { $methodDocumentation .= ' * @' . $tag . "\n"; } else { foreach ($values as $value) { $methodDocumentation .= ' * @' . $tag . ' ' . $value . "\n"; } } } } $methodAnnotations = $this->reflectionService->getMethodAnnotations($className, $methodName); foreach ($methodAnnotations as $annotation) { $methodDocumentation .= ' * ' . \TYPO3\Flow\Object\Proxy\Compiler::renderAnnotation($annotation) . "\n"; } } $methodDocumentation .= "\t */\n"; return $methodDocumentation; }
/** * Checks if the specified method matches with the method tag filter pattern * * @param string $className Name of the class to check against - not used here * @param string $methodName Name of the method * @param string $methodDeclaringClassName Name of the class the method was originally declared in * @param mixed $pointcutQueryIdentifier Some identifier for this query - must at least differ from a previous identifier. Used for circular reference detection - not used here * @return boolean TRUE if the class matches, otherwise FALSE * @throws \TYPO3\Flow\Aop\Exception */ public function matches($className, $methodName, $methodDeclaringClassName, $pointcutQueryIdentifier) { if ($methodDeclaringClassName === NULL || !method_exists($methodDeclaringClassName, $methodName)) { return FALSE; } foreach ($this->reflectionService->getMethodTagsValues($methodDeclaringClassName, $methodName) as $tag => $values) { $matchResult = preg_match('/^' . $this->methodTagFilterExpression . '$/i', $tag); if ($matchResult === FALSE) { throw new \TYPO3\Flow\Aop\Exception('Error in regular expression "' . $this->methodTagFilterExpression . '" in pointcut method tag filter', 1229343988); } if ($matchResult === 1) { return TRUE; } } return FALSE; }
/** * Register method arguments for "render" by analysing the doc comment above. * * @return void * @throws Parser\Exception */ private function registerRenderMethodArguments() { $methodParameters = $this->reflectionService->getMethodParameters(get_class($this), 'render'); if (count($methodParameters) === 0) { return; } if (Fluid::$debugMode) { $methodTags = $this->reflectionService->getMethodTagsValues(get_class($this), 'render'); $paramAnnotations = array(); if (isset($methodTags['param'])) { $paramAnnotations = $methodTags['param']; } } $i = 0; foreach ($methodParameters as $parameterName => $parameterInfo) { $dataType = NULL; if (isset($parameterInfo['type'])) { $dataType = $parameterInfo['type']; } elseif ($parameterInfo['array']) { $dataType = 'array'; } if ($dataType === NULL) { throw new 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); } $description = ''; if (Fluid::$debugMode && isset($paramAnnotations[$i])) { $explodedAnnotation = explode(' ', $paramAnnotations[$i]); array_shift($explodedAnnotation); array_shift($explodedAnnotation); $description = implode(' ', $explodedAnnotation); } $defaultValue = NULL; if (isset($parameterInfo['defaultValue'])) { $defaultValue = $parameterInfo['defaultValue']; } $this->argumentDefinitions[$parameterName] = new ArgumentDefinition($parameterName, $dataType, $description, $parameterInfo['optional'] === FALSE, $defaultValue, TRUE); $i++; } }
/** * @test */ public function theReflectionServiceCorrectlyBuildsMethodTagsValues() { $actual = $this->reflectionService->getMethodTagsValues('TYPO3\\Flow\\Tests\\Functional\\Reflection\\Fixtures\\ClassSchemaFixture', 'setName'); $expected = array('param' => array('string $name'), 'return' => array('void'), 'validate' => array('$name", type="foo1', '$name", type="foo2'), 'skipcsrfprotection' => array()); $this->assertSame($expected, $actual); }