public function get($being) { $c = array(); if (isset($this->settings["Defaults"])) { $classRaw = $this->settings["Defaults"]; $propertyRaw = $classRaw["properties"]; unset($classRaw["properties"]); $c = $this->convert($classRaw); if (class_exists($being, false)) { $propertyDefaults = $this->convert($propertyRaw); $schema = $this->reflectionService->getClassSchema($being); if (is_object($schema)) { $properties = $schema->getProperties(); } else { $properties = array_flip($this->reflectionService->getClassPropertyNames($being)); } foreach ($properties as $property => $meta) { if ($property == "FLOW3_Persistence_Identifier") { continue; } $c["properties"][$property] = $propertyDefaults; } } } return $c; }
public function get($class) { $c = array(); if (class_exists($class)) { $c = array(); // Loac Class Annotations foreach ($this->reflectionService->getClassAnnotations($class) as $key => $object) { $shortName = $this->convertAnnotationName(get_class($object)); if (!isset($c[$shortName])) { $c[$shortName] = array(); } $c[$shortName][] = $object; } $schema = $this->reflectionService->getClassSchema($class); if (is_object($schema)) { if (!isset($c["repository"])) { $c["repository"] = array(new \Admin\Annotations\Repository(array("class" => $schema->getRepositoryClassName()))); } $properties = $schema->getProperties(); } else { $properties = array_flip($this->reflectionService->getClassPropertyNames($class)); } foreach ($properties as $property => $meta) { if ($property == "FLOW3_Persistence_Identifier") { continue; } $c["properties"][$property] = array(); // Load legacy Annotations like @var,... foreach ($this->reflectionService->getPropertyTagsValues($class, $property) as $shortName => $tags) { if (!isset($c["properties"][$property])) { $c["properties"][$property] = array(); } $c["properties"][$property][$shortName] = $tags; } // $c["properties"][$property]["type"] = array( // new \Admin\Annotations\Type(array( // "name" => $meta["type"], // "subtype" => $meta["elementType"], // )) // ); // Load Annotations and override legacy Annotations $annotations = $this->reflectionService->getPropertyAnnotations($class, $property); foreach ($annotations as $key => $objects) { $shortName = $this->convertAnnotationName($key); if (!isset($c["properties"][$property])) { $c["properties"][$property] = array(); } $c["properties"][$property][$shortName] = $objects; } } } return $c; }
/** * Serializes an object as property array. * * @param object $object The object to store in the registry * @param boolean $isTopLevelItem Internal flag for managing the recursion * @return array The property array */ public function serializeObjectAsPropertyArray($object, $isTopLevelItem = TRUE) { if ($isTopLevelItem) { $this->objectReferences = new \SplObjectStorage(); } $this->objectReferences->attach($object); $className = get_class($object); $propertyArray = array(); foreach ($this->reflectionService->getClassPropertyNames($className) as $propertyName) { if ($this->reflectionService->isPropertyTaggedWith($className, $propertyName, 'transient')) { continue; } $propertyReflection = new \TYPO3\FLOW3\Reflection\PropertyReflection($className, $propertyName); $propertyValue = $propertyReflection->getValue($object); if (is_object($propertyValue) && isset($this->objectReferences[$propertyValue])) { $propertyArray[$propertyName][self::TYPE] = 'object'; $propertyArray[$propertyName][self::VALUE] = \spl_object_hash($propertyValue); continue; } $propertyClassName = is_object($propertyValue) ? get_class($propertyValue) : ''; if ($propertyClassName === 'SplObjectStorage') { $propertyArray[$propertyName][self::TYPE] = 'SplObjectStorage'; $propertyArray[$propertyName][self::VALUE] = array(); foreach ($propertyValue as $storedObject) { $propertyArray[$propertyName][self::VALUE][] = spl_object_hash($storedObject); $this->serializeObjectAsPropertyArray($storedObject, FALSE); } } elseif (is_object($propertyValue) && $propertyValue instanceof \Doctrine\Common\Collections\Collection) { $propertyArray[$propertyName][self::TYPE] = 'Collection'; $propertyArray[$propertyName][self::CLASSNAME] = get_class($propertyValue); $propertyArray[$propertyName][self::VALUE] = $this->buildStorageArrayForArrayProperty($propertyValue->toArray()); } elseif (is_object($propertyValue) && $propertyValue instanceof \ArrayObject) { $propertyArray[$propertyName][self::TYPE] = 'ArrayObject'; $propertyArray[$propertyName][self::VALUE] = $this->buildStorageArrayForArrayProperty($propertyValue->getArrayCopy()); } elseif (is_object($propertyValue) && $this->persistenceManager->isNewObject($propertyValue) === FALSE && ($this->reflectionService->isClassAnnotatedWith($propertyClassName, 'TYPO3\\FLOW3\\Annotations\\Entity') || $this->reflectionService->isClassAnnotatedWith($propertyClassName, 'TYPO3\\FLOW3\\Annotations\\ValueObject') || $this->reflectionService->isClassAnnotatedWith($propertyClassName, 'Doctrine\\ORM\\Mapping\\Entity'))) { $propertyArray[$propertyName][self::TYPE] = 'persistenceObject'; $propertyArray[$propertyName][self::VALUE] = get_class($propertyValue) . ':' . $this->persistenceManager->getIdentifierByObject($propertyValue); } elseif (is_object($propertyValue)) { $propertyObjectName = $this->objectManager->getObjectNameByClassName($propertyClassName); if ($propertyObjectName != '' && $this->objectManager->getScope($propertyObjectName) === \TYPO3\FLOW3\Object\Configuration\Configuration::SCOPE_SINGLETON) { continue; } $propertyArray[$propertyName][self::TYPE] = 'object'; $propertyArray[$propertyName][self::VALUE] = spl_object_hash($propertyValue); $this->serializeObjectAsPropertyArray($propertyValue, FALSE); } elseif (is_array($propertyValue)) { $propertyArray[$propertyName][self::TYPE] = 'array'; $propertyArray[$propertyName][self::VALUE] = $this->buildStorageArrayForArrayProperty($propertyValue); } else { $propertyArray[$propertyName][self::TYPE] = 'simple'; $propertyArray[$propertyName][self::VALUE] = $propertyValue; } } $this->objectsAsArray[spl_object_hash($object)] = array(self::CLASSNAME => $className, self::PROPERTIES => $propertyArray); if ($isTopLevelItem) { return $this->objectsAsArray; } }
/** * Returns all Properties of a Specified Model * * @param $model String Name of the Model * @return $properties Array of Model Properties * @author Marc Neuhaus <*****@*****.**> **/ public function getModelProperties($model) { $tmpProperties = $this->reflectionService->getClassPropertyNames($model); foreach ($tmpProperties as $property) { $properties[$property] = $this->reflectionService->getPropertyTagsValues($model, $property); if (!in_array("var", array_keys($properties[$property]))) { continue; } $properties[$property]["identity"] = in_array("identity", array_keys($properties[$property])) ? "true" : "false"; } unset($tmpProperties); return $properties; }
public function getProperties($source) { if ($source instanceof \Doctrine\ORM\Proxy\Proxy) { $class = get_parent_class($source); } else { $class = get_class($source); } $schema = $this->reflectionService->getClassSchema($class); if (is_object($schema)) { $properties = $schema->getProperties(); } else { $properties = array_flip($this->reflectionService->getClassPropertyNames($class)); } return $properties; }
/** * Builds a base validator conjunction for the given data type. * * The base validation rules are those which were declared directly in a class (typically * a model) through some validate annotations on properties. * * If a property holds a class for which a base validator exists, that property will be * checked as well, regardless of a validate annotation * * Additionally, if a custom validator was defined for the class in question, it will be added * to the end of the conjunction. A custom validator is found if it follows the naming convention * "Replace '\Model\' by '\Validator\' and append 'Validator'". * * Example: $targetClassName is TYPO3\Foo\Domain\Model\Quux, then the validator will be found if it has the * name TYPO3\Foo\Domain\Validator\QuuxValidator * * @param string $indexKey The key to use as index in $this->baseValidatorConjunctions; calculated from target class name and validation groups * @param string $targetClassName The data type to build the validation conjunction for. Needs to be the fully qualified class name. * @param array $validationGroups The validation groups to build the validator for * @return void * @throws Exception\NoSuchValidatorException * @throws \InvalidArgumentException */ protected function buildBaseValidatorConjunction($indexKey, $targetClassName, array $validationGroups) { $conjunctionValidator = new ConjunctionValidator(); $this->baseValidatorConjunctions[$indexKey] = $conjunctionValidator; if (class_exists($targetClassName)) { // Model based validator $objectValidator = new GenericObjectValidator(array()); foreach ($this->reflectionService->getClassPropertyNames($targetClassName) as $classPropertyName) { $classPropertyTagsValues = $this->reflectionService->getPropertyTagsValues($targetClassName, $classPropertyName); try { $parsedType = \TYPO3\FLOW3\Utility\TypeHandling::parseType(trim(implode('', $classPropertyTagsValues['var']), ' \\')); } catch (\TYPO3\FLOW3\Utility\Exception\InvalidTypeException $exception) { throw new \InvalidArgumentException(sprintf(' @var annotation of ' . $exception->getMessage(), 'class "' . $targetClassName . '", property "' . $classPropertyName . '"'), 1315564744); } $propertyTargetClassName = $parsedType['type']; if (\TYPO3\FLOW3\Utility\TypeHandling::isCollectionType($propertyTargetClassName) === TRUE) { $collectionValidator = $this->createValidator('TYPO3\\FLOW3\\Validation\\Validator\\CollectionValidator', array('elementType' => $parsedType['elementType'], 'validationGroups' => $validationGroups)); $objectValidator->addPropertyValidator($classPropertyName, $collectionValidator); } elseif (class_exists($propertyTargetClassName) && $this->objectManager->isRegistered($propertyTargetClassName) && $this->objectManager->getScope($propertyTargetClassName) === \TYPO3\FLOW3\Object\Configuration\Configuration::SCOPE_PROTOTYPE) { $validatorForProperty = $this->getBaseValidatorConjunction($propertyTargetClassName, $validationGroups); if (count($validatorForProperty) > 0) { $objectValidator->addPropertyValidator($classPropertyName, $validatorForProperty); } } $validateAnnotations = $this->reflectionService->getPropertyAnnotations($targetClassName, $classPropertyName, 'TYPO3\\FLOW3\\Annotations\\Validate'); foreach ($validateAnnotations as $validateAnnotation) { if (count(array_intersect($validateAnnotation->validationGroups, $validationGroups)) === 0) { // In this case, the validation groups for the property do not match current validation context continue; } $newValidator = $this->createValidator($validateAnnotation->type, $validateAnnotation->options); if ($newValidator === NULL) { throw new \TYPO3\FLOW3\Validation\Exception\NoSuchValidatorException('Invalid validate annotation in ' . $targetClassName . '::' . $classPropertyName . ': Could not resolve class name for validator "' . $validateAnnotation->type . '".', 1241098027); } $objectValidator->addPropertyValidator($classPropertyName, $newValidator); } } if (count($objectValidator->getPropertyValidators()) > 0) { $conjunctionValidator->addValidator($objectValidator); } // Custom validator for the class $possibleValidatorClassName = str_replace('\\Model\\', '\\Validator\\', $targetClassName) . 'Validator'; $customValidator = $this->createValidator($possibleValidatorClassName); if ($customValidator !== NULL) { $conjunctionValidator->addValidator($customValidator); } } }
/** * Creates and returns an aspect from the annotations found in a class which * is tagged as an aspect. The object acting as an advice will already be * fetched (and therefore instantiated if necessary). * * @param string $aspectClassName Name of the class which forms the aspect, contains advices etc. * @return mixed The aspect container containing one or more advisors or FALSE if no container could be built * @throws \TYPO3\FLOW3\Aop\Exception */ protected function buildAspectContainer($aspectClassName) { $aspectContainer = new \TYPO3\FLOW3\Aop\AspectContainer($aspectClassName); $methodNames = get_class_methods($aspectClassName); foreach ($methodNames as $methodName) { foreach ($this->reflectionService->getMethodAnnotations($aspectClassName, $methodName) as $annotation) { $annotationClass = get_class($annotation); switch ($annotationClass) { case 'TYPO3\\FLOW3\\Annotations\\Around': $pointcutFilterComposite = $this->pointcutExpressionParser->parse($annotation->pointcutExpression, $this->renderSourceHint($aspectClassName, $methodName, $annotationClass)); $advice = new \TYPO3\FLOW3\Aop\Advice\AroundAdvice($aspectClassName, $methodName); $pointcut = new \TYPO3\FLOW3\Aop\Pointcut\Pointcut($annotation->pointcutExpression, $pointcutFilterComposite, $aspectClassName); $advisor = new \TYPO3\FLOW3\Aop\Advisor($advice, $pointcut); $aspectContainer->addAdvisor($advisor); break; case 'TYPO3\\FLOW3\\Annotations\\Before': $pointcutFilterComposite = $this->pointcutExpressionParser->parse($annotation->pointcutExpression, $this->renderSourceHint($aspectClassName, $methodName, $annotationClass)); $advice = new \TYPO3\FLOW3\Aop\Advice\BeforeAdvice($aspectClassName, $methodName); $pointcut = new \TYPO3\FLOW3\Aop\Pointcut\Pointcut($annotation->pointcutExpression, $pointcutFilterComposite, $aspectClassName); $advisor = new \TYPO3\FLOW3\Aop\Advisor($advice, $pointcut); $aspectContainer->addAdvisor($advisor); break; case 'TYPO3\\FLOW3\\Annotations\\AfterReturning': $pointcutFilterComposite = $this->pointcutExpressionParser->parse($annotation->pointcutExpression, $this->renderSourceHint($aspectClassName, $methodName, $annotationClass)); $advice = new \TYPO3\FLOW3\Aop\Advice\AfterReturningAdvice($aspectClassName, $methodName); $pointcut = new \TYPO3\FLOW3\Aop\Pointcut\Pointcut($annotation->pointcutExpression, $pointcutFilterComposite, $aspectClassName); $advisor = new \TYPO3\FLOW3\Aop\Advisor($advice, $pointcut); $aspectContainer->addAdvisor($advisor); break; case 'TYPO3\\FLOW3\\Annotations\\AfterThrowing': $pointcutFilterComposite = $this->pointcutExpressionParser->parse($annotation->pointcutExpression, $this->renderSourceHint($aspectClassName, $methodName, $annotationClass)); $advice = new \TYPO3\FLOW3\Aop\Advice\AfterThrowingAdvice($aspectClassName, $methodName); $pointcut = new \TYPO3\FLOW3\Aop\Pointcut\Pointcut($annotation->pointcutExpression, $pointcutFilterComposite, $aspectClassName); $advisor = new \TYPO3\FLOW3\Aop\Advisor($advice, $pointcut); $aspectContainer->addAdvisor($advisor); break; case 'TYPO3\\FLOW3\\Annotations\\After': $pointcutFilterComposite = $this->pointcutExpressionParser->parse($annotation->pointcutExpression, $this->renderSourceHint($aspectClassName, $methodName, $annotationClass)); $advice = new \TYPO3\FLOW3\Aop\Advice\AfterAdvice($aspectClassName, $methodName); $pointcut = new \TYPO3\FLOW3\Aop\Pointcut\Pointcut($annotation->pointcutExpression, $pointcutFilterComposite, $aspectClassName); $advisor = new \TYPO3\FLOW3\Aop\Advisor($advice, $pointcut); $aspectContainer->addAdvisor($advisor); break; case 'TYPO3\\FLOW3\\Annotations\\Pointcut': $pointcutFilterComposite = $this->pointcutExpressionParser->parse($annotation->expression, $this->renderSourceHint($aspectClassName, $methodName, $annotationClass)); $pointcut = new \TYPO3\FLOW3\Aop\Pointcut\Pointcut($annotation->expression, $pointcutFilterComposite, $aspectClassName, $methodName); $aspectContainer->addPointcut($pointcut); break; } } } $introduceAnnotation = $this->reflectionService->getClassAnnotation($aspectClassName, 'TYPO3\\FLOW3\\Annotations\\Introduce'); if ($introduceAnnotation !== NULL) { if ($introduceAnnotation->interfaceName === NULL) { throw new \TYPO3\FLOW3\Aop\Exception('The interface introduction in class "' . $aspectClassName . '" does not contain the required interface name).', 1172694761); } $pointcutFilterComposite = $this->pointcutExpressionParser->parse($introduceAnnotation->pointcutExpression, $this->renderSourceHint($aspectClassName, $methodName, 'TYPO3\\FLOW3\\Annotations\\Introduce')); $pointcut = new \TYPO3\FLOW3\Aop\Pointcut\Pointcut($introduceAnnotation->pointcutExpression, $pointcutFilterComposite, $aspectClassName); $introduction = new \TYPO3\FLOW3\Aop\InterfaceIntroduction($aspectClassName, $introduceAnnotation->interfaceName, $pointcut); $aspectContainer->addInterfaceIntroduction($introduction); } foreach ($this->reflectionService->getClassPropertyNames($aspectClassName) as $propertyName) { $introduceAnnotation = $this->reflectionService->getPropertyAnnotation($aspectClassName, $propertyName, 'TYPO3\\FLOW3\\Annotations\\Introduce'); if ($introduceAnnotation !== NULL) { $pointcutFilterComposite = $this->pointcutExpressionParser->parse($introduceAnnotation->pointcutExpression, $this->renderSourceHint($aspectClassName, $propertyName, 'TYPO3\\FLOW3\\Annotations\\Introduce')); $pointcut = new \TYPO3\FLOW3\Aop\Pointcut\Pointcut($introduceAnnotation->pointcutExpression, $pointcutFilterComposite, $aspectClassName); $introduction = new \TYPO3\FLOW3\Aop\PropertyIntroduction($aspectClassName, $propertyName, $pointcut); $aspectContainer->addPropertyIntroduction($introduction); } } if (count($aspectContainer->getAdvisors()) < 1 && count($aspectContainer->getPointcuts()) < 1 && count($aspectContainer->getInterfaceIntroductions()) < 1) { throw new \TYPO3\FLOW3\Aop\Exception('The class "' . $aspectClassName . '" is tagged to be an aspect but doesn\'t contain advices nor pointcut or introduction declarations.', 1169124534); } return $aspectContainer; }