/** * Default implementation for use in compiled templates * * @param array $arguments * @param \Closure $renderChildrenClosure * @param RenderingContextInterface $renderingContext * @return mixed */ public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) { if (self::$staticReflectionService === NULL) { $objectManager = GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager'); self::$staticReflectionService = $objectManager->get('TYPO3\\CMS\\Extbase\\Reflection\\ReflectionService'); } $property = $arguments['property']; $validatorName = isset($arguments['validatorName']) ? $arguments['validatorName'] : NULL; $object = isset($arguments['object']) ? $arguments['object'] : NULL; if (NULL === $object) { $object = self::getFormObject($renderingContext->getViewHelperVariableContainer()); } $className = get_class($object); if (FALSE !== strpos($property, '.')) { $pathSegments = explode('.', $property); foreach ($pathSegments as $property) { if (TRUE === ctype_digit($property)) { continue; } $annotations = self::$staticReflectionService->getPropertyTagValues($className, $property, 'var'); $possibleClassName = array_pop($annotations); if (FALSE !== strpos($possibleClassName, '<')) { $className = array_pop(explode('<', trim($possibleClassName, '>'))); } elseif (TRUE === class_exists($possibleClassName)) { $className = $possibleClassName; } } } $annotations = self::$staticReflectionService->getPropertyTagValues($className, $property, 'validate'); $hasEvaluated = TRUE; if (0 < count($annotations) && (NULL === $validatorName || TRUE === in_array($validatorName, $annotations))) { return static::renderStaticThenChild($arguments, $hasEvaluated); } return static::renderStaticElseChild($arguments, $hasEvaluated); }
/** * Render * * Renders the then-child if the property at $property of the * object at $object (or the associated form object if $object * is not specified) uses a certain @validate validator. * * @param string $property The property name, dotted path supported, to determine required * @param string $validatorName The class name of the Validator that indicates the property is required * @param DomainObjectInterface $object Optional object - if not specified, grabs the associated form object * @return string */ public function render($property, $validatorName = NULL, DomainObjectInterface $object = NULL) { if (NULL === $object) { $object = $this->getFormObject(); } $className = get_class($object); if (FALSE !== strpos($property, '.')) { $pathSegments = explode('.', $property); foreach ($pathSegments as $property) { if (TRUE === ctype_digit($property)) { continue; } $annotations = $this->ownReflectionService->getPropertyTagValues($className, $property, 'var'); $possibleClassName = array_pop($annotations); if (FALSE !== strpos($possibleClassName, '<')) { $className = array_pop(explode('<', trim($possibleClassName, '>'))); } elseif (TRUE === class_exists($possibleClassName)) { $className = $possibleClassName; } } } $annotations = $this->ownReflectionService->getPropertyTagValues($className, $property, 'validate'); if (0 < count($annotations) && (NULL === $validatorName || TRUE === in_array($validatorName, $annotations))) { return $this->renderThenChild(); } return $this->renderElseChild(); }
/** * @param array $arguments * @return boolean */ protected static function evaluateCondition($arguments = null) { if (self::$staticReflectionService === null) { $objectManager = GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager'); self::$staticReflectionService = $objectManager->get('TYPO3\\CMS\\Extbase\\Reflection\\ReflectionService'); } $property = $arguments['property']; $validatorName = isset($arguments['validatorName']) ? $arguments['validatorName'] : null; $object = isset($arguments['object']) ? $arguments['object'] : null; if (null === $object) { $object = static::getFormObject($renderingContext->getViewHelperVariableContainer()); } $className = get_class($object); if (false !== strpos($property, '.')) { $pathSegments = explode('.', $property); foreach ($pathSegments as $property) { if (true === ctype_digit($property)) { continue; } $annotations = self::$staticReflectionService->getPropertyTagValues($className, $property, 'var'); $possibleClassName = array_pop($annotations); if (false !== strpos($possibleClassName, '<')) { $className = array_pop(explode('<', trim($possibleClassName, '>'))); } elseif (true === class_exists($possibleClassName)) { $className = $possibleClassName; } } } $annotations = self::$staticReflectionService->getPropertyTagValues($className, $property, 'validate'); return count($annotations) && (!$validatorName || in_array($validatorName, $annotations)); }
/** * Creates the remote api based on the module/plugin configuration using the extbase * reflection features. * * @param string $routeUrl * @param string $namespace * @return array */ public function createApi($routeUrl, $namespace) { $api = []; $api['url'] = $routeUrl; $api['type'] = 'remoting'; $api['namespace'] = $namespace; $api['actions'] = []; if (empty($this->frameworkConfiguration['controllerConfiguration'])) { # @todo improve me! Hack for fetching API of newsletter the hard way! # It looks $this->frameworkConfiguration['controllerConfiguration'] is empty as of TYPO3 6.1. Bug or feature? $this->frameworkConfiguration['controllerConfiguration'] = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions']['Newsletter']['modules']['web_NewsletterTxNewsletterM1']['controllers']; } foreach ($this->frameworkConfiguration['controllerConfiguration'] as $controllerName => $allowedControllerActions) { $unstrippedControllerName = $controllerName . 'Controller'; $controllerObjectName = 'Ecodev\\Newsletter\\Controller\\' . $unstrippedControllerName; $controllerActions = []; foreach ($allowedControllerActions['actions'] as $actionName) { $unstrippedActionName = $actionName . 'Action'; try { $actionParameters = $this->reflectionService->getMethodParameters($controllerObjectName, $unstrippedActionName); $controllerActions[] = ['len' => count($actionParameters), 'name' => $unstrippedActionName]; } catch (ReflectionException $re) { if ($unstrippedActionName !== 'extObjAction') { \Ecodev\Newsletter\Tools::getLogger(__CLASS__)->critical('You have a not existing action (' . $controllerObjectName . '::' . $unstrippedActionName . ') in your module/plugin configuration. This action will not be available for Ext.Direct remote execution.'); } } } $api['actions'][$unstrippedControllerName] = $controllerActions; } return $api; }
public function secureActionArguments($arguments, $request, $controllerClassName) { // look for @modificationAllowed and @creationAllowed annotations on action methods $actionMethodName = $request->getControllerActionName() . 'Action'; $tags = $this->reflectionService->getMethodTagsValues($controllerClassName, $actionMethodName); if (array_key_exists('modificationAllowed', $tags)) { $modificationAllowed = $tags['modificationAllowed']; } else { $modificationAllowed = array(); } if (array_key_exists('creationAllowed', $tags)) { $creationAllowed = $tags['creationAllowed']; } else { $creationAllowed = array(); } // modification and creation are disabled by default on all arguments foreach ($arguments->getArgumentNames() as $argumentName) { $conf = $arguments[$argumentName]->getPropertyMappingConfiguration(); $options = array(); $key = \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED; if (!in_array($argumentName, $modificationAllowed)) { $options[$key] = false; } else { $options[$key] = true; } $key = \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED; if (!in_array($argumentName, $creationAllowed)) { $options[$key] = false; } else { $options[$key] = true; } // set sane defaults #$conf->setTypeConverterOptions('TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter', $options); } }
/** * @test */ public function getTypeOfChildPropertyShouldUseReflectionServiceToDetermineType() { $this->mockReflectionService->expects($this->any())->method('hasMethod')->with('TheTargetType', 'setThePropertyName')->will($this->returnValue(FALSE)); $this->mockReflectionService->expects($this->any())->method('getMethodParameters')->with('TheTargetType', '__construct')->will($this->returnValue(array('thePropertyName' => array('type' => 'TheTypeOfSubObject', 'elementType' => NULL)))); $configuration = new \TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration(); $configuration->setTypeConverterOptions('TYPO3\\CMS\\Extbase\\Property\\TypeConverter\\ObjectConverter', array()); $this->assertEquals('TheTypeOfSubObject', $this->converter->getTypeOfChildProperty('TheTargetType', 'thePropertyName', $configuration)); }
/** * Get all class names inside this namespace and return them as array. * * @param string $namespace * @return array Array of all class names inside a given namespace. */ protected function getClassNamesInNamespace($namespace) { $affectedViewHelperClassNames = array(); $allViewHelperClassNames = $this->reflectionService->getAllSubClassNamesForClass(\TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper::class); foreach ($allViewHelperClassNames as $viewHelperClassName) { if ($this->reflectionService->isClassAbstract($viewHelperClassName)) { continue; } if (strncmp($namespace, $viewHelperClassName, strlen($namespace)) === 0) { $affectedViewHelperClassNames[] = $viewHelperClassName; } } sort($affectedViewHelperClassNames); return $affectedViewHelperClassNames; }
/** * Checks the request hash (HMAC), if arguments have been touched by the property mapper. * * In case the @dontverifyrequesthash-Annotation has been set, this suppresses the exception. * * @return void * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidOrNoRequestHashException In case request hash checking failed * @deprecated since Extbase 1.4.0, will be removed two versions after Extbase 6.1 */ protected function checkRequestHash() { if ($this->configurationManager->isFeatureEnabled('rewrittenPropertyMapper')) { // If the new property mapper is enabled, the request hash is not needed anymore. return; } if (!$this->request instanceof \TYPO3\CMS\Extbase\Mvc\Web\Request) { return; } // We only want to check it for now for web requests. if ($this->request->isHmacVerified()) { return; } // all good $verificationNeeded = FALSE; foreach ($this->arguments as $argument) { if ($argument->getOrigin() == \TYPO3\CMS\Extbase\Mvc\Controller\Argument::ORIGIN_NEWLY_CREATED || $argument->getOrigin() == \TYPO3\CMS\Extbase\Mvc\Controller\Argument::ORIGIN_PERSISTENCE_AND_MODIFIED) { $verificationNeeded = TRUE; } } if ($verificationNeeded) { $methodTagsValues = $this->reflectionService->getMethodTagsValues(get_class($this), $this->actionMethodName); if (!isset($methodTagsValues['dontverifyrequesthash'])) { throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidOrNoRequestHashException('Request hash (HMAC) checking failed. The parameter __hmac was invalid or not set, and objects were modified.', 1255082824); } } }
/** * Register method arguments for "render" by analysing the doc comment above. * * @return void * @throws \TYPO3Fluid\Fluid\Core\Parser\Exception */ protected function registerRenderMethodArguments() { $methodParameters = $this->reflectionService->getMethodParameters(get_class($this), 'render'); if (count($methodParameters) === 0) { return; } $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 = isset($parameterInfo['array']) && (bool) $parameterInfo['array'] ? 'array' : $parameterInfo['type']; } else { 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); } $description = ''; if (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++; } }
/** * 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) * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentMixingException * @return array All and exceeding command line arguments */ 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[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\CMS\Extbase\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\CMS\Extbase\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 { if ($argumentIndex < count($argumentNames)) { $commandLineArguments[$argumentNames[$argumentIndex]] = $rawArgument; } else { $exceedingArguments[] = $rawArgument; } } } $argumentIndex++; } return array($commandLineArguments, $exceedingArguments); }
/** * @test * @author Robert Lemke <*****@*****.**> */ public function booleanOptionsCanHaveOnlyCertainValuesIfTheValueIsAssignedWithoutEqualSign() { $methodParameters = array('b1' => array('optional' => TRUE, 'type' => 'boolean'), 'b2' => array('optional' => TRUE, 'type' => 'boolean'), 'b3' => array('optional' => TRUE, 'type' => 'boolean'), 'b4' => array('optional' => TRUE, 'type' => 'boolean'), 'b5' => array('optional' => TRUE, 'type' => 'boolean'), 'b6' => array('optional' => TRUE, 'type' => 'boolean')); $this->mockReflectionService->expects($this->once())->method('getMethodParameters')->with('Tx_SomeExtensionName_Command_DefaultCommandController', 'listCommand')->will($this->returnValue($methodParameters)); $expectedArguments = array('b1' => TRUE, 'b2' => TRUE, 'b3' => TRUE, 'b4' => FALSE, 'b5' => FALSE, 'b6' => FALSE); $request = $this->requestBuilder->build('some_extension_name:default:list --b2 y --b1 1 --b3 true --b4 false --b5 n --b6 0'); $this->assertEquals($expectedArguments, $request->getArguments()); }
/** * Builds a data map by adding column maps for all the configured columns in the $TCA. * It also resolves the type of values the column is holding and the typo of relation the column * represents. * * @param string $className The class name you want to fetch the Data Map for * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InvalidClassException * @return \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap The data map */ protected function buildDataMapInternal($className) { if (!class_exists($className)) { throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InvalidClassException('Could not find class definition for name "' . $className . '". This could be caused by a mis-spelling of the class name in the class definition.', 1476045117); } $recordType = null; $subclasses = []; $tableName = $this->resolveTableName($className); $columnMapping = []; $frameworkConfiguration = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK); $classSettings = $frameworkConfiguration['persistence']['classes'][$className]; if ($classSettings !== null) { if (isset($classSettings['subclasses']) && is_array($classSettings['subclasses'])) { $subclasses = $this->resolveSubclassesRecursive($frameworkConfiguration['persistence']['classes'], $classSettings['subclasses']); } if (isset($classSettings['mapping']['recordType']) && $classSettings['mapping']['recordType'] !== '') { $recordType = $classSettings['mapping']['recordType']; } if (isset($classSettings['mapping']['tableName']) && $classSettings['mapping']['tableName'] !== '') { $tableName = $classSettings['mapping']['tableName']; } $classHierarchy = array_merge([$className], class_parents($className)); foreach ($classHierarchy as $currentClassName) { if (in_array($currentClassName, [\TYPO3\CMS\Extbase\DomainObject\AbstractEntity::class, \TYPO3\CMS\Extbase\DomainObject\AbstractValueObject::class])) { break; } $currentClassSettings = $frameworkConfiguration['persistence']['classes'][$currentClassName]; if ($currentClassSettings !== null) { if (isset($currentClassSettings['mapping']['columns']) && is_array($currentClassSettings['mapping']['columns'])) { \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($columnMapping, $currentClassSettings['mapping']['columns'], true, false); } } } } /** @var $dataMap \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap */ $dataMap = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap::class, $className, $tableName, $recordType, $subclasses); $dataMap = $this->addMetaDataColumnNames($dataMap, $tableName); // $classPropertyNames = $this->reflectionService->getClassPropertyNames($className); $tcaColumnsDefinition = $this->getColumnsDefinition($tableName); \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($tcaColumnsDefinition, $columnMapping); // @todo Is this is too powerful? foreach ($tcaColumnsDefinition as $columnName => $columnDefinition) { if (isset($columnDefinition['mapOnProperty'])) { $propertyName = $columnDefinition['mapOnProperty']; } else { $propertyName = \TYPO3\CMS\Core\Utility\GeneralUtility::underscoredToLowerCamelCase($columnName); } // if (in_array($propertyName, $classPropertyNames)) { // @todo Enable check for property existence $columnMap = $this->createColumnMap($columnName, $propertyName); $propertyMetaData = $this->reflectionService->getClassSchema($className)->getProperty($propertyName); $columnMap = $this->setType($columnMap, $columnDefinition['config']); $columnMap = $this->setRelations($columnMap, $columnDefinition['config'], $propertyMetaData); $columnMap = $this->setFieldEvaluations($columnMap, $columnDefinition['config']); $dataMap->addColumnMap($columnMap); } return $dataMap; }
/** * Gets the default value of argument * * @param \TYPO3\CMS\Extbase\Mvc\Cli\CommandArgumentDefinition $argument * @return mixed */ protected function getDefaultArgumentValue(\TYPO3\CMS\Extbase\Mvc\Cli\CommandArgumentDefinition $argument) { $type = $this->getArgumentType($argument); $argumentName = $argument->getName(); $command = $this->commandManager->getCommandByIdentifier($this->task->getCommandIdentifier()); $argumentReflection = $this->reflectionService->getMethodParameters($command->getControllerClassName(), $command->getControllerCommandName() . 'Command'); $defaultValue = $argumentReflection[$argumentName]['defaultValue']; if ($type === 'boolean') { $defaultValue = (bool) $defaultValue ? 1 : 0; } return $defaultValue; }
/** * @test */ public function prepareArgumentsRegistersAnnotationBasedArgumentsWithDescriptionIfDebugModeIsEnabled() { $dataCacheMock = $this->getMock(\TYPO3\CMS\Core\Cache\Frontend\VariableFrontend::class, array(), array(), '', false); $dataCacheMock->expects($this->any())->method('has')->will($this->returnValue(true)); $dataCacheMock->expects($this->any())->method('get')->will($this->returnValue(array())); $viewHelper = new \TYPO3\CMS\Fluid\Tests\Unit\Core\Fixtures\TestViewHelper(); $this->mockReflectionService->expects($this->once())->method('getMethodParameters')->with(\TYPO3\CMS\Fluid\Tests\Unit\Core\Fixtures\TestViewHelper::class, 'render')->will($this->returnValue($this->fixtureMethodParameters)); $this->mockReflectionService->expects($this->once())->method('getMethodTagsValues')->with(\TYPO3\CMS\Fluid\Tests\Unit\Core\Fixtures\TestViewHelper::class, 'render')->will($this->returnValue($this->fixtureMethodTags)); $viewHelper->injectReflectionService($this->mockReflectionService); $expected = array('param1' => new \TYPO3\CMS\Fluid\Core\ViewHelper\ArgumentDefinition('param1', 'integer', 'P1 Stuff', true, null, true), 'param2' => new \TYPO3\CMS\Fluid\Core\ViewHelper\ArgumentDefinition('param2', 'array', 'P2 Stuff', true, null, true), 'param3' => new \TYPO3\CMS\Fluid\Core\ViewHelper\ArgumentDefinition('param3', 'string', 'P3 Stuff', false, 'default', true)); $this->assertEquals($expected, $viewHelper->prepareArguments(), 'Annotation based arguments were not registered.'); }
/** * @test * @expectedException \TYPO3\CMS\Extbase\Property\Exception\InvalidTargetException */ public function convertFromShouldThrowExceptionIfRequiredConstructorParameterWasNotFound() { $source = array('propertyX' => 'bar'); $object = new \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor('param1'); $convertedChildProperties = array('property2' => 'bar'); $this->mockReflectionService->expects($this->any())->method('getMethodParameters')->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, '__construct')->will($this->returnValue(array('property1' => array('optional' => false)))); $this->mockReflectionService->expects($this->any())->method('hasMethod')->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, '__construct')->will($this->returnValue(true)); $this->mockContainer->expects($this->any())->method('getImplementationClassName')->will($this->returnValue(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class)); $configuration = $this->buildConfiguration(array(PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => true)); $result = $this->converter->convertFrom($source, \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, $convertedChildProperties, $configuration); $this->assertSame($object, $result); }
/** * Returns the type of a child object. * * @param string $parentClassName The class name of the object this proxy is part of * @param string $propertyName The name of the proxied property in it's parent * @throws UnexpectedTypeException * @return string The class name of the child object */ public function getType($parentClassName, $propertyName) { $propertyMetaData = $this->reflectionService->getClassSchema($parentClassName)->getProperty($propertyName); if (!empty($propertyMetaData['elementType'])) { $type = $propertyMetaData['elementType']; } elseif (!empty($propertyMetaData['type'])) { $type = $propertyMetaData['type']; } else { throw new UnexpectedTypeException('Could not determine the child object type.', 1251315967); } return $type; }
/** * @test */ public function prepareArgumentsRegistersAnnotationBasedArgumentsWithoutDescriptionIfDebugModeIsDisabled() { \TYPO3\CMS\Fluid\Fluid::$debugMode = FALSE; $dataCacheMock = $this->getMock('TYPO3\\CMS\\Core\\Cache\\Frontend\\VariableFrontend', array(), array(), '', FALSE); $dataCacheMock->expects($this->any())->method('has')->will($this->returnValue(TRUE)); $dataCacheMock->expects($this->any())->method('get')->will($this->returnValue(array())); $viewHelper = new \TYPO3\CMS\Fluid\Tests\Unit\Core\Fixtures\TestViewHelper2(); $this->mockReflectionService->expects($this->once())->method('getMethodParameters')->with('TYPO3\\CMS\\Fluid\\Tests\\Unit\\Core\\Fixtures\\TestViewHelper2', 'render')->will($this->returnValue($this->fixtureMethodParameters)); $this->mockReflectionService->expects($this->never())->method('getMethodTagsValues'); $viewHelper->injectReflectionService($this->mockReflectionService); $expected = array('param1' => new \TYPO3\CMS\Fluid\Core\ViewHelper\ArgumentDefinition('param1', 'integer', '', TRUE, NULL, TRUE), 'param2' => new \TYPO3\CMS\Fluid\Core\ViewHelper\ArgumentDefinition('param2', 'array', '', TRUE, NULL, TRUE), 'param3' => new \TYPO3\CMS\Fluid\Core\ViewHelper\ArgumentDefinition('param3', 'string', '', FALSE, 'default', TRUE)); $this->assertEquals($expected, $viewHelper->prepareArguments(), 'Annotation based arguments were not registered.'); }
/** * @param $model * @return \stdClass */ public function transform($model) { if ($model instanceof \Traversable) { $out = array(); foreach ($model as $subModel) { $out[] = $this->transform($subModel); } return $out; } else { if ($model instanceof \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface) { $transformedObject = new \stdClass(); $properties = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getGettablePropertyNames($model); $class = get_class($model); foreach ($properties as $property) { $getMethodName = 'get' . ucfirst($property); $methodTags = $this->reflectionService->getMethodTagsValues($class, $getMethodName); // The Goal here is to be able to expose properties and methods with the JSONExpose annotation. if ($property == 'uid' || array_key_exists('JSONExpose', $methodTags) || $this->reflectionService->isPropertyTaggedWith($class, $property, 'JSONExpose')) { $value = $model->{$getMethodName}(); // TODO, not sure about this check for lazy loading. Would be good to write a test for it. if ($value instanceof \TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy) { $transformedObject->{$property} = 'lazy'; } elseif ($this->typeHandlingService->isSimpleType(gettype($value))) { $transformedObject->{$property} = $value; } elseif (is_object($value)) { if ($value instanceof \TYPO3\CMS\Extbase\Persistence\ObjectStorage) { $transformedObject->{$property} = $this->transform($value); } else { $transformedObject->{$property} = get_class($value); } } } } return $transformedObject; } else { return NULL; } } }
/** * @return void */ protected function initializeExtbaseFramework() { // initialize cache manager $this->cacheManager = $GLOBALS['typo3CacheManager']; // inject content object into the configuration manager $this->configurationManager = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Configuration\\ConfigurationManagerInterface'); $contentObject = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectRenderer'); $this->configurationManager->setContentObject($contentObject); $this->typoScriptService->makeTypoScriptBackup(); // load extbase typoscript TypoScriptService::loadTypoScriptFromFile('EXT:extbase/ext_typoscript_setup.txt'); TypoScriptService::loadTypoScriptFromFile('EXT:ap_ldap_auth/ext_typoscript_setup.txt'); $this->configurationManager->setConfiguration($GLOBALS['TSFE']->tmpl->setup); $this->configureObjectManager(); // initialize reflection $this->reflectionService = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Reflection\\ReflectionService'); $this->reflectionService->setDataCache($this->cacheManager->getCache('extbase_reflection')); if (!$this->reflectionService->isInitialized()) { $this->reflectionService->initialize(); } // initialize persistence $this->persistenceManager = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\PersistenceManager'); }
/** * Temporary replacement for $this->reflectionService->getMethodAnnotations() * * @param string $className * @param string $methodName * * @return array */ public function getMethodValidateAnnotations($className, $methodName) { $validateAnnotations = array(); $methodTagsValues = $this->reflectionService->getMethodTagsValues($className, $methodName); if (isset($methodTagsValues['validate']) && is_array($methodTagsValues['validate'])) { foreach ($methodTagsValues['validate'] as $validateValue) { $parsedAnnotations = $this->parseValidatorAnnotation($validateValue); foreach ($parsedAnnotations['validators'] as $validator) { array_push($validateAnnotations, array('argumentName' => $parsedAnnotations['argumentName'], 'validatorName' => $validator['validatorName'], 'validatorOptions' => $validator['validatorOptions'])); } } } return $validateAnnotations; }
/** * 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. * * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentTypeException * @return void */ protected function initializeCommandMethodArguments() { $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 \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentTypeException('The argument type for parameter $' . $parameterName . ' of method ' . get_class($this) . '->' . $this->commandMethodName . '() could not be detected.', 1306755296); } $defaultValue = isset($parameterInfo['defaultValue']) ? $parameterInfo['defaultValue'] : NULL; $this->arguments->addNewArgument($parameterName, $dataType, $parameterInfo['optional'] === FALSE, $defaultValue); } }
/** * 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. * * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentTypeException * @return void * @throws InvalidArgumentTypeException */ protected function initializeCommandMethodArguments() { $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); } }
/** * Calls the specified action method and passes the arguments. * * If the action returns a string, it is appended to the content in the * response object. If the action doesn't return anything and a valid * view exists, the view is rendered automatically. * * @return void * @api */ protected function callActionMethod() { $preparedArguments = array(); /** @var \TYPO3\CMS\Extbase\Mvc\Controller\Argument $argument */ foreach ($this->arguments as $argument) { $preparedArguments[] = $argument->getValue(); } $validationResult = $this->arguments->getValidationResults(); if (!$validationResult->hasErrors()) { $this->emitBeforeCallActionMethodSignal($preparedArguments); $actionResult = call_user_func_array(array($this, $this->actionMethodName), $preparedArguments); } else { $methodTagsValues = $this->reflectionService->getMethodTagsValues(get_class($this), $this->actionMethodName); $ignoreValidationAnnotations = array(); if (isset($methodTagsValues['ignorevalidation'])) { $ignoreValidationAnnotations = $methodTagsValues['ignorevalidation']; } // if there exist errors which are not ignored with @ignorevalidation => call error method // else => call action method $shouldCallActionMethod = true; foreach ($validationResult->getSubResults() as $argumentName => $subValidationResult) { if (!$subValidationResult->hasErrors()) { continue; } if (array_search('$' . $argumentName, $ignoreValidationAnnotations) !== false) { continue; } $shouldCallActionMethod = false; break; } if ($shouldCallActionMethod) { $this->emitBeforeCallActionMethodSignal($preparedArguments); $actionResult = call_user_func_array(array($this, $this->actionMethodName), $preparedArguments); } else { $actionResult = call_user_func(array($this, $this->errorMethodName)); } } if ($actionResult === null && $this->view instanceof ViewInterface) { $this->response->appendContent($this->view->render()); } elseif (is_string($actionResult) && $actionResult !== '') { $this->response->appendContent($actionResult); } elseif (is_object($actionResult) && method_exists($actionResult, '__toString')) { $this->response->appendContent((string) $actionResult); } }
/** * Returns an array of \TYPO3\CMS\Extbase\Mvc\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\CMS\Extbase\Mvc\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 = preg_split('/\\s+/', $annotations['param'][$i], 3); $description = !empty($explodedAnnotation[2]) ? $explodedAnnotation[2] : ''; $required = $commandParameterDefinition['optional'] !== TRUE; $commandArgumentDefinitions[] = $this->objectManager->get(\TYPO3\CMS\Extbase\Mvc\Cli\CommandArgumentDefinition::class, $commandParameterName, $required, $description); $i++; } return $commandArgumentDefinitions; }
/** * 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. * * @param string $commandMethodName * @return Arguments * @throws InvalidArgumentTypeException */ protected function getCommandMethodArguments($commandMethodName) { $arguments = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Mvc\\Controller\\Arguments'); $methodParameters = $this->reflectionService->getMethodParameters(self::INSTALL_COMMAND_CONTROLLER_CLASS, $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, self::INSTALL_COMMAND_CONTROLLER_CLASS, $commandMethodName), 1306755296); } $defaultValue = isset($parameterInfo['defaultValue']) ? $parameterInfo['defaultValue'] : NULL; $arguments->addNewArgument($parameterName, $dataType, $parameterInfo['optional'] === FALSE, $defaultValue); } return $arguments; }
/** * Remove related objects * * @param \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object The object to scanned for related objects * @return void */ protected function removeRelatedObjects(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface $object) { $className = get_class($object); $dataMap = $this->dataMapper->getDataMap($className); $classSchema = $this->reflectionService->getClassSchema($className); $properties = $object->_getProperties(); foreach ($properties as $propertyName => $propertyValue) { $columnMap = $dataMap->getColumnMap($propertyName); $propertyMetaData = $classSchema->getProperty($propertyName); if ($propertyMetaData['cascade'] === 'remove') { if ($columnMap->getTypeOfRelation() === \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_MANY) { foreach ($propertyValue as $containedObject) { $this->removeEntity($containedObject); } } elseif ($propertyValue instanceof \TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface) { $this->removeEntity($propertyValue); } } } }
/** * 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 * @author Robert Lemke <*****@*****.**> * @author Christopher Hlubek <*****@*****.**> */ public function getArguments() { if ($this->data === array()) { return array(); } $arguments = array(); if (!$this->request->isFormPost()) { $parameters = $this->reflectionService->getMethodParameters($this->getControllerObjectName(), $this->getControllerActionName() . '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; }
/** * 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\CMS\Extbase\Property\Exception\InvalidTargetException if a required constructor argument is missing */ protected function buildObject(array &$possibleConstructorArgumentValues, $objectType) { $specificObjectType = $this->objectContainer->getImplementationClassName($objectType); if ($this->reflectionService->hasMethod($specificObjectType, '__construct')) { $constructorSignature = $this->reflectionService->getMethodParameters($specificObjectType, '__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\CMS\Extbase\Property\Exception\InvalidTargetException('Missing constructor argument "' . $constructorArgumentName . '" for object of type "' . $objectType . '".', 1268734872); } } return call_user_func_array(array($this->objectManager, 'get'), array_merge(array($objectType), $constructorArguments)); } else { return $this->objectManager->get($objectType); } }
/** * Loads the model with the given identifier * * @param mixed $identifier The identifier * @param string $path The path * @return mixed|null|object */ protected function getModelWithIdentityForPath($identifier, $path) { $repository = $this->getRepositoryForPath($path); // Tries to fetch the object by UID $object = $repository->findByUid($identifier); if ($object) { return $object; } // Fetch the first identity property and search the repository for it $type = NULL; $property = NULL; try { $classSchema = $this->reflectionService->getClassSchema($this->getModelClassForPath($path)); $identityProperties = $classSchema->getIdentityProperties(); $type = reset($identityProperties); $property = key($identityProperties); } catch (\Exception $exception) { } switch ($type) { case 'string': $typeMatching = is_string($identifier); break; case 'boolean': $typeMatching = is_bool($identifier); break; case 'integer': $typeMatching = is_int($identifier); break; case 'float': $typeMatching = is_float($identifier); break; case 'array': default: $typeMatching = FALSE; } if ($typeMatching) { $findMethod = 'findOneBy' . ucfirst($property); return call_user_func(array($repository, $findMethod), $identifier); } return NULL; }
/** * Returns an array of \TYPO3\CMS\Extbase\Mvc\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\CMS\Extbase\Mvc\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 = ltrim(implode(' ', $explodedAnnotation)); $required = $commandParameterDefinition['optional'] !== TRUE; $commandArgumentDefinitions[] = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Mvc\\Cli\\CommandArgumentDefinition', $commandParameterName, $required, $description); $i++; } return $commandArgumentDefinitions; }