Наследование: extends AbstractValidator, implements Neos\Flow\Validation\Validator\ObjectValidatorInterface
 /**
  * @test
  */
 public function collectionValidatorValidatesNestedObjectStructuresWithoutEndlessLooping()
 {
     $classNameA = 'A' . md5(uniqid(mt_rand(), true));
     eval('class ' . $classNameA . '{ public $b = array(); public $integer = 5; }');
     $classNameB = 'B' . md5(uniqid(mt_rand(), true));
     eval('class ' . $classNameB . '{ public $a; public $c; public $integer = "Not an integer"; }');
     $A = new $classNameA();
     $B = new $classNameB();
     $A->b = [$B];
     $B->a = $A;
     $B->c = [$A];
     $this->mockValidatorResolver->expects($this->any())->method('createValidator')->with('Integer')->will($this->returnValue(new IntegerValidator()));
     $this->mockValidatorResolver->expects($this->any())->method('buildBaseValidatorConjunction')->will($this->returnValue(new GenericObjectValidator()));
     // Create validators
     $aValidator = new GenericObjectValidator([]);
     $this->validator->_set('options', ['elementValidator' => 'Integer', 'elementValidatorOptions' => []]);
     $integerValidator = new IntegerValidator([]);
     // Add validators to properties
     $aValidator->addPropertyValidator('b', $this->validator);
     $aValidator->addPropertyValidator('integer', $integerValidator);
     $result = $aValidator->validate($A)->getFlattenedErrors();
     $this->assertEquals('A valid integer number is expected.', $result['b.0'][0]->getMessage());
 }
 /**
  * Checks if the given value is valid according to the validator, and returns
  * the Error Messages object which occurred. Will skip validation if value is
  * an uninitialized lazy loading proxy.
  *
  * @param mixed $value The value that should be validated
  * @return \Neos\Error\Messages\Result
  * @api
  */
 public function validate($value)
 {
     $this->result = new Result();
     /**
      * The idea is that Aggregates form a consistency boundary, and an Aggregate only needs to be
      * validated if it changed state. Also since all entity relations are lazy loaded by default,
      * and the relation will only be initialized when it gets accessed (e.g. during property mapping),
      * we can just skip validation of an uninitialized aggregate.
      * This greatly improves validation performance for domain models with lots of small aggregate
      * relations. Therefore proper Aggregate Design becomes a performance optimization.
      */
     if ($value instanceof \Doctrine\ORM\Proxy\Proxy && !$value->__isInitialized()) {
         return $this->result;
     }
     return parent::validate($value);
 }
 /**
  * @test
  */
 public function validateCanHandleRecursiveTargetsWithoutEndlessLooping()
 {
     $classNameA = 'B' . md5(uniqid(mt_rand(), true));
     eval('class ' . $classNameA . '{ public $b; }');
     $classNameB = 'B' . md5(uniqid(mt_rand(), true));
     eval('class ' . $classNameB . '{ public $a; }');
     $A = new $classNameA();
     $B = new $classNameB();
     $A->b = $B;
     $B->a = $A;
     $aValidator = new GenericObjectValidator([]);
     $bValidator = new GenericObjectValidator([]);
     $aValidator->addPropertyValidator('b', $bValidator);
     $bValidator->addPropertyValidator('a', $aValidator);
     $this->assertFalse($aValidator->validate($A)->hasErrors());
 }