getClassSchema() public method

Returns the class schema for the given class
public getClassSchema ( mixed $classNameOrObject ) : ClassSchema
$classNameOrObject mixed The class name or an object
return ClassSchema
 /**
  * Generate a view with the given name for the given package and controller
  *
  * @param string $packageKey The package key of the controller's package
  * @param string $subpackage An optional subpackage name
  * @param string $controllerName The name of the new controller
  * @param string $viewName The name of the view
  * @param string $templateName The name of the view
  * @param boolean $overwrite Overwrite any existing files?
  * @return array An array of generated filenames
  */
 public function generateView($packageKey, $subpackage, $controllerName, $viewName, $templateName, $overwrite = false)
 {
     list($baseNamespace) = $this->getPrimaryNamespaceAndEntryPath($this->packageManager->getPackage($packageKey));
     $viewName = ucfirst($viewName);
     $templatePathAndFilename = 'resource://Neos.Kickstarter/Private/Generator/View/' . $templateName . 'Template.html';
     $contextVariables = array();
     $contextVariables['packageKey'] = $packageKey;
     $contextVariables['subpackage'] = $subpackage;
     $contextVariables['isInSubpackage'] = $subpackage != '';
     $contextVariables['controllerName'] = $controllerName;
     $contextVariables['viewName'] = $viewName;
     $contextVariables['modelName'] = strtolower($controllerName[0]) . substr($controllerName, 1);
     $contextVariables['repositoryClassName'] = '\\' . trim($baseNamespace, '\\') . ($subpackage != '' ? '\\' . $subpackage : '') . '\\Domain\\Repository\\' . $controllerName . 'Repository';
     $contextVariables['modelFullClassName'] = '\\' . trim($baseNamespace, '\\') . ($subpackage != '' ? '\\' . $subpackage : '') . '\\Domain\\Model\\' . $controllerName;
     $contextVariables['modelClassName'] = ucfirst($contextVariables['modelName']);
     $modelClassSchema = $this->reflectionService->getClassSchema($contextVariables['modelFullClassName']);
     if ($modelClassSchema !== null) {
         $contextVariables['properties'] = $modelClassSchema->getProperties();
         if (isset($contextVariables['properties']['Persistence_Object_Identifier'])) {
             unset($contextVariables['properties']['Persistence_Object_Identifier']);
         }
     }
     if (!isset($contextVariables['properties']) || $contextVariables['properties'] === array()) {
         $contextVariables['properties'] = array('name' => array('type' => 'string'));
     }
     $fileContent = $this->renderTemplate($templatePathAndFilename, $contextVariables);
     $subpackagePath = $subpackage != '' ? $subpackage . '/' : '';
     $viewFilename = $viewName . '.html';
     $viewPath = 'resource://' . $packageKey . '/Private/Templates/' . $subpackagePath . $controllerName . '/';
     $targetPathAndFilename = $viewPath . $viewFilename;
     $this->generateFile($targetPathAndFilename, $fileContent, $overwrite);
     return $this->generatedFiles;
 }
 /**
  * After returning advice, generates the value hash for the object
  *
  * @param JoinPointInterface $joinPoint The current join point
  * @return void
  * @Flow\After("Neos\Flow\Persistence\Aspect\PersistenceMagicAspect->isNonEmbeddedValueObject && method(.*->__construct()) && filter(Neos\Flow\Persistence\Doctrine\Mapping\Driver\FlowAnnotationDriver)")
  */
 public function generateValueHash(JoinPointInterface $joinPoint)
 {
     $proxy = $joinPoint->getProxy();
     $proxyClassName = get_class($proxy);
     $hashSourceParts = [];
     $classSchema = $this->reflectionService->getClassSchema($proxyClassName);
     foreach ($classSchema->getProperties() as $property => $propertySchema) {
         // Currently, private properties are transient. Should this behaviour change, they need to be included
         // in the value hash generation
         if ($classSchema->isPropertyTransient($property) || $this->reflectionService->isPropertyPrivate($proxyClassName, $property)) {
             continue;
         }
         $propertyValue = ObjectAccess::getProperty($proxy, $property, true);
         if (is_object($propertyValue) === true) {
             // The persistence manager will return NULL if the given object is unknown to persistence
             $propertyValue = $this->persistenceManager->getIdentifierByObject($propertyValue) ?: $propertyValue;
         }
         $hashSourceParts[$property] = $propertyValue;
     }
     ksort($hashSourceParts);
     $hashSourceParts['__class_name__'] = $proxyClassName;
     $serializedSource = $this->useIgBinary === true ? igbinary_serialize($hashSourceParts) : serialize($hashSourceParts);
     $proxy = $joinPoint->getProxy();
     ObjectAccess::setProperty($proxy, 'Persistence_Object_Identifier', sha1($serializedSource), true);
 }
