Exemple #1
0
 /**
  * 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);
 }
 /**
  * get indexed arguments for method
  * 
  * @param string $class
  * @param string $method
  * @return array
  */
 protected function getArguments($class, $method)
 {
     $arguments = array();
     $parameters = $this->reflectionService->getMethodParameters($class, $method);
     foreach ($parameters as $name => $parameter) {
         $arguments[$parameter['position']] = $this->request->hasArgument($name) ? $this->request->getArgument($name) : null;
     }
     return $arguments;
 }
 /**
  * @test
  */
 public function methodParameterTypeExpansionDoesNotModifySimpleTypes()
 {
     $methodParameters = $this->reflectionService->getMethodParameters('TYPO3\\Flow\\Tests\\Functional\\Reflection\\Fixtures\\Model\\EntityWithUseStatements', 'simpleType');
     $expectedType = 'float';
     $actualType = $methodParameters['parameter']['type'];
     $this->assertSame($expectedType, $actualType);
 }
 /**
  * @test
  */
 public function methodParametersGetNormalizedType()
 {
     $methodParameters = $this->reflectionService->getMethodParameters(\TYPO3\Flow\Tests\Functional\Reflection\Fixtures\AnnotatedClass::class, 'intAndIntegerParameters');
     foreach ($methodParameters as $methodParameter) {
         $this->assertEquals('integer', $methodParameter['type']);
     }
 }
 /**
  * Checks if the specified method matches against the method name
  * expression.
  *
  * Returns TRUE if method name, visibility and arguments constraints match and the target
  * method is not final.
  *
  * @param string $className Ignored in this pointcut filter
  * @param string $methodName Name of the method to match against
  * @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.
  * @return boolean TRUE if the class matches, otherwise FALSE
  * @throws \TYPO3\Flow\Aop\Exception
  */
 public function matches($className, $methodName, $methodDeclaringClassName, $pointcutQueryIdentifier)
 {
     $matchResult = preg_match('/^' . $this->methodNameFilterExpression . '$/', $methodName);
     if ($matchResult === false) {
         throw new \TYPO3\Flow\Aop\Exception('Error in regular expression', 1168876915);
     } elseif ($matchResult !== 1) {
         return false;
     }
     switch ($this->methodVisibility) {
         case 'public':
             if (!($methodDeclaringClassName !== null && $this->reflectionService->isMethodPublic($methodDeclaringClassName, $methodName))) {
                 return false;
             }
             break;
         case 'protected':
             if (!($methodDeclaringClassName !== null && $this->reflectionService->isMethodProtected($methodDeclaringClassName, $methodName))) {
                 return false;
             }
             break;
     }
     if ($methodDeclaringClassName !== null && $this->reflectionService->isMethodFinal($methodDeclaringClassName, $methodName)) {
         return false;
     }
     $methodArguments = $methodDeclaringClassName === null ? array() : $this->reflectionService->getMethodParameters($methodDeclaringClassName, $methodName);
     foreach (array_keys($this->methodArgumentConstraints) as $argumentName) {
         $objectAccess = explode('.', $argumentName, 2);
         $argumentName = $objectAccess[0];
         if (!array_key_exists($argumentName, $methodArguments)) {
             $this->systemLogger->log('The argument "' . $argumentName . '" declared in pointcut does not exist in method ' . $methodDeclaringClassName . '->' . $methodName, LOG_NOTICE);
             return false;
         }
     }
     return true;
 }
 /**
  * Takes an array of unparsed command line arguments and options and converts it separated
  * by named arguments, options and unnamed arguments.
  *
  * @param array $rawCommandLineArguments The unparsed command parts (such as "--foo") as an array
  * @param string $controllerObjectName Object name of the designated command controller
  * @param string $controllerCommandName Command name of the recognized command (ie. method name without "Command" suffix)
  * @return array All and exceeding command line arguments
  * @throws \TYPO3\Flow\Mvc\Exception\InvalidArgumentMixingException
  */
 protected function parseRawCommandLineArguments(array $rawCommandLineArguments, $controllerObjectName, $controllerCommandName)
 {
     $commandLineArguments = array();
     $exceedingArguments = array();
     $commandMethodName = $controllerCommandName . 'Command';
     $commandMethodParameters = $this->reflectionService->getMethodParameters($controllerObjectName, $commandMethodName);
     $requiredArguments = array();
     $optionalArguments = array();
     $argumentNames = array();
     foreach ($commandMethodParameters as $parameterName => $parameterInfo) {
         $argumentNames[] = $parameterName;
         if ($parameterInfo['optional'] === FALSE) {
             $requiredArguments[strtolower($parameterName)] = array('parameterName' => $parameterName, 'type' => $parameterInfo['type']);
         } else {
             $optionalArguments[strtolower($parameterName)] = array('parameterName' => $parameterName, 'type' => $parameterInfo['type']);
         }
     }
     $decidedToUseNamedArguments = FALSE;
     $decidedToUseUnnamedArguments = FALSE;
     $argumentIndex = 0;
     while (count($rawCommandLineArguments) > 0) {
         $rawArgument = array_shift($rawCommandLineArguments);
         if ($rawArgument !== '' && $rawArgument[0] === '-') {
             if ($rawArgument[1] === '-') {
                 $rawArgument = substr($rawArgument, 2);
             } else {
                 $rawArgument = substr($rawArgument, 1);
             }
             $argumentName = $this->extractArgumentNameFromCommandLinePart($rawArgument);
             if (isset($optionalArguments[$argumentName])) {
                 $argumentValue = $this->getValueOfCurrentCommandLineOption($rawArgument, $rawCommandLineArguments, $optionalArguments[$argumentName]['type']);
                 $commandLineArguments[$optionalArguments[$argumentName]['parameterName']] = $argumentValue;
             } elseif (isset($requiredArguments[$argumentName])) {
                 if ($decidedToUseUnnamedArguments) {
                     throw new \TYPO3\Flow\Mvc\Exception\InvalidArgumentMixingException(sprintf('Unexpected named argument "%s". If you use unnamed arguments, all required arguments must be passed without a name.', $argumentName), 1309971821);
                 }
                 $decidedToUseNamedArguments = TRUE;
                 $argumentValue = $this->getValueOfCurrentCommandLineOption($rawArgument, $rawCommandLineArguments, $requiredArguments[$argumentName]['type']);
                 $commandLineArguments[$requiredArguments[$argumentName]['parameterName']] = $argumentValue;
                 unset($requiredArguments[$argumentName]);
             }
         } else {
             if (count($requiredArguments) > 0) {
                 if ($decidedToUseNamedArguments) {
                     throw new \TYPO3\Flow\Mvc\Exception\InvalidArgumentMixingException(sprintf('Unexpected unnamed argument "%s". If you use named arguments, all required arguments must be passed named.', $rawArgument), 1309971820);
                 }
                 $argument = array_shift($requiredArguments);
                 $commandLineArguments[$argument['parameterName']] = $rawArgument;
                 $decidedToUseUnnamedArguments = TRUE;
             } else {
                 $exceedingArguments[] = $rawArgument;
             }
         }
         $argumentIndex++;
     }
     return array($commandLineArguments, $exceedingArguments);
 }
 /**
  * This function tries to find yet unmatched dependencies which need to be injected via "inject*" setter methods.
  *
  * @param array &$objectConfigurations
  * @return void
  * @throws \TYPO3\Flow\Object\Exception if an injected property is private
  */
 protected function autowireProperties(array &$objectConfigurations)
 {
     foreach ($objectConfigurations as $objectConfiguration) {
         $className = $objectConfiguration->getClassName();
         $properties = $objectConfiguration->getProperties();
         $classMethodNames = get_class_methods($className);
         if (!is_array($classMethodNames)) {
             if (!class_exists($className)) {
                 throw new \TYPO3\Flow\Object\Exception\UnknownClassException(sprintf('The class "%s" defined in the object configuration for object "%s", defined in package: %s, does not exist.', $className, $objectConfiguration->getObjectName(), $objectConfiguration->getPackageKey()), 1352371371);
             } else {
                 throw new \TYPO3\Flow\Object\Exception\UnknownClassException(sprintf('Could not autowire properties of class "%s" because names of methods contained in that class could not be retrieved using get_class_methods().', $className), 1352386418);
             }
         }
         foreach ($classMethodNames as $methodName) {
             if (strlen($methodName) > 6 && substr($methodName, 0, 6) === 'inject' && $methodName[6] === strtoupper($methodName[6])) {
                 $propertyName = lcfirst(substr($methodName, 6));
                 $autowiringAnnotation = $this->reflectionService->getMethodAnnotation($className, $methodName, 'TYPO3\\Flow\\Annotations\\Autowiring');
                 if ($autowiringAnnotation !== NULL && $autowiringAnnotation->enabled === FALSE) {
                     continue;
                 }
                 if ($methodName === 'injectSettings') {
                     $packageKey = $objectConfiguration->getPackageKey();
                     if ($packageKey !== NULL) {
                         $properties[$propertyName] = new ConfigurationProperty($propertyName, $packageKey, ConfigurationProperty::PROPERTY_TYPES_SETTING);
                     }
                 } else {
                     if (array_key_exists($propertyName, $properties)) {
                         continue;
                     }
                     $methodParameters = $this->reflectionService->getMethodParameters($className, $methodName);
                     if (count($methodParameters) !== 1) {
                         $this->systemLogger->log(sprintf('Could not autowire property %s because %s() expects %s instead of exactly 1 parameter.', "{$className}::{$propertyName}", $methodName, count($methodParameters) ?: 'none'), LOG_DEBUG);
                         continue;
                     }
                     $methodParameter = array_pop($methodParameters);
                     if ($methodParameter['class'] === NULL) {
                         $this->systemLogger->log(sprintf('Could not autowire property %s because the method parameter in %s() contained no class type hint.', "{$className}::{$propertyName}", $methodName), LOG_DEBUG);
                         continue;
                     }
                     $properties[$propertyName] = new ConfigurationProperty($propertyName, $methodParameter['class'], ConfigurationProperty::PROPERTY_TYPES_OBJECT);
                 }
             }
         }
         foreach ($this->reflectionService->getPropertyNamesByAnnotation($className, 'TYPO3\\Flow\\Annotations\\Inject') as $propertyName) {
             if ($this->reflectionService->isPropertyPrivate($className, $propertyName)) {
                 $exceptionMessage = 'The property "' . $propertyName . '" in class "' . $className . '" must not be private when annotated for injection.';
                 throw new \TYPO3\Flow\Object\Exception($exceptionMessage, 1328109641);
             }
             if (!array_key_exists($propertyName, $properties)) {
                 $objectName = trim(implode('', $this->reflectionService->getPropertyTagValues($className, $propertyName, 'var')), ' \\');
                 $properties[$propertyName] = new ConfigurationProperty($propertyName, $objectName, ConfigurationProperty::PROPERTY_TYPES_OBJECT);
             }
         }
         $objectConfiguration->setProperties($properties);
     }
 }
 /**
  * Get the constructor argument reflection for the given object type.
  *
  * @param string $className
  * @return array<array>
  */
 protected function getConstructorArgumentsForClass($className)
 {
     if (!isset($this->constructorReflectionFirstLevelCache[$className])) {
         $constructorSignature = array();
         // TODO: Check if we can get rid of this reflection service usage, directly reflecting doesn't work as the proxy class __construct has no arguments.
         if ($this->reflectionService->hasMethod($className, '__construct')) {
             $constructorSignature = $this->reflectionService->getMethodParameters($className, '__construct');
         }
         $this->constructorReflectionFirstLevelCache[$className] = $constructorSignature;
     }
     return $this->constructorReflectionFirstLevelCache[$className];
 }
 /**
  * Detects and registers any validators for arguments:
  * - by the data type specified in the param annotations
  * - additional validators specified in the validate annotations of a method
  *
  * @param string $className
  * @param string $methodName
  * @param array $methodParameters Optional pre-compiled array of method parameters
  * @param array $methodValidateAnnotations Optional pre-compiled array of validate annotations (as array)
  * @return array An Array of ValidatorConjunctions for each method parameters.
  * @throws \TYPO3\Flow\Validation\Exception\InvalidValidationConfigurationException
  * @throws \TYPO3\Flow\Validation\Exception\NoSuchValidatorException
  * @throws \TYPO3\Flow\Validation\Exception\InvalidTypeHintException
  */
 public function buildMethodArgumentsValidatorConjunctions($className, $methodName, array $methodParameters = NULL, array $methodValidateAnnotations = NULL)
 {
     $validatorConjunctions = array();
     if ($methodParameters === NULL) {
         $methodParameters = $this->reflectionService->getMethodParameters($className, $methodName);
     }
     if (count($methodParameters) === 0) {
         return $validatorConjunctions;
     }
     foreach ($methodParameters as $parameterName => $methodParameter) {
         $validatorConjunction = $this->createValidator('TYPO3\\Flow\\Validation\\Validator\\ConjunctionValidator');
         if (!array_key_exists('type', $methodParameter)) {
             throw new Exception\InvalidTypeHintException('Missing type information, probably no @param annotation for parameter "$' . $parameterName . '" in ' . $className . '->' . $methodName . '()', 1281962564);
         }
         if (strpos($methodParameter['type'], '\\') === FALSE) {
             $typeValidator = $this->createValidator($methodParameter['type']);
         } elseif (strpos($methodParameter['type'], '\\Model\\') !== FALSE) {
             $possibleValidatorClassName = str_replace('\\Model\\', '\\Validator\\', $methodParameter['type']) . 'Validator';
             $typeValidator = $this->createValidator($possibleValidatorClassName);
         } else {
             $typeValidator = NULL;
         }
         if ($typeValidator !== NULL) {
             $validatorConjunction->addValidator($typeValidator);
         }
         $validatorConjunctions[$parameterName] = $validatorConjunction;
     }
     if ($methodValidateAnnotations === NULL) {
         $validateAnnotations = $this->reflectionService->getMethodAnnotations($className, $methodName, 'TYPO3\\Flow\\Annotations\\Validate');
         $methodValidateAnnotations = array_map(function ($validateAnnotation) {
             return array('type' => $validateAnnotation->type, 'options' => $validateAnnotation->options, 'argumentName' => $validateAnnotation->argumentName);
         }, $validateAnnotations);
     }
     foreach ($methodValidateAnnotations as $annotationParameters) {
         $newValidator = $this->createValidator($annotationParameters['type'], $annotationParameters['options']);
         if ($newValidator === NULL) {
             throw new Exception\NoSuchValidatorException('Invalid validate annotation in ' . $className . '->' . $methodName . '(): Could not resolve class name for  validator "' . $annotationParameters['type'] . '".', 1239853109);
         }
         if (isset($validatorConjunctions[$annotationParameters['argumentName']])) {
             $validatorConjunctions[$annotationParameters['argumentName']]->addValidator($newValidator);
         } elseif (strpos($annotationParameters['argumentName'], '.') !== FALSE) {
             $objectPath = explode('.', $annotationParameters['argumentName']);
             $argumentName = array_shift($objectPath);
             $validatorConjunctions[$argumentName]->addValidator($this->buildSubObjectValidator($objectPath, $newValidator));
         } else {
             throw new Exception\InvalidValidationConfigurationException('Invalid validate annotation in ' . $className . '->' . $methodName . '(): Validator specified for argument name "' . $annotationParameters['argumentName'] . '", but this argument does not exist.', 1253172726);
         }
     }
     return $validatorConjunctions;
 }
 /**
  * Generates the parameters code needed to call the constructor with the saved parameters.
  *
  * @param string $className Name of the class the method is declared in
  * @return string The generated parameters code
  */
 protected function buildSavedConstructorParametersCode($className)
 {
     if ($className === NULL) {
         return '';
     }
     $parametersCode = '';
     $methodParameters = $this->reflectionService->getMethodParameters($className, '__construct');
     $methodParametersCount = count($methodParameters);
     if ($methodParametersCount > 0) {
         foreach ($methodParameters as $methodParameterName => $methodParameterInfo) {
             $methodParametersCount--;
             $parametersCode .= '$this->Flow_Aop_Proxy_originalConstructorArguments[\'' . $methodParameterName . '\']' . ($methodParametersCount > 0 ? ', ' : '');
         }
     }
     return $parametersCode;
 }
 /**
  * intialize the arguments
  * 
  */
 protected function initializeArguments()
 {
     $methodParameters = $this->reflectionService->getMethodParameters($this->class, $this->method);
     $validators = $this->validatorResolver->buildMethodArgumentsValidatorConjunctions($this->class, $this->method);
     $validationGroups = array('Default', ucfirst($this->method));
     foreach ($methodParameters as $name => $methodParameter) {
         $methodParameterType = $methodParameter['type'] == 'mixed' ? 'string' : $methodParameter['type'];
         $validator = $validators[$name];
         $validator->addValidator($this->validatorResolver->getBaseValidatorConjunction($methodParameterType, $validationGroups));
         $argument = new WebserviceCallArgument($name, $methodParameterType);
         $argument->setPosition($methodParameter['position']);
         $argument->setRequired(!$methodParameter['optional']);
         $argument->setDefaultValue($methodParameter['defaultValue']);
         $argument->setValidator($validator);
         $this->arguments[$name] = $argument;
     }
 }
 /**
  * Initializes the arguments array of this controller by creating an empty argument object for each of the
  * method arguments found in the designated command method.
  *
  * @return void
  * @throws InvalidArgumentTypeException
  */
 protected function initializeCommandMethodArguments()
 {
     $this->arguments->removeAll();
     $methodParameters = $this->reflectionService->getMethodParameters(get_class($this), $this->commandMethodName);
     foreach ($methodParameters as $parameterName => $parameterInfo) {
         $dataType = null;
         if (isset($parameterInfo['type'])) {
             $dataType = $parameterInfo['type'];
         } elseif ($parameterInfo['array']) {
             $dataType = 'array';
         }
         if ($dataType === null) {
             throw new InvalidArgumentTypeException(sprintf('The argument type for parameter $%s of method %s->%s() could not be detected.', $parameterName, get_class($this), $this->commandMethodName), 1306755296);
         }
         $defaultValue = isset($parameterInfo['defaultValue']) ? $parameterInfo['defaultValue'] : null;
         $this->arguments->addNewArgument($parameterName, $dataType, $parameterInfo['optional'] === false, $defaultValue);
     }
 }
 /**
  * Builds the PHP code for the parameters of the specified method to be
  * used in a method interceptor in the proxy class
  *
  * @param string $fullClassName Name of the class the method is declared in
  * @param string $methodName Name of the method to create the parameters code for
  * @param boolean $addTypeAndDefaultValue If the type and default value for each parameters should be rendered
  * @return string A comma speparated list of parameters
  */
 public function buildMethodParametersCode($fullClassName, $methodName, $addTypeAndDefaultValue = true)
 {
     $methodParametersCode = '';
     $methodParameterTypeName = '';
     $defaultValue = '';
     $byReferenceSign = '';
     if ($fullClassName === null || $methodName === null) {
         return '';
     }
     $methodParameters = $this->reflectionService->getMethodParameters($fullClassName, $methodName);
     if (count($methodParameters) > 0) {
         $methodParametersCount = 0;
         foreach ($methodParameters as $methodParameterName => $methodParameterInfo) {
             if ($addTypeAndDefaultValue) {
                 if ($methodParameterInfo['array'] === true) {
                     $methodParameterTypeName = 'array';
                 } elseif ($methodParameterInfo['scalarDeclaration']) {
                     $methodParameterTypeName = $methodParameterInfo['type'];
                 } else {
                     $methodParameterTypeName = $methodParameterInfo['class'] === null ? '' : '\\' . $methodParameterInfo['class'];
                 }
                 if ($methodParameterInfo['optional'] === true) {
                     $rawDefaultValue = isset($methodParameterInfo['defaultValue']) ? $methodParameterInfo['defaultValue'] : null;
                     if ($rawDefaultValue === null) {
                         $defaultValue = ' = NULL';
                     } elseif (is_bool($rawDefaultValue)) {
                         $defaultValue = $rawDefaultValue ? ' = TRUE' : ' = FALSE';
                     } elseif (is_numeric($rawDefaultValue)) {
                         $defaultValue = ' = ' . $rawDefaultValue;
                     } elseif (is_string($rawDefaultValue)) {
                         $defaultValue = " = '" . $rawDefaultValue . "'";
                     } elseif (is_array($rawDefaultValue)) {
                         $defaultValue = ' = ' . $this->buildArraySetupCode($rawDefaultValue);
                     }
                 }
                 $byReferenceSign = $methodParameterInfo['byReference'] ? '&' : '';
             }
             $methodParametersCode .= ($methodParametersCount > 0 ? ', ' : '') . ($methodParameterTypeName ? $methodParameterTypeName . ' ' : '') . $byReferenceSign . '$' . $methodParameterName . $defaultValue;
             $methodParametersCount++;
         }
     }
     return $methodParametersCode;
 }
