ValidationVisitorTest.php

Namespace

Symfony\Component\Validator\Tests

File

drupal/core/vendor/symfony/validator/Symfony/Component/Validator/Tests/ValidationVisitorTest.php
View source
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Component\Validator\Tests;

use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory;
use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\Tests\Fixtures\Reference;
use Symfony\Component\Validator\DefaultTranslator;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\Tests\Fixtures\FailingConstraint;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintAValidator;
use Symfony\Component\Validator\Tests\Fixtures\Entity;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\ConstraintValidatorFactory;
use Symfony\Component\Validator\ValidationVisitor;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ValidationVisitorTest extends \PHPUnit_Framework_TestCase {
  const CLASS_NAME = 'Symfony\\Component\\Validator\\Tests\\Fixtures\\Entity';

  /**
   * @var ValidationVisitor
   */
  private $visitor;

  /**
   * @var FakeMetadataFactory
   */
  private $metadataFactory;

  /**
   * @var ClassMetadata
   */
  private $metadata;
  protected function setUp() {
    $this->metadataFactory = new FakeMetadataFactory();
    $this->visitor = new ValidationVisitor('Root', $this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator());
    $this->metadata = new ClassMetadata(self::CLASS_NAME);
    $this->metadataFactory
      ->addMetadata($this->metadata);
  }
  protected function tearDown() {
    $this->metadataFactory = null;
    $this->visitor = null;
    $this->metadata = null;
  }
  public function testValidatePassesCorrectClassAndProperty() {
    $this->metadata
      ->addConstraint(new ConstraintA());
    $entity = new Entity();
    $this->visitor
      ->validate($entity, 'Default', '');
    $context = ConstraintAValidator::$passedContext;
    $this
      ->assertEquals('Symfony\\Component\\Validator\\Tests\\Fixtures\\Entity', $context
      ->getClassName());
    $this
      ->assertNull($context
      ->getPropertyName());
  }
  public function testValidateConstraints() {
    $this->metadata
      ->addConstraint(new ConstraintA());
    $this->visitor
      ->validate(new Entity(), 'Default', '');
    $this
      ->assertCount(1, $this->visitor
      ->getViolations());
  }
  public function testValidateTwiceValidatesConstraintsOnce() {
    $this->metadata
      ->addConstraint(new ConstraintA());
    $entity = new Entity();
    $this->visitor
      ->validate($entity, 'Default', '');
    $this->visitor
      ->validate($entity, 'Default', '');
    $this
      ->assertCount(1, $this->visitor
      ->getViolations());
  }
  public function testValidateDifferentObjectsValidatesTwice() {
    $this->metadata
      ->addConstraint(new ConstraintA());
    $this->visitor
      ->validate(new Entity(), 'Default', '');
    $this->visitor
      ->validate(new Entity(), 'Default', '');
    $this
      ->assertCount(2, $this->visitor
      ->getViolations());
  }
  public function testValidateTwiceInDifferentGroupsValidatesTwice() {
    $this->metadata
      ->addConstraint(new ConstraintA());
    $this->metadata
      ->addConstraint(new ConstraintA(array(
      'groups' => 'Custom',
    )));
    $entity = new Entity();
    $this->visitor
      ->validate($entity, 'Default', '');
    $this->visitor
      ->validate($entity, 'Custom', '');
    $this
      ->assertCount(2, $this->visitor
      ->getViolations());
  }
  public function testValidatePropertyConstraints() {
    $this->metadata
      ->addPropertyConstraint('firstName', new ConstraintA());
    $this->visitor
      ->validate(new Entity(), 'Default', '');
    $this
      ->assertCount(1, $this->visitor
      ->getViolations());
  }
  public function testValidateGetterConstraints() {
    $this->metadata
      ->addGetterConstraint('lastName', new ConstraintA());
    $this->visitor
      ->validate(new Entity(), 'Default', '');
    $this
      ->assertCount(1, $this->visitor
      ->getViolations());
  }
  public function testValidateInDefaultGroupTraversesGroupSequence() {
    $entity = new Entity();
    $this->metadata
      ->addPropertyConstraint('firstName', new FailingConstraint(array(
      'groups' => 'First',
    )));
    $this->metadata
      ->addGetterConstraint('lastName', new FailingConstraint(array(
      'groups' => 'Default',
    )));
    $this->metadata
      ->setGroupSequence(array(
      'First',
      $this->metadata
        ->getDefaultGroup(),
    ));
    $this->visitor
      ->validate($entity, 'Default', '');

    // After validation of group "First" failed, no more group was
    // validated
    $violations = new ConstraintViolationList(array(
      new ConstraintViolation('Failed', 'Failed', array(), 'Root', 'firstName', ''),
    ));
    $this
      ->assertEquals($violations, $this->visitor
      ->getViolations());
  }
  public function testValidateInGroupSequencePropagatesDefaultGroup() {
    $entity = new Entity();
    $entity->reference = new Reference();
    $this->metadata
      ->addPropertyConstraint('reference', new Valid());
    $this->metadata
      ->setGroupSequence(array(
      $this->metadata
        ->getDefaultGroup(),
    ));
    $referenceMetadata = new ClassMetadata(get_class($entity->reference));
    $referenceMetadata
      ->addConstraint(new FailingConstraint(array(
      // this constraint is only evaluated if group "Default" is
      // propagated to the reference
      'groups' => 'Default',
    )));
    $this->metadataFactory
      ->addMetadata($referenceMetadata);
    $this->visitor
      ->validate($entity, 'Default', '');

    // The validation of the reference's FailingConstraint in group
    // "Default" was launched
    $violations = new ConstraintViolationList(array(
      new ConstraintViolation('Failed', 'Failed', array(), 'Root', 'reference', $entity->reference),
    ));
    $this
      ->assertEquals($violations, $this->visitor
      ->getViolations());
  }
  public function testValidateInOtherGroupTraversesNoGroupSequence() {
    $entity = new Entity();
    $this->metadata
      ->addPropertyConstraint('firstName', new FailingConstraint(array(
      'groups' => 'First',
    )));
    $this->metadata
      ->addGetterConstraint('lastName', new FailingConstraint(array(
      'groups' => $this->metadata
        ->getDefaultGroup(),
    )));
    $this->metadata
      ->setGroupSequence(array(
      'First',
      $this->metadata
        ->getDefaultGroup(),
    ));
    $this->visitor
      ->validate($entity, $this->metadata
      ->getDefaultGroup(), '');

    // Only group "Second" was validated
    $violations = new ConstraintViolationList(array(
      new ConstraintViolation('Failed', 'Failed', array(), 'Root', 'lastName', ''),
    ));
    $this
      ->assertEquals($violations, $this->visitor
      ->getViolations());
  }
  public function testValidateCascadedPropertyValidatesReferences() {
    $entity = new Entity();
    $entity->reference = new Entity();

    // add a constraint for the entity that always fails
    $this->metadata
      ->addConstraint(new FailingConstraint());

    // validate entity when validating the property "reference"
    $this->metadata
      ->addPropertyConstraint('reference', new Valid());

    // invoke validation on an object
    $this->visitor
      ->validate($entity, 'Default', '');
    $violations = new ConstraintViolationList(array(
      // generated by the root object
      new ConstraintViolation('Failed', 'Failed', array(), 'Root', '', $entity),
      // generated by the reference
      new ConstraintViolation('Failed', 'Failed', array(), 'Root', 'reference', $entity->reference),
    ));
    $this
      ->assertEquals($violations, $this->visitor
      ->getViolations());
  }
  public function testValidateCascadedPropertyValidatesArraysByDefault() {
    $entity = new Entity();
    $entity->reference = array(
      'key' => new Entity(),
    );

    // add a constraint for the entity that always fails
    $this->metadata
      ->addConstraint(new FailingConstraint());

    // validate array when validating the property "reference"
    $this->metadata
      ->addPropertyConstraint('reference', new Valid());
    $this->visitor
      ->validate($entity, 'Default', '');
    $violations = new ConstraintViolationList(array(
      // generated by the root object
      new ConstraintViolation('Failed', 'Failed', array(), 'Root', '', $entity),
      // generated by the reference
      new ConstraintViolation('Failed', 'Failed', array(), 'Root', 'reference[key]', $entity->reference['key']),
    ));
    $this
      ->assertEquals($violations, $this->visitor
      ->getViolations());
  }
  public function testValidateCascadedPropertyValidatesTraversableByDefault() {
    $entity = new Entity();
    $entity->reference = new \ArrayIterator(array(
      'key' => new Entity(),
    ));

    // add a constraint for the entity that always fails
    $this->metadata
      ->addConstraint(new FailingConstraint());

    // validate array when validating the property "reference"
    $this->metadata
      ->addPropertyConstraint('reference', new Valid());
    $this->visitor
      ->validate($entity, 'Default', '');
    $violations = new ConstraintViolationList(array(
      // generated by the root object
      new ConstraintViolation('Failed', 'Failed', array(), 'Root', '', $entity),
      // generated by the reference
      new ConstraintViolation('Failed', 'Failed', array(), 'Root', 'reference[key]', $entity->reference['key']),
    ));
    $this
      ->assertEquals($violations, $this->visitor
      ->getViolations());
  }
  public function testValidateCascadedPropertyDoesNotValidateTraversableIfDisabled() {
    $entity = new Entity();
    $entity->reference = new \ArrayIterator(array(
      'key' => new Entity(),
    ));
    $this->metadataFactory
      ->addMetadata(new ClassMetadata('ArrayIterator'));

    // add a constraint for the entity that always fails
    $this->metadata
      ->addConstraint(new FailingConstraint());

    // validate array when validating the property "reference"
    $this->metadata
      ->addPropertyConstraint('reference', new Valid(array(
      'traverse' => false,
    )));
    $this->visitor
      ->validate($entity, 'Default', '');
    $violations = new ConstraintViolationList(array(
      // generated by the root object
      new ConstraintViolation('Failed', 'Failed', array(), 'Root', '', $entity),
    ));
    $this
      ->assertEquals($violations, $this->visitor
      ->getViolations());
  }
  public function testMetadataMayNotExistIfTraversalIsEnabled() {
    $entity = new Entity();
    $entity->reference = new \ArrayIterator();
    $this->metadata
      ->addPropertyConstraint('reference', new Valid(array(
      'traverse' => true,
    )));
    $this->visitor
      ->validate($entity, 'Default', '');
  }

  /**
   * @expectedException \Symfony\Component\Validator\Exception\NoSuchMetadataException
   */
  public function testMetadataMustExistIfTraversalIsDisabled() {
    $entity = new Entity();
    $entity->reference = new \ArrayIterator();
    $this->metadata
      ->addPropertyConstraint('reference', new Valid(array(
      'traverse' => false,
    )));
    $this->visitor
      ->validate($entity, 'Default', '');
  }
  public function testValidateCascadedPropertyDoesNotRecurseByDefault() {
    $entity = new Entity();
    $entity->reference = new \ArrayIterator(array(
      // The inner iterator should not be traversed by default
      'key' => new \ArrayIterator(array(
        'nested' => new Entity(),
      )),
    ));
    $this->metadataFactory
      ->addMetadata(new ClassMetadata('ArrayIterator'));

    // add a constraint for the entity that always fails
    $this->metadata
      ->addConstraint(new FailingConstraint());

    // validate iterator when validating the property "reference"
    $this->metadata
      ->addPropertyConstraint('reference', new Valid());
    $this->visitor
      ->validate($entity, 'Default', '');
    $violations = new ConstraintViolationList(array(
      // generated by the root object
      new ConstraintViolation('Failed', 'Failed', array(), 'Root', '', $entity),
    ));
    $this
      ->assertEquals($violations, $this->visitor
      ->getViolations());
  }

  // https://github.com/symfony/symfony/issues/6246
  public function testValidateCascadedPropertyRecursesArraysByDefault() {
    $entity = new Entity();
    $entity->reference = array(
      'key' => array(
        'nested' => new Entity(),
      ),
    );

    // add a constraint for the entity that always fails
    $this->metadata
      ->addConstraint(new FailingConstraint());

    // validate iterator when validating the property "reference"
    $this->metadata
      ->addPropertyConstraint('reference', new Valid());
    $this->visitor
      ->validate($entity, 'Default', '');
    $violations = new ConstraintViolationList(array(
      // generated by the root object
      new ConstraintViolation('Failed', 'Failed', array(), 'Root', '', $entity),
      // nothing generated by the reference!
      new ConstraintViolation('Failed', 'Failed', array(), 'Root', 'reference[key][nested]', $entity->reference['key']['nested']),
    ));
    $this
      ->assertEquals($violations, $this->visitor
      ->getViolations());
  }
  public function testValidateCascadedPropertyRecursesIfDeepIsSet() {
    $entity = new Entity();
    $entity->reference = new \ArrayIterator(array(
      // The inner iterator should now be traversed
      'key' => new \ArrayIterator(array(
        'nested' => new Entity(),
      )),
    ));

    // add a constraint for the entity that always fails
    $this->metadata
      ->addConstraint(new FailingConstraint());

    // validate iterator when validating the property "reference"
    $this->metadata
      ->addPropertyConstraint('reference', new Valid(array(
      'deep' => true,
    )));
    $this->visitor
      ->validate($entity, 'Default', '');
    $violations = new ConstraintViolationList(array(
      // generated by the root object
      new ConstraintViolation('Failed', 'Failed', array(), 'Root', '', $entity),
      // nothing generated by the reference!
      new ConstraintViolation('Failed', 'Failed', array(), 'Root', 'reference[key][nested]', $entity->reference['key']['nested']),
    ));
    $this
      ->assertEquals($violations, $this->visitor
      ->getViolations());
  }
  public function testValidateCascadedPropertyDoesNotValidateNestedScalarValues() {
    $entity = new Entity();
    $entity->reference = array(
      'scalar',
      'values',
    );

    // validate array when validating the property "reference"
    $this->metadata
      ->addPropertyConstraint('reference', new Valid());
    $this->visitor
      ->validate($entity, 'Default', '');
    $this
      ->assertCount(0, $this->visitor
      ->getViolations());
  }
  public function testValidateCascadedPropertyDoesNotValidateNullValues() {
    $entity = new Entity();
    $entity->reference = null;
    $this->metadata
      ->addPropertyConstraint('reference', new Valid());
    $this->visitor
      ->validate($entity, 'Default', '');
    $this
      ->assertCount(0, $this->visitor
      ->getViolations());
  }

  /**
   * @expectedException \Symfony\Component\Validator\Exception\NoSuchMetadataException
   */
  public function testValidateCascadedPropertyRequiresObjectOrArray() {
    $entity = new Entity();
    $entity->reference = 'no object';
    $this->metadata
      ->addPropertyConstraint('reference', new Valid());
    $this->visitor
      ->validate($entity, 'Default', '');
  }

}

Classes

Namesort descending Description
ValidationVisitorTest @author Bernhard Schussek <bschussek@gmail.com>