Ejemplo n.º 3
0
 /**
  * Fetch a class schema for the given class, if possible.
  *
  * @param string $className
  * @return ClassSchema
  * @throws ClassSchemaNotFoundException
  */
 protected function getClassSchema($className)
 {
     $classSchema = $this->reflectionService->getClassSchema($className);
     if (!$classSchema) {
         throw new ClassSchemaNotFoundException('No class schema found for "' . $className . '".', 1295973082);
     }
     return $classSchema;
 }
 /**
  * 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);
 }
 /**
  * Builds methods for a single AOP proxy class for the specified class.
  *
  * @param string $targetClassName Name of the class to create a proxy class file for
  * @param array &$aspectContainers The array of aspect containers from the AOP Framework
  * @return boolean TRUE if the proxy class could be built, FALSE otherwise.
  */
 public function buildProxyClass($targetClassName, array &$aspectContainers)
 {
     $interfaceIntroductions = $this->getMatchingInterfaceIntroductions($aspectContainers, $targetClassName);
     $introducedInterfaces = $this->getInterfaceNamesFromIntroductions($interfaceIntroductions);
     $introducedTraits = $this->getMatchingTraitNamesFromIntroductions($aspectContainers, $targetClassName);
     $propertyIntroductions = $this->getMatchingPropertyIntroductions($aspectContainers, $targetClassName);
     $methodsFromTargetClass = $this->getMethodsFromTargetClass($targetClassName);
     $methodsFromIntroducedInterfaces = $this->getIntroducedMethodsFromInterfaceIntroductions($interfaceIntroductions, $targetClassName);
     $interceptedMethods = [];
     $this->addAdvicedMethodsToInterceptedMethods($interceptedMethods, array_merge($methodsFromTargetClass, $methodsFromIntroducedInterfaces), $targetClassName, $aspectContainers);
     $this->addIntroducedMethodsToInterceptedMethods($interceptedMethods, $methodsFromIntroducedInterfaces);
     if (count($interceptedMethods) < 1 && count($introducedInterfaces) < 1 && count($propertyIntroductions) < 1) {
         return false;
     }
     $proxyClass = $this->compiler->getProxyClass($targetClassName);
     if ($proxyClass === false) {
         return false;
     }
     $proxyClass->addInterfaces($introducedInterfaces);
     $proxyClass->addTraits($introducedTraits);
     /** @var $propertyIntroduction PropertyIntroduction */
     foreach ($propertyIntroductions as $propertyIntroduction) {
         $propertyName = $propertyIntroduction->getPropertyName();
         $declaringAspectClassName = $propertyIntroduction->getDeclaringAspectClassName();
         $possiblePropertyTypes = $this->reflectionService->getPropertyTagValues($declaringAspectClassName, $propertyName, 'var');
         if (count($possiblePropertyTypes) > 0 && !$this->reflectionService->isPropertyAnnotatedWith($declaringAspectClassName, $propertyName, Flow\Transient::class)) {
             $classSchema = $this->reflectionService->getClassSchema($targetClassName);
             if ($classSchema !== null) {
                 $classSchema->addProperty($propertyName, $possiblePropertyTypes[0]);
             }
         }
         $propertyReflection = new PropertyReflection($declaringAspectClassName, $propertyName);
         $propertyReflection->setIsAopIntroduced(true);
         $this->reflectionService->reflectClassProperty($targetClassName, $propertyReflection, new ClassReflection($declaringAspectClassName));
         $proxyClass->addProperty($propertyName, var_export($propertyIntroduction->getInitialValue(), true), $propertyIntroduction->getPropertyVisibility(), $propertyIntroduction->getPropertyDocComment());
     }
     $proxyClass->getMethod('Flow_Aop_Proxy_buildMethodsAndAdvicesArray')->addPreParentCallCode("        if (method_exists(get_parent_class(), 'Flow_Aop_Proxy_buildMethodsAndAdvicesArray') && is_callable('parent::Flow_Aop_Proxy_buildMethodsAndAdvicesArray')) parent::Flow_Aop_Proxy_buildMethodsAndAdvicesArray();\n");
     $proxyClass->getMethod('Flow_Aop_Proxy_buildMethodsAndAdvicesArray')->addPreParentCallCode($this->buildMethodsAndAdvicesArrayCode($interceptedMethods));
     $proxyClass->getMethod('Flow_Aop_Proxy_buildMethodsAndAdvicesArray')->overrideMethodVisibility('protected');
     $callBuildMethodsAndAdvicesArrayCode = "\n        \$this->Flow_Aop_Proxy_buildMethodsAndAdvicesArray();\n";
     $proxyClass->getConstructor()->addPreParentCallCode($callBuildMethodsAndAdvicesArrayCode);
     $proxyClass->getMethod('__wakeup')->addPreParentCallCode($callBuildMethodsAndAdvicesArrayCode);
     $proxyClass->getMethod('__clone')->addPreParentCallCode($callBuildMethodsAndAdvicesArrayCode);
     if (!$this->reflectionService->hasMethod($targetClassName, '__wakeup')) {
         $proxyClass->getMethod('__wakeup')->addPostParentCallCode("        if (method_exists(get_parent_class(), '__wakeup') && is_callable('parent::__wakeup')) parent::__wakeup();\n");
     }
     $proxyClass->addTraits(['\\' . AdvicesTrait::class]);
     $this->buildMethodsInterceptorCode($targetClassName, $interceptedMethods);
     $proxyClass->addProperty('Flow_Aop_Proxy_targetMethodsAndGroupedAdvices', 'array()');
     $proxyClass->addProperty('Flow_Aop_Proxy_groupedAdviceChains', 'array()');
     $proxyClass->addProperty('Flow_Aop_Proxy_methodIsInAdviceMode', 'array()');
     return true;
 }
 /**
  * If $this->uriPattern is specified, this will be returned, otherwise identity properties of $this->objectType
  * are returned in the format {property1}/{property2}/{property3}.
  * If $this->objectType does not contain identity properties, an empty string is returned.
  *
  * @return string
  */
 public function getUriPattern()
 {
     if ($this->uriPattern === null) {
         $classSchema = $this->reflectionService->getClassSchema($this->objectType);
         $identityProperties = $classSchema->getIdentityProperties();
         if (count($identityProperties) === 0) {
             $this->uriPattern = '';
         } else {
             $this->uriPattern = '{' . implode('}/{', array_keys($identityProperties)) . '}';
         }
     }
     return $this->uriPattern;
 }
 /**
  * An onFlush event listener used to validate entities upon persistence.
  *
  * @param \Doctrine\ORM\Event\OnFlushEventArgs $eventArgs
  * @return void
  */
 public function onFlush(\Doctrine\ORM\Event\OnFlushEventArgs $eventArgs)
 {
     $unitOfWork = $this->entityManager->getUnitOfWork();
     $entityInsertions = $unitOfWork->getScheduledEntityInsertions();
     $validatedInstancesContainer = new \SplObjectStorage();
     $knownValueObjects = [];
     foreach ($entityInsertions as $entity) {
         $className = TypeHandling::getTypeForValue($entity);
         if ($this->reflectionService->getClassSchema($className)->getModelType() === ClassSchema::MODELTYPE_VALUEOBJECT) {
             $identifier = $this->getIdentifierByObject($entity);
             if (isset($knownValueObjects[$className][$identifier]) || $unitOfWork->getEntityPersister($className)->exists($entity)) {
                 unset($entityInsertions[spl_object_hash($entity)]);
                 continue;
             }
             $knownValueObjects[$className][$identifier] = true;
         }
         $this->validateObject($entity, $validatedInstancesContainer);
     }
     ObjectAccess::setProperty($unitOfWork, 'entityInsertions', $entityInsertions, true);
     foreach ($unitOfWork->getScheduledEntityUpdates() as $entity) {
         $this->validateObject($entity, $validatedInstancesContainer);
     }
 }
 /**
  * Checks if the given value is a unique entity depending on it's identity properties or
  * custom configured identity properties.
  *
  * @param mixed $value The value that should be validated
  * @return void
  * @throws InvalidValidationOptionsException
  * @api
  */
 protected function isValid($value)
 {
     if (!is_object($value)) {
         throw new InvalidValidationOptionsException('The value supplied for the UniqueEntityValidator must be an object.', 1358454270);
     }
     $classSchema = $this->reflectionService->getClassSchema(TypeHandling::getTypeForValue($value));
     if ($classSchema === null || $classSchema->getModelType() !== ClassSchema::MODELTYPE_ENTITY) {
         throw new InvalidValidationOptionsException('The object supplied for the UniqueEntityValidator must be an entity.', 1358454284);
     }
     if ($this->options['identityProperties'] !== null) {
         $identityProperties = $this->options['identityProperties'];
         foreach ($identityProperties as $propertyName) {
             if ($classSchema->hasProperty($propertyName) === false) {
                 throw new InvalidValidationOptionsException(sprintf('The custom identity property name "%s" supplied for the UniqueEntityValidator does not exists in "%s".', $propertyName, $classSchema->getClassName()), 1358960500);
             }
         }
     } else {
         $identityProperties = array_keys($classSchema->getIdentityProperties());
     }
     if (count($identityProperties) === 0) {
         throw new InvalidValidationOptionsException('The object supplied for the UniqueEntityValidator must have at least one identity property.', 1358459831);
     }
     $identifierProperties = $this->reflectionService->getPropertyNamesByAnnotation($classSchema->getClassName(), 'Doctrine\\ORM\\Mapping\\Id');
     if (count($identifierProperties) > 1) {
         throw new InvalidValidationOptionsException('The object supplied for the UniqueEntityValidator must only have one identifier property @ORM\\Id.', 1358501745);
     }
     $identifierPropertyName = count($identifierProperties) > 0 ? array_shift($identifierProperties) : 'Persistence_Object_Identifier';
     $query = $this->persistenceManager->createQueryForType($classSchema->getClassName());
     $constraints = [$query->logicalNot($query->equals($identifierPropertyName, $this->persistenceManager->getIdentifierByObject($value)))];
     foreach ($identityProperties as $propertyName) {
         $constraints[] = $query->equals($propertyName, ObjectAccess::getProperty($value, $propertyName));
     }
     if ($query->matching($query->logicalAnd($constraints))->count() > 0) {
         $this->addError('Another entity with the same unique identifiers already exists', 1355785874);
     }
 }
 /**
  * Remove objects removed from SplObjectStorage compared to
  * $previousSplObjectStorage.
  *
  * @param \SplObjectStorage $splObjectStorage
  * @param array $previousObjectStorage
  * @return void
  */
 protected function removeDeletedSplObjectStorageEntries(\SplObjectStorage $splObjectStorage = null, array $previousObjectStorage)
 {
     // remove objects detached since reconstitution
     foreach ($previousObjectStorage as $item) {
         if ($splObjectStorage instanceof LazySplObjectStorage && !$this->persistenceSession->hasIdentifier($item['value']['identifier'])) {
             // ingore this identifier, assume it was blocked by security query rewriting upon activation
             continue;
         }
         $object = $this->persistenceSession->getObjectByIdentifier($item['value']['identifier']);
         if ($splObjectStorage === null || !$splObjectStorage->contains($object)) {
             if ($this->reflectionService->getClassSchema($object)->getModelType() === ClassSchema::MODELTYPE_ENTITY && $this->reflectionService->getClassSchema($object)->isAggregateRoot() === false) {
                 $this->removeEntity($object);
             } elseif ($this->reflectionService->getClassSchema($object)->getModelType() === ClassSchema::MODELTYPE_VALUEOBJECT) {
                 $this->removeValueObject($object);
             }
         }
     }
 }