Exemple #14
0
 /**
  * Ext Direct does not provide named arguments by now, so we have
  * to map them by reflecting on the action parameters.
  *
  * @return array The mapped arguments
  */
 public function getArguments()
 {
     if ($this->data === array()) {
         return array();
     }
     $arguments = array();
     if (!$this->request->isFormPost()) {
         $parameters = $this->reflectionService->getMethodParameters($this->getControllerObjectName(), $this->method . 'Action');
         // TODO Add checks for parameters
         foreach ($parameters as $name => $options) {
             $parameterIndex = $options['position'];
             if (isset($this->data[$parameterIndex])) {
                 $arguments[$name] = $this->convertObjectToArray($this->data[$parameterIndex]);
             }
         }
     } else {
         // TODO Reuse setArgumentsFromRawRequestData from Web/RequestBuilder
     }
     return $arguments;
 }
 /**
  * Returns an array of \TYPO3\Flow\Cli\CommandArgumentDefinition that contains
  * information about required/optional arguments of this command.
  * If the command does not expect any arguments, an empty array is returned
  *
  * @return array<\TYPO3\Flow\Cli\CommandArgumentDefinition>
  */
 public function getArgumentDefinitions()
 {
     if (!$this->hasArguments()) {
         return array();
     }
     $commandArgumentDefinitions = array();
     $commandMethodReflection = $this->getCommandMethodReflection();
     $annotations = $commandMethodReflection->getTagsValues();
     $commandParameters = $this->reflectionService->getMethodParameters($this->controllerClassName, $this->controllerCommandName . 'Command');
     $i = 0;
     foreach ($commandParameters as $commandParameterName => $commandParameterDefinition) {
         $explodedAnnotation = explode(' ', $annotations['param'][$i]);
         array_shift($explodedAnnotation);
         array_shift($explodedAnnotation);
         $description = implode(' ', $explodedAnnotation);
         $required = $commandParameterDefinition['optional'] !== TRUE;
         $commandArgumentDefinitions[] = new CommandArgumentDefinition($commandParameterName, $required, $description);
         $i++;
     }
     return $commandArgumentDefinitions;
 }
 /**
  * Builds a new instance of $objectType with the given $possibleConstructorArgumentValues.
  * If constructor argument values are missing from the given array the method looks for a
  * default value in the constructor signature.
  *
  * Furthermore, the constructor arguments are removed from $possibleConstructorArgumentValues
  *
  * @param array &$possibleConstructorArgumentValues
  * @param string $objectType
  * @return object The created instance
  * @throws \TYPO3\Flow\Property\Exception\InvalidTargetException if a required constructor argument is missing
  */
 protected function buildObject(array &$possibleConstructorArgumentValues, $objectType)
 {
     $className = $this->objectManager->getClassNameByObjectName($objectType);
     if ($this->reflectionService->hasMethod($className, '__construct')) {
         $constructorSignature = $this->reflectionService->getMethodParameters($className, '__construct');
         $constructorArguments = array();
         foreach ($constructorSignature as $constructorArgumentName => $constructorArgumentInformation) {
             if (array_key_exists($constructorArgumentName, $possibleConstructorArgumentValues)) {
                 $constructorArguments[] = $possibleConstructorArgumentValues[$constructorArgumentName];
                 unset($possibleConstructorArgumentValues[$constructorArgumentName]);
             } elseif ($constructorArgumentInformation['optional'] === TRUE) {
                 $constructorArguments[] = $constructorArgumentInformation['defaultValue'];
             } else {
                 throw new \TYPO3\Flow\Property\Exception\InvalidTargetException('Missing constructor argument "' . $constructorArgumentName . '" for object of type "' . $objectType . '".', 1268734872);
             }
         }
         $classReflection = new \ReflectionClass($className);
         return $classReflection->newInstanceArgs($constructorArguments);
     } else {
         return new $className();
     }
 }
 /**
  * Convert array to change interface
  *
  * @param array $changeData
  * @return ChangeInterface
  */
 protected function convertChangeData($changeData)
 {
     $type = $changeData['type'];
     if (!isset($this->typeMap[$type])) {
         return new \TYPO3\Flow\Error\Error(sprintf('Could not convert change type %s, it is unknown to the system', $type));
     }
     $changeClass = $this->typeMap[$type];
     $changeClassInstance = $this->objectManager->get($changeClass);
     $changeClassInstance->injectPersistenceManager($this->persistenceManager);
     $subjectContextPath = $changeData['subject'];
     $subject = $this->nodeService->getNodeFromContextPath($subjectContextPath);
     if ($subject instanceof \TYPO3\Flow\Error\Error) {
         return $subject;
     }
     $changeClassInstance->setSubject($subject);
     if (isset($changeData['reference']) && method_exists($changeClassInstance, 'setReference')) {
         $referenceContextPath = $changeData['reference'];
         $reference = $this->nodeService->getNodeFromContextPath($referenceContextPath);
         if ($reference instanceof \TYPO3\Flow\Error\Error) {
             return $reference;
         }
         $changeClassInstance->setReference($reference);
     }
     if (isset($changeData['payload'])) {
         foreach ($changeData['payload'] as $propertyName => $value) {
             if (!in_array($propertyName, $this->disallowedPayloadProperties)) {
                 $methodParameters = $this->reflectionService->getMethodParameters($changeClass, ObjectAccess::buildSetterMethodName($propertyName));
                 $methodParameter = current($methodParameters);
                 $targetType = $methodParameter['type'];
                 $value = $this->propertyMapper->convert($value, $targetType);
                 ObjectAccess::setProperty($changeClassInstance, $propertyName, $value);
             }
         }
     }
     return $changeClassInstance;
 }
 /**
  * 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++;
     }
 }
 /**
  * This function tries to find yet unmatched dependencies which need to be injected via "inject*" setter methods.
  *
  * @param array &$objectConfigurations
  * @return void
  * @throws \TYPO3\Flow\Object\Exception if an injected property is private
  */
 protected function autowireProperties(array &$objectConfigurations)
 {
     /** @var Configuration $objectConfiguration */
     foreach ($objectConfigurations as $objectConfiguration) {
         $className = $objectConfiguration->getClassName();
         $properties = $objectConfiguration->getProperties();
         if ($className === '') {
             continue;
         }
         $classMethodNames = get_class_methods($className);
         if (!is_array($classMethodNames)) {
             if (!class_exists($className)) {
                 throw new \TYPO3\Flow\Object\Exception\UnknownClassException(sprintf('The class "%s" defined in the object configuration for object "%s", defined in package: %s, does not exist.', $className, $objectConfiguration->getObjectName(), $objectConfiguration->getPackageKey()), 1352371371);
             } else {
                 throw new \TYPO3\Flow\Object\Exception\UnknownClassException(sprintf('Could not autowire properties of class "%s" because names of methods contained in that class could not be retrieved using get_class_methods().', $className), 1352386418);
             }
         }
         foreach ($classMethodNames as $methodName) {
             if (isset($methodName[6]) && strpos($methodName, 'inject') === 0 && $methodName[6] === strtoupper($methodName[6])) {
                 $propertyName = lcfirst(substr($methodName, 6));
                 $autowiringAnnotation = $this->reflectionService->getMethodAnnotation($className, $methodName, \TYPO3\Flow\Annotations\Autowiring::class);
                 if ($autowiringAnnotation !== NULL && $autowiringAnnotation->enabled === FALSE) {
                     continue;
                 }
                 if ($methodName === 'injectSettings') {
                     $packageKey = $objectConfiguration->getPackageKey();
                     if ($packageKey !== NULL) {
                         $properties[$propertyName] = new ConfigurationProperty($propertyName, array('type' => ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, 'path' => $packageKey), ConfigurationProperty::PROPERTY_TYPES_CONFIGURATION);
                     }
                 } else {
                     if (array_key_exists($propertyName, $properties)) {
                         continue;
                     }
                     $methodParameters = $this->reflectionService->getMethodParameters($className, $methodName);
                     if (count($methodParameters) !== 1) {
                         $this->systemLogger->log(sprintf('Could not autowire property %s because %s() expects %s instead of exactly 1 parameter.', $className . '::' . $propertyName, $methodName, count($methodParameters) ?: 'none'), LOG_DEBUG);
                         continue;
                     }
                     $methodParameter = array_pop($methodParameters);
                     if ($methodParameter['class'] === NULL) {
                         $this->systemLogger->log(sprintf('Could not autowire property %s because the method parameter in %s() contained no class type hint.', $className . '::' . $propertyName, $methodName), LOG_DEBUG);
                         continue;
                     }
                     $properties[$propertyName] = new ConfigurationProperty($propertyName, $methodParameter['class'], ConfigurationProperty::PROPERTY_TYPES_OBJECT);
                 }
             }
         }
         foreach ($this->reflectionService->getPropertyNamesByAnnotation($className, \TYPO3\Flow\Annotations\Inject::class) as $propertyName) {
             if ($this->reflectionService->isPropertyPrivate($className, $propertyName)) {
                 throw new \TYPO3\Flow\Object\Exception(sprintf('The property "%%s" in class "%s" must not be private when annotated for injection.', $propertyName, $className), 1328109641);
             }
             if (!array_key_exists($propertyName, $properties)) {
                 /** @var Inject $injectAnnotation */
                 $injectAnnotation = $this->reflectionService->getPropertyAnnotation($className, $propertyName, \TYPO3\Flow\Annotations\Inject::class);
                 // TODO: Should be removed with 3.2. Inject settings by Inject-Annotation is deprecated since 3.0. Injecting settings by annotation should be done using the InjectConfiguration annotation
                 if ($injectAnnotation->setting !== NULL) {
                     $packageKey = $injectAnnotation->package !== NULL ? $injectAnnotation->package : $objectConfiguration->getPackageKey();
                     $configurationPath = rtrim($packageKey . '.' . $injectAnnotation->setting, '.');
                     $properties[$propertyName] = new ConfigurationProperty($propertyName, array('type' => ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, 'path' => $configurationPath), ConfigurationProperty::PROPERTY_TYPES_CONFIGURATION);
                 } else {
                     $objectName = trim(implode('', $this->reflectionService->getPropertyTagValues($className, $propertyName, 'var')), ' \\');
                     $configurationProperty = new ConfigurationProperty($propertyName, $objectName, ConfigurationProperty::PROPERTY_TYPES_OBJECT, NULL, $injectAnnotation->lazy);
                     $properties[$propertyName] = $configurationProperty;
                 }
             }
         }
         foreach ($this->reflectionService->getPropertyNamesByAnnotation($className, \TYPO3\Flow\Annotations\InjectConfiguration::class) as $propertyName) {
             if ($this->reflectionService->isPropertyPrivate($className, $propertyName)) {
                 throw new \TYPO3\Flow\Object\Exception(sprintf('The property "%s" in class "%s" must not be private when annotated for configuration injection.', $propertyName, $className), 1416765599);
             }
             if (array_key_exists($propertyName, $properties)) {
                 continue;
             }
             /** @var InjectConfiguration $injectConfigurationAnnotation */
             $injectConfigurationAnnotation = $this->reflectionService->getPropertyAnnotation($className, $propertyName, \TYPO3\Flow\Annotations\InjectConfiguration::class);
             if ($injectConfigurationAnnotation->type === ConfigurationManager::CONFIGURATION_TYPE_SETTINGS) {
                 $packageKey = $injectConfigurationAnnotation->package !== NULL ? $injectConfigurationAnnotation->package : $objectConfiguration->getPackageKey();
                 $configurationPath = rtrim($packageKey . '.' . $injectConfigurationAnnotation->path, '.');
             } else {
                 if ($injectConfigurationAnnotation->package !== NULL) {
                     throw new \TYPO3\Flow\Object\Exception(sprintf('The InjectConfiguration annotation for property "%s" in class "%s" specifies a "package" key for configuration type "%s", but this is only supported for injection of "Settings".', $propertyName, $className, $injectConfigurationAnnotation->type), 1420811958);
                 }
                 $configurationPath = $injectConfigurationAnnotation->path;
             }
             $properties[$propertyName] = new ConfigurationProperty($propertyName, array('type' => $injectConfigurationAnnotation->type, 'path' => $configurationPath), ConfigurationProperty::PROPERTY_TYPES_CONFIGURATION);
         }
         $objectConfiguration->setProperties($properties);
     }
 }
 /**
  * Renders additional code for the __construct() method of the Proxy Class which realizes constructor injection.
  *
  * @param Configuration $objectConfiguration
  * @return string The built code
  * @throws \TYPO3\Flow\Object\Exception\UnknownObjectException
  */
 protected function buildConstructorInjectionCode(Configuration $objectConfiguration)
 {
     $assignments = array();
     $argumentConfigurations = $objectConfiguration->getArguments();
     $constructorParameterInfo = $this->reflectionService->getMethodParameters($objectConfiguration->getClassName(), '__construct');
     $argumentNumberToOptionalInfo = array();
     foreach ($constructorParameterInfo as $parameterInfo) {
         $argumentNumberToOptionalInfo[$parameterInfo['position'] + 1] = $parameterInfo['optional'];
     }
     foreach ($argumentConfigurations as $argumentNumber => $argumentConfiguration) {
         if ($argumentConfiguration === null) {
             continue;
         }
         $argumentValue = $argumentConfiguration->getValue();
         $assignmentPrologue = 'if (!array_key_exists(' . ($argumentNumber - 1) . ', $arguments)) $arguments[' . ($argumentNumber - 1) . '] = ';
         if ($argumentValue === null && isset($argumentNumberToOptionalInfo[$argumentNumber]) && $argumentNumberToOptionalInfo[$argumentNumber] === true) {
             $assignments[] = $assignmentPrologue . 'NULL';
         } else {
             switch ($argumentConfiguration->getType()) {
                 case ConfigurationArgument::ARGUMENT_TYPES_OBJECT:
                     if ($argumentValue instanceof Configuration) {
                         $argumentValueObjectName = $argumentValue->getObjectName();
                         $argumentValueClassName = $argumentValue->getClassName();
                         if ($argumentValueClassName === null) {
                             $preparedArgument = $this->buildCustomFactoryCall($argumentValue->getFactoryObjectName(), $argumentValue->getFactoryMethodName(), $argumentValue->getArguments());
                             $assignments[] = $assignmentPrologue . $preparedArgument;
                         } else {
                             if ($this->objectConfigurations[$argumentValueObjectName]->getScope() === Configuration::SCOPE_PROTOTYPE) {
                                 $assignments[] = $assignmentPrologue . 'new \\' . $argumentValueObjectName . '(' . $this->buildMethodParametersCode($argumentValue->getArguments()) . ')';
                             } else {
                                 $assignments[] = $assignmentPrologue . '\\TYPO3\\Flow\\Core\\Bootstrap::$staticObjectManager->get(\'' . $argumentValueObjectName . '\')';
                             }
                         }
                     } else {
                         if (strpos($argumentValue, '.') !== false) {
                             $settingPath = explode('.', $argumentValue);
                             $settings = Arrays::getValueByPath($this->configurationManager->getConfiguration(ConfigurationManager::CONFIGURATION_TYPE_SETTINGS), array_shift($settingPath));
                             $argumentValue = Arrays::getValueByPath($settings, $settingPath);
                         }
                         if (!isset($this->objectConfigurations[$argumentValue])) {
                             throw new \TYPO3\Flow\Object\Exception\UnknownObjectException('The object "' . $argumentValue . '" which was specified as an argument in the object configuration of object "' . $objectConfiguration->getObjectName() . '" does not exist.', 1264669967);
                         }
                         $assignments[] = $assignmentPrologue . '\\TYPO3\\Flow\\Core\\Bootstrap::$staticObjectManager->get(\'' . $argumentValue . '\')';
                     }
                     break;
                 case ConfigurationArgument::ARGUMENT_TYPES_STRAIGHTVALUE:
                     $assignments[] = $assignmentPrologue . var_export($argumentValue, true);
                     break;
                 case ConfigurationArgument::ARGUMENT_TYPES_SETTING:
                     $assignments[] = $assignmentPrologue . '\\TYPO3\\Flow\\Core\\Bootstrap::$staticObjectManager->getSettingsByPath(explode(\'.\', \'' . $argumentValue . '\'))';
                     break;
             }
         }
     }
     $code = count($assignments) > 0 ? "\n\t\t" . implode(";\n\t\t", $assignments) . ";\n" : '';
     $index = 0;
     foreach ($constructorParameterInfo as $parameterName => $parameterInfo) {
         if ($parameterInfo['optional'] === true) {
             break;
         }
         if ($objectConfiguration->getScope() === Configuration::SCOPE_SINGLETON) {
             $code .= '		if (!array_key_exists(' . $index . ', $arguments)) throw new \\TYPO3\\Flow\\Object\\Exception\\UnresolvedDependenciesException(\'Missing required constructor argument $' . $parameterName . ' in class \' . __CLASS__ . \'. Please check your calling code and Dependency Injection configuration.\', 1296143787);' . "\n";
         } else {
             $code .= '		if (!array_key_exists(' . $index . ', $arguments)) throw new \\TYPO3\\Flow\\Object\\Exception\\UnresolvedDependenciesException(\'Missing required constructor argument $' . $parameterName . ' in class \' . __CLASS__ . \'. Note that constructor injection is only support for objects of scope singleton (and this is not a singleton) – for other scopes you must pass each required argument to the constructor yourself.\', 1296143788);' . "\n";
         }
         $index++;
     }
     return $code;
 }