/**
  * Recursively parse constraints.
  *
  * @param  $className
  * @param  array $visited
  * @return array
  */
 protected function doParse($className, array $visited)
 {
     $params = array();
     $classdata = $this->factory->getMetadataFor($className);
     $properties = $classdata->getConstrainedProperties();
     $refl = $classdata->getReflectionClass();
     $defaults = $refl->getDefaultProperties();
     foreach ($properties as $property) {
         $vparams = array();
         $vparams['default'] = isset($defaults[$property]) ? $defaults[$property] : null;
         $pds = $classdata->getPropertyMetadata($property);
         foreach ($pds as $propdata) {
             $constraints = $propdata->getConstraints();
             foreach ($constraints as $constraint) {
                 $vparams = $this->parseConstraint($constraint, $vparams, $className, $visited);
             }
         }
         if (isset($vparams['format'])) {
             $vparams['format'] = join(', ', $vparams['format']);
         }
         foreach (array('dataType', 'readonly', 'required', 'subType') as $reqprop) {
             if (!isset($vparams[$reqprop])) {
                 $vparams[$reqprop] = null;
             }
         }
         // check for nested classes with All constraint
         if (isset($vparams['class']) && !in_array($vparams['class'], $visited) && null !== $this->factory->getMetadataFor($vparams['class'])) {
             $visited[] = $vparams['class'];
             $vparams['children'] = $this->doParse($vparams['class'], $visited);
         }
         $vparams['actualType'] = isset($vparams['actualType']) ? $vparams['actualType'] : DataTypes::STRING;
         $params[$property] = $vparams;
     }
     return $params;
 }
 /**
  * Gets ClassMetadata of desired class with annotations and others (xml, yml, php) using metadata factory
  *
  * @param string $className
  *
  * @return ClassMetadata Returns ClassMetadata object of desired entity with annotations info
  */
 public function getClassMetadata($className)
 {
     if (!isset($this->classesMetadata[$className])) {
         $this->classesMetadata[$className] = $this->metadataFactory->getMetadataFor($className);
     }
     return $this->classesMetadata[$className];
 }
    /**
     * {@inheritDoc}
     *
     * @throws ValidatorException If the metadata for the value does not support properties.
     */
    public function validatePropertyValue($containingValue, $property, $value, $groups = null)
    {
        $visitor = $this->createVisitor($containingValue);
        $metadata = $this->metadataFactory->getMetadataFor($containingValue);

        if (!$metadata instanceof PropertyMetadataContainerInterface) {
            $valueAsString = is_scalar($containingValue)
                ? '"' . $containingValue . '"'
                : 'the value of type ' . gettype($containingValue);

            throw new ValidatorException(sprintf('The metadata for ' . $valueAsString . ' does not support properties.'));
        }

        foreach ($this->resolveGroups($groups) as $group) {
            if (!$metadata->hasPropertyMetadata($property)) {
                continue;
            }

            foreach ($metadata->getPropertyMetadata($property) as $propMeta) {
                $propMeta->accept($visitor, $value, $group, $property);
            }
        }

        return $visitor->getViolations();
    }
 /**
  * @param Node $node
  * @return void
  */
 public function enterNode(Node $node)
 {
     if ($node instanceof Node\Stmt\Namespace_) {
         if (isset($node->name)) {
             $this->namespace = implode('\\', $node->name->parts);
         }
         return;
     }
     if (!$node instanceof Node\Stmt\Class_) {
         return;
     }
     $name = '' === $this->namespace ? $node->name : $this->namespace . '\\' . $node->name;
     if (!class_exists($name)) {
         return;
     }
     $metadata = $this->metadataFactory instanceof ClassMetadataFactoryInterface ? $this->metadataFactory->getClassMetadata($name) : $this->metadataFactory->getMetadataFor($name);
     if (!$metadata->hasConstraints() && !count($metadata->getConstrainedProperties())) {
         return;
     }
     $this->extractFromConstraints($metadata->constraints);
     foreach ($metadata->members as $members) {
         foreach ($members as $member) {
             $this->extractFromConstraints($member->constraints);
         }
     }
 }
 /**
  * Extracts constraints based on validation metadata
  *
  * @param FormInterface $form
  * @return array
  */
 protected function extractMetadataPropertiesConstraints(FormInterface $form)
 {
     $constraints = [];
     if ($form->getConfig()->getDataClass()) {
         /** @var ClassMetadata $metadata */
         $metadata = $this->metadataFactory->getMetadataFor($form->getConfig()->getDataClass());
         $constraints = $metadata->properties;
     }
     $errorMapping = $form->getConfig()->getOption('error_mapping');
     if (!empty($constraints) && !empty($errorMapping)) {
         foreach ($errorMapping as $originalName => $mappedName) {
             if (isset($constraints[$originalName])) {
                 $constraints[$mappedName] = $constraints[$originalName];
             }
         }
     }
     return $constraints;
 }
    /**
     * {@inheritdoc}
     */
    public function validate($value, $group, $propertyPath, $traverse = false, $deep = false)
    {
        if (null === $value) {
            return;
        }

        if (is_object($value)) {
            $hash = spl_object_hash($value);

            // Exit, if the object is already validated for the current group
            if (isset($this->validatedObjects[$hash][$group])) {
                return;
            }

            // Initialize if the object wasn't initialized before
            if (!isset($this->validatedObjects[$hash])) {
                foreach ($this->objectInitializers as $initializer) {
                    if (!$initializer instanceof ObjectInitializerInterface) {
                        throw new \LogicException('Validator initializers must implement ObjectInitializerInterface.');
                    }
                    $initializer->initialize($value);
                }
            }

            // Remember validating this object before starting and possibly
            // traversing the object graph
            $this->validatedObjects[$hash][$group] = true;
        }

        // Validate arrays recursively by default, otherwise every driver needs
        // to implement special handling for arrays.
        // https://github.com/symfony/symfony/issues/6246
        if (is_array($value) || ($traverse && $value instanceof \Traversable)) {
            foreach ($value as $key => $element) {
                // Ignore any scalar values in the collection
                if (is_object($element) || is_array($element)) {
                    // Only repeat the traversal if $deep is set
                    $this->validate($element, $group, $propertyPath.'['.$key.']', $deep, $deep);
                }
            }

            try {
                $this->metadataFactory->getMetadataFor($value)->accept($this, $value, $group, $propertyPath);
            } catch (NoSuchMetadataException $e) {
                // Metadata doesn't necessarily have to exist for
                // traversable objects, because we know how to validate
                // them anyway. Optionally, additional metadata is supported.
            }
        } else {
            $this->metadataFactory->getMetadataFor($value)->accept($this, $value, $group, $propertyPath);
        }
    }