Ejemplo n.º 10
0
 /**
  * Sets the given properties on the object.
  *
  * @param object $object The object to set properties on
  * @param string $identifier The identifier of the object
  * @param array $objectData
  * @return void
  * @throws UnknownObjectException
  */
 public function thawProperties($object, $identifier, array $objectData)
 {
     $classSchema = $this->reflectionService->getClassSchema($objectData['classname']);
     foreach ($objectData['properties'] as $propertyName => $propertyData) {
         if (!$classSchema->hasProperty($propertyName) || $classSchema->isPropertyTransient($propertyName)) {
             continue;
         }
         $propertyValue = null;
         if ($propertyData['value'] !== null) {
             switch ($propertyData['type']) {
                 case 'integer':
                     $propertyValue = (int) $propertyData['value'];
                     break;
                 case 'float':
                     $propertyValue = (double) $propertyData['value'];
                     break;
                 case 'boolean':
                     $propertyValue = (bool) $propertyData['value'];
                     break;
                 case 'string':
                     $propertyValue = (string) $propertyData['value'];
                     break;
                 case 'array':
                     $propertyValue = $this->mapArray($propertyData['value']);
                     break;
                 case 'Doctrine\\Common\\Collections\\Collection':
                 case 'Doctrine\\Common\\Collections\\ArrayCollection':
                     $propertyValue = new ArrayCollection($this->mapArray($propertyData['value']));
                     break;
                 case 'SplObjectStorage':
                     $propertyValue = $this->mapSplObjectStorage($propertyData['value'], $classSchema->isPropertyLazy($propertyName));
                     break;
                 case 'DateTime':
                     $propertyValue = $this->mapDateTime($propertyData['value']);
                     break;
                 default:
                     if ($propertyData['value'] === false) {
                         throw new UnknownObjectException('An expected object was not found by the backend. It was expected for ' . $objectData['classname'] . '::' . $propertyName, 1289509867);
                     }
                     $propertyValue = $this->mapToObject($propertyData['value']);
                     break;
             }
         } else {
             switch ($propertyData['type']) {
                 case 'NULL':
                     continue;
                 case 'array':
                     $propertyValue = $this->mapArray(null);
                     break;
                 case Collection::class:
                 case ArrayCollection::class:
                     $propertyValue = new ArrayCollection();
                     break;
                 case 'SplObjectStorage':
                     $propertyValue = $this->mapSplObjectStorage(null);
                     break;
             }
         }
         ObjectAccess::setProperty($object, $propertyName, $propertyValue, true);
     }
     if (isset($objectData['metadata'])) {
         $object->Flow_Persistence_Metadata = $objectData['metadata'];
     }
     ObjectAccess::setProperty($object, 'Persistence_Object_Identifier', $identifier, true);
 }
 /**
  * @test
  */
 public function domainModelPropertyTypesAreExpandedWithUseStatementsInClassSchema()
 {
     $classSchema = $this->reflectionService->getClassSchema(Reflection\Fixtures\Model\EntityWithUseStatements::class);
     $this->assertEquals(Reflection\Fixtures\Model\SubSubEntity::class, $classSchema->getProperty('subSubEntity')['type']);
     $this->assertEquals(Persistence\Fixtures\SubEntity::class, $classSchema->getProperty('propertyFromOtherNamespace')['type']);
 }
Ejemplo n.º 12
0
 /**
  * Constructs a query object working on the given type
  *
  * @param string $type
  * @param ReflectionService $reflectionService
  */
 public function __construct($type, ReflectionService $reflectionService)
 {
     $this->type = $type;
     $this->classSchema = $reflectionService->getClassSchema($type);
 }