/** * @param string $entityClassName * @param string $propertyName * @return array */ protected function getPropertyValidationSettings($entityClassName, $propertyName) { $options = array('required' => FALSE); $validationAnnotations = $this->reflectionService->getPropertyAnnotations($entityClassName, $propertyName, 'TYPO3\\Flow\\Annotations\\Validate'); foreach ($validationAnnotations as $validationAnnotation) { if ($validationAnnotation->type === 'NotEmpty') { $options['required'] = TRUE; } if ($validationAnnotation->type === 'StringLength') { $options['minimum'] = isset($validationAnnotation->options['minimum']) ? intval($validationAnnotation->options['minimum']) : 0; $options['maximum'] = isset($validationAnnotation->options['maximum']) ? intval($validationAnnotation->options['maximum']) : 0; } } return $options; }
/** * Returns TRUE if the property is a relation on the object * * @param string $objectName * @param string $propertyName * @return boolean */ protected function isRelation($objectName, $propertyName) { foreach ($this->reflectionService->getPropertyAnnotations($objectName, $propertyName) as $annotationName => $annotation) { if (strpos($annotationName, 'OneToOne') !== FALSE || strpos($annotationName, 'OneToMany') !== FALSE || strpos($annotationName, 'ManyToOne') !== FALSE || strpos($annotationName, 'ManyToMany') !== FALSE) { return TRUE; } } return FALSE; }
/** * 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 Neos\Foo\Domain\Model\Quux, then the validator will be found if it has the * name Neos\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 (!TypeHandling::isSimpleType($targetClassName) && class_exists($targetClassName)) { // Model based validator $classSchema = $this->reflectionService->getClassSchema($targetClassName); if ($classSchema !== null && $classSchema->isAggregateRoot()) { $objectValidator = new AggregateBoundaryValidator(array()); } else { $objectValidator = new GenericObjectValidator([]); } $conjunctionValidator->addValidator($objectValidator); foreach ($this->reflectionService->getClassPropertyNames($targetClassName) as $classPropertyName) { $classPropertyTagsValues = $this->reflectionService->getPropertyTagsValues($targetClassName, $classPropertyName); if (!isset($classPropertyTagsValues['var'])) { throw new \InvalidArgumentException(sprintf('There is no @var annotation for property "%s" in class "%s".', $classPropertyName, $targetClassName), 1363778104); } try { $parsedType = TypeHandling::parseType(trim(implode('', $classPropertyTagsValues['var']), ' \\')); } catch (InvalidTypeException $exception) { throw new \InvalidArgumentException(sprintf(' @var annotation of ' . $exception->getMessage(), 'class "' . $targetClassName . '", property "' . $classPropertyName . '"'), 1315564744, $exception); } if ($this->reflectionService->isPropertyAnnotatedWith($targetClassName, $classPropertyName, Flow\IgnoreValidation::class)) { continue; } $propertyTargetClassName = $parsedType['type']; if (TypeHandling::isCollectionType($propertyTargetClassName) === true) { $collectionValidator = $this->createValidator(Validator\CollectionValidator::class, ['elementType' => $parsedType['elementType'], 'validationGroups' => $validationGroups]); $objectValidator->addPropertyValidator($classPropertyName, $collectionValidator); } elseif (!TypeHandling::isSimpleType($propertyTargetClassName) && $this->objectManager->isRegistered($propertyTargetClassName) && $this->objectManager->getScope($propertyTargetClassName) === Configuration::SCOPE_PROTOTYPE) { $validatorForProperty = $this->getBaseValidatorConjunction($propertyTargetClassName, $validationGroups); if (count($validatorForProperty) > 0) { $objectValidator->addPropertyValidator($classPropertyName, $validatorForProperty); } } $validateAnnotations = $this->reflectionService->getPropertyAnnotations($targetClassName, $classPropertyName, Flow\Validate::class); 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 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->removeValidator($objectValidator); } } $this->addCustomValidators($targetClassName, $conjunctionValidator); }
/** * Initialize needed annotations for entity if needed * * @param string $className */ protected function initializeAnnotationsForEntity($className) { if (!isset(self::$storedProperties[$className]['annotations'])) { self::$storedProperties[$className]['annotations'] = array(); $propertyNames = $this->reflectionService->getClassPropertyNames($className); foreach ($propertyNames as $propertyName) { $annotations = $this->reflectionService->getPropertyAnnotations($className, $propertyName, Traceable::class); foreach ($annotations as $annotation) { self::$storedProperties[$className]['annotations'][$propertyName][] = $annotation; } } } }