Example #7
0
 /**
  * Validates a value against a constraint.
  *
  * @param Constraint $constraint
  * @param            $value
  * @param            $group
  * @param            $propertyPath
  * @param null       $currentClass
  * @param null       $currentProperty
  *
  * @deprecated Deprecated since version 2.2, to be removed in 2.3.
  */
 public function walkConstraint(Constraint $constraint, $value, $group, $propertyPath, $currentClass = null, $currentProperty = null)
 {
     $metadata = null;
     // BC code to make getCurrentClass() and getCurrentProperty() work when
     // called from within this method
     if (null !== $currentClass) {
         $metadata = $this->metadataFactory->getMetadataFor($currentClass);
         if (null !== $currentProperty && $metadata instanceof PropertyMetadataContainerInterface) {
             $metadata = current($metadata->getPropertyMetadata($currentProperty));
         }
     }
     $context = new ExecutionContext($this->visitor, $metadata, $value, $group, $propertyPath);
     $context->validateValue($value, $constraint);
 }
 /**
  * Validates a value against a constraint.
  *
  * @param Constraint $constraint
  * @param            $value
  * @param            $group
  * @param            $propertyPath
  * @param null       $currentClass
  * @param null       $currentProperty
  *
  * @deprecated Deprecated since version 2.2, to be removed in 2.3.
  */
 public function walkConstraint(Constraint $constraint, $value, $group, $propertyPath, $currentClass = null, $currentProperty = null)
 {
     trigger_error('walkConstraint() is deprecated since version 2.2 and will be removed in 2.3.', E_USER_DEPRECATED);
     $metadata = null;
     // BC code to make getCurrentClass() and getCurrentProperty() work when
     // called from within this method
     if (null !== $currentClass) {
         $metadata = $this->metadataFactory->getMetadataFor($currentClass);
         if (null !== $currentProperty && $metadata instanceof PropertyMetadataContainerInterface) {
             $metadata = current($metadata->getPropertyMetadata($currentProperty));
         }
     }
     $context = new ExecutionContext($this->visitor, $this->translator, $this->translationDomain, $metadata, $value, $group, $propertyPath);
     $context->validateValue($value, $constraint);
 }
 /**
  * Validates an object against the constraints defined for its class.
  *
  * If no metadata is available for the class, but the class is an instance
  * of {@link \Traversable} and the selected traversal strategy allows
  * traversal, the object will be iterated and each nested object will be
  * validated instead.
  *
  * @param object    $object            The object to cascade
  * @param string    $propertyPath      The current property path
  * @param string[]  $groups            The validated groups
  * @param int       $traversalStrategy The strategy for traversing the
  *                                     cascaded object
  * @param ExecutionContextInterface $context The current execution context
  *
  * @throws NoSuchMetadataException If the object has no associated metadata
  *                                 and does not implement {@link \Traversable}
  *                                 or if traversal is disabled via the
  *                                 $traversalStrategy argument
  * @throws UnsupportedMetadataException If the metadata returned by the
  *                                      metadata factory does not implement
  *                                      {@link ClassMetadataInterface}
  */
 private function validateObject($object, $propertyPath, array $groups, $traversalStrategy, ExecutionContextInterface $context)
 {
     try {
         $classMetadata = $this->metadataFactory->getMetadataFor($object);
         if (!$classMetadata instanceof ClassMetadataInterface) {
             throw new UnsupportedMetadataException(sprintf('The metadata factory should return instances of ' . '"Symfony\\Component\\Validator\\Mapping\\ClassMetadataInterface", ' . 'got: "%s".', is_object($classMetadata) ? get_class($classMetadata) : gettype($classMetadata)));
         }
         $this->validateClassNode($object, spl_object_hash($object), $classMetadata, $propertyPath, $groups, null, $traversalStrategy, $context);
     } catch (NoSuchMetadataException $e) {
         // Rethrow if not Traversable
         if (!$object instanceof \Traversable) {
             throw $e;
         }
         // Rethrow unless IMPLICIT or TRAVERSE
         if (!($traversalStrategy & (TraversalStrategy::IMPLICIT | TraversalStrategy::TRAVERSE))) {
             throw $e;
         }
         $this->validateEachObjectIn($object, $propertyPath, $groups, $traversalStrategy & TraversalStrategy::STOP_RECURSION, $context);
     }
 }
 /**
  * {@inheritdoc}
  *
  * @throws ValidatorException If the metadata for the value does not support properties.
  */
 public function validatePropertyValue($containingValue, $property, $value, $groups = null)
 {
     $visitor = $this->createVisitor(is_object($containingValue) ? $containingValue : $value);
     $metadata = $this->metadataFactory->getMetadataFor($containingValue);
     if (!$metadata instanceof PropertyMetadataContainerInterface) {
         $valueAsString = is_scalar($containingValue) ? '"' . $containingValue . '"' : 'the value of type ' . gettype($containingValue);
         throw new ValidatorException(sprintf('The metadata for ' . $valueAsString . ' does not support properties.'));
     }
     // If $containingValue is passed as class name, take $value as root
     // and start the traversal with an empty property path
     $propertyPath = is_object($containingValue) ? $property : '';
     foreach ($this->resolveGroups($groups) as $group) {
         if (!$metadata->hasPropertyMetadata($property)) {
             continue;
         }
         foreach ($metadata->getPropertyMetadata($property) as $propMeta) {
             $propMeta->accept($visitor, $value, $group, $propertyPath);
         }
     }
     return $visitor->getViolations();
 }
 public function testExecuteEmptyValidator()
 {
     $metadata = $this->getMock('Symfony\\Component\\Validator\\MetadataInterface');
     $this->validatorFactory->expects($this->once())->method('getMetadataFor')->with($this->equalTo('Acme\\Entity\\Foo'))->will($this->returnValue($metadata));
     $metadata->properties = array();
     $metadata->getters = array();
     $modelManager = $this->getMock('Sonata\\AdminBundle\\Model\\ModelManagerInterface');
     $this->admin->expects($this->any())->method('getModelManager')->will($this->returnValue($modelManager));
     // @todo Mock of \Traversable is available since Phpunit 3.8. This should be completed after stable release of Phpunit 3.8.
     // @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/103
     // $formBuilder = $this->getMock('Symfony\Component\Form\FormBuilderInterface');
     //
     // $this->admin->expects($this->any())
     //     ->method('getFormBuilder')
     //     ->will($this->returnValue($formBuilder));
     $datagridBuilder = $this->getMock('\\Sonata\\AdminBundle\\Builder\\DatagridBuilderInterface');
     $this->admin->expects($this->any())->method('getDatagridBuilder')->will($this->returnValue($datagridBuilder));
     $listBuilder = $this->getMock('Sonata\\AdminBundle\\Builder\\ListBuilderInterface');
     $this->admin->expects($this->any())->method('getListBuilder')->will($this->returnValue($listBuilder));
     $command = $this->application->find('sonata:admin:explain');
     $commandTester = new CommandTester($command);
     $commandTester->execute(array('command' => $command->getName(), 'admin' => 'acme.admin.foo'));
     $this->assertEquals(sprintf(str_replace("\n", PHP_EOL, file_get_contents(__DIR__ . '/../Fixtures/Command/explain_admin_empty_validator.txt')), get_class($this->admin), get_class($modelManager), get_class($datagridBuilder), get_class($listBuilder)), $commandTester->getDisplay());
 }
 /**
  * {@inheritdoc}
  */
 public function hasMetadataFor($object)
 {
     return $this->metadataFactory->hasMetadataFor($object);
 }
 public function find(FormInterface $form)
 {
     $propertyPath = $form->getPropertyPath();
     if ($form->getPropertyPath() === null) {
         return new ConstraintCollection();
     }
     $class = $this->resolveDataClass($form);
     if ($class === null) {
         return new ConstraintCollection();
     }
     $metadata = $this->metadataFactory->getMetadataFor($class);
     if (!$metadata instanceof ClassMetadata) {
         return new ConstraintCollection();
     }
     if ($propertyPath->getLength() < 1) {
         throw new UnsupportedException('Not supported please submit a issue with the form that produces this error!');
     }
     // Retrieve the last property element
     $propertyLastElementIndex = $propertyPath->getLength() - 1;
     $propertyName = $propertyPath->getElement($propertyLastElementIndex);
     if ($propertyPath->getLength() > 1) {
         // When we have multiple parts to the path then resolve it
         // To return the actual property and metadata
         // Resolve parent data
         list($dataSource, $dataSourceClass) = $this->resolveDataSource($form);
         for ($i = 0; $i < $propertyPath->getLength() - 1; $i++) {
             $element = $propertyPath->getElement($i);
             $property = $this->guessProperty($metadata, $element);
             // If the Valid tag is missing the property will return null.
             // Or if there is no data set on the form
             if ($property === null) {
                 return new ConstraintCollection();
             }
             foreach ($metadata->getPropertyMetadata($property) as $propertyMetadata) {
                 if (!$propertyMetadata instanceof MemberMetadata) {
                     continue;
                 }
                 $dataSourceInfo = $this->findPropertyDataTypeInfo($propertyMetadata, $dataSource, $dataSourceClass);
                 if ($dataSourceInfo === null) {
                     return new ConstraintCollection();
                 }
                 list($dataSourceClass, $dataSource) = $dataSourceInfo;
                 // Handle arrays/index based properties
                 while ($dataSourceClass === null) {
                     $i++;
                     if (!$propertyPath->isIndex($i)) {
                         // For some strange reason the findPropertyDataTypeInfo is wrong
                         // or the form is wrong
                         return new ConstraintCollection();
                     }
                     $dataSource = $dataSource[$propertyPath->getElement($i)];
                     if (is_object($dataSource)) {
                         $dataSourceClass = get_class($dataSource);
                     }
                 }
                 // Ok we failed to find the data source class
                 if ($dataSourceClass === null) {
                     return new ConstraintCollection();
                 }
                 $metadata = $this->metadataFactory->getMetadataFor($dataSourceClass);
                 if (!$metadata instanceof ClassMetadata) {
                     continue;
                 }
                 continue 2;
             }
             // We where unable to locate a class/array property
             return new ConstraintCollection();
         }
     }
     // Handle array properties
     $propertyCascadeOnly = false;
     if ($propertyPath->isIndex($propertyLastElementIndex)) {
         $propertyCascadeOnly = true;
         $elements = $form->getParent()->getPropertyPath()->getElements();
         $propertyName = end($elements);
     }
     // Find property constraints
     return $this->findPropertyConstraints($metadata, $propertyName, $propertyCascadeOnly);
 }