GraphWalkerTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Tests\Component\Validator;
  11. require_once __DIR__.'/Fixtures/Entity.php';
  12. require_once __DIR__.'/Fixtures/Reference.php';
  13. require_once __DIR__.'/Fixtures/ConstraintA.php';
  14. require_once __DIR__.'/Fixtures/ConstraintAValidator.php';
  15. require_once __DIR__.'/Fixtures/FailingConstraint.php';
  16. require_once __DIR__.'/Fixtures/FailingConstraintValidator.php';
  17. require_once __DIR__.'/Fixtures/FakeClassMetadataFactory.php';
  18. use Symfony\Tests\Component\Validator\Fixtures\Entity;
  19. use Symfony\Tests\Component\Validator\Fixtures\Reference;
  20. use Symfony\Tests\Component\Validator\Fixtures\FakeClassMetadataFactory;
  21. use Symfony\Tests\Component\Validator\Fixtures\ConstraintA;
  22. use Symfony\Tests\Component\Validator\Fixtures\FailingConstraint;
  23. use Symfony\Component\Validator\GraphWalker;
  24. use Symfony\Component\Validator\ConstraintViolation;
  25. use Symfony\Component\Validator\ConstraintViolationList;
  26. use Symfony\Component\Validator\ConstraintValidatorFactory;
  27. use Symfony\Component\Validator\Mapping\ClassMetadata;
  28. use Symfony\Component\Validator\Constraints\Valid;
  29. class GraphWalkerTest extends \PHPUnit_Framework_TestCase
  30. {
  31. const CLASSNAME = 'Symfony\Tests\Component\Validator\Fixtures\Entity';
  32. protected $factory;
  33. protected $walker;
  34. protected $metadata;
  35. protected function setUp()
  36. {
  37. $this->factory = new FakeClassMetadataFactory();
  38. $this->walker = new GraphWalker('Root', $this->factory, new ConstraintValidatorFactory());
  39. $this->metadata = new ClassMetadata(self::CLASSNAME);
  40. }
  41. public function testWalkObjectValidatesConstraints()
  42. {
  43. $this->metadata->addConstraint(new ConstraintA());
  44. $this->walker->walkObject($this->metadata, new Entity(), 'Default', '');
  45. $this->assertEquals(1, count($this->walker->getViolations()));
  46. }
  47. public function testWalkObjectTwiceValidatesConstraintsOnce()
  48. {
  49. $this->metadata->addConstraint(new ConstraintA());
  50. $entity = new Entity();
  51. $this->walker->walkObject($this->metadata, $entity, 'Default', '');
  52. $this->walker->walkObject($this->metadata, $entity, 'Default', '');
  53. $this->assertEquals(1, count($this->walker->getViolations()));
  54. }
  55. public function testWalkDifferentObjectsValidatesTwice()
  56. {
  57. $this->metadata->addConstraint(new ConstraintA());
  58. $this->walker->walkObject($this->metadata, new Entity(), 'Default', '');
  59. $this->walker->walkObject($this->metadata, new Entity(), 'Default', '');
  60. $this->assertEquals(2, count($this->walker->getViolations()));
  61. }
  62. public function testWalkObjectTwiceInDifferentGroupsValidatesTwice()
  63. {
  64. $this->metadata->addConstraint(new ConstraintA());
  65. $this->metadata->addConstraint(new ConstraintA(array('groups' => 'Custom')));
  66. $entity = new Entity();
  67. $this->walker->walkObject($this->metadata, $entity, 'Default', '');
  68. $this->walker->walkObject($this->metadata, $entity, 'Custom', '');
  69. $this->assertEquals(2, count($this->walker->getViolations()));
  70. }
  71. public function testWalkObjectValidatesPropertyConstraints()
  72. {
  73. $this->metadata->addPropertyConstraint('firstName', new ConstraintA());
  74. $this->walker->walkObject($this->metadata, new Entity(), 'Default', '');
  75. $this->assertEquals(1, count($this->walker->getViolations()));
  76. }
  77. public function testWalkObjectValidatesGetterConstraints()
  78. {
  79. $this->metadata->addGetterConstraint('lastName', new ConstraintA());
  80. $this->walker->walkObject($this->metadata, new Entity(), 'Default', '');
  81. $this->assertEquals(1, count($this->walker->getViolations()));
  82. }
  83. public function testWalkObjectInDefaultGroupTraversesGroupSequence()
  84. {
  85. $entity = new Entity();
  86. $this->metadata->addPropertyConstraint('firstName', new FailingConstraint(array(
  87. 'groups' => 'First',
  88. )));
  89. $this->metadata->addGetterConstraint('lastName', new FailingConstraint(array(
  90. 'groups' => 'Default',
  91. )));
  92. $this->metadata->setGroupSequence(array('First', $this->metadata->getDefaultGroup()));
  93. $this->walker->walkObject($this->metadata, $entity, 'Default', '');
  94. // After validation of group "First" failed, no more group was
  95. // validated
  96. $violations = new ConstraintViolationList();
  97. $violations->add(new ConstraintViolation(
  98. '',
  99. array(),
  100. 'Root',
  101. 'firstName',
  102. ''
  103. ));
  104. $this->assertEquals($violations, $this->walker->getViolations());
  105. }
  106. public function testWalkObjectInGroupSequencePropagatesDefaultGroup()
  107. {
  108. $entity = new Entity();
  109. $entity->reference = new Reference();
  110. $this->metadata->addPropertyConstraint('reference', new Valid());
  111. $this->metadata->setGroupSequence(array($this->metadata->getDefaultGroup()));
  112. $referenceMetadata = new ClassMetadata(get_class($entity->reference));
  113. $referenceMetadata->addConstraint(new FailingConstraint(array(
  114. // this constraint is only evaluated if group "Default" is
  115. // propagated to the reference
  116. 'groups' => 'Default',
  117. )));
  118. $this->factory->addClassMetadata($referenceMetadata);
  119. $this->walker->walkObject($this->metadata, $entity, 'Default', '');
  120. // The validation of the reference's FailingConstraint in group
  121. // "Default" was launched
  122. $violations = new ConstraintViolationList();
  123. $violations->add(new ConstraintViolation(
  124. '',
  125. array(),
  126. 'Root',
  127. 'reference',
  128. $entity->reference
  129. ));
  130. $this->assertEquals($violations, $this->walker->getViolations());
  131. }
  132. public function testWalkObjectInOtherGroupTraversesNoGroupSequence()
  133. {
  134. $entity = new Entity();
  135. $this->metadata->addPropertyConstraint('firstName', new FailingConstraint(array(
  136. 'groups' => 'First',
  137. )));
  138. $this->metadata->addGetterConstraint('lastName', new FailingConstraint(array(
  139. 'groups' => $this->metadata->getDefaultGroup(),
  140. )));
  141. $this->metadata->setGroupSequence(array('First', $this->metadata->getDefaultGroup()));
  142. $this->walker->walkObject($this->metadata, $entity, $this->metadata->getDefaultGroup(), '');
  143. // Only group "Second" was validated
  144. $violations = new ConstraintViolationList();
  145. $violations->add(new ConstraintViolation(
  146. '',
  147. array(),
  148. 'Root',
  149. 'lastName',
  150. ''
  151. ));
  152. $this->assertEquals($violations, $this->walker->getViolations());
  153. }
  154. public function testWalkPropertyValueValidatesConstraints()
  155. {
  156. $this->metadata->addPropertyConstraint('firstName', new ConstraintA());
  157. $this->walker->walkPropertyValue($this->metadata, 'firstName', 'value', 'Default', '');
  158. $this->assertEquals(1, count($this->walker->getViolations()));
  159. }
  160. public function testWalkCascadedPropertyValidatesReferences()
  161. {
  162. $entity = new Entity();
  163. $entityMetadata = new ClassMetadata(get_class($entity));
  164. $this->factory->addClassMetadata($entityMetadata);
  165. // add a constraint for the entity that always fails
  166. $entityMetadata->addConstraint(new FailingConstraint());
  167. // validate entity when validating the property "reference"
  168. $this->metadata->addPropertyConstraint('reference', new Valid());
  169. // invoke validation on an object
  170. $this->walker->walkPropertyValue(
  171. $this->metadata,
  172. 'reference',
  173. $entity, // object!
  174. 'Default',
  175. 'path'
  176. );
  177. $violations = new ConstraintViolationList();
  178. $violations->add(new ConstraintViolation(
  179. '',
  180. array(),
  181. 'Root',
  182. 'path',
  183. $entity
  184. ));
  185. $this->assertEquals($violations, $this->walker->getViolations());
  186. }
  187. public function testWalkCascadedPropertyValidatesArraysByDefault()
  188. {
  189. $entity = new Entity();
  190. $entityMetadata = new ClassMetadata(get_class($entity));
  191. $this->factory->addClassMetadata($entityMetadata);
  192. // add a constraint for the entity that always fails
  193. $entityMetadata->addConstraint(new FailingConstraint());
  194. // validate array when validating the property "reference"
  195. $this->metadata->addPropertyConstraint('reference', new Valid());
  196. $this->walker->walkPropertyValue(
  197. $this->metadata,
  198. 'reference',
  199. array('key' => $entity), // array!
  200. 'Default',
  201. 'path'
  202. );
  203. $violations = new ConstraintViolationList();
  204. $violations->add(new ConstraintViolation(
  205. '',
  206. array(),
  207. 'Root',
  208. 'path[key]',
  209. $entity
  210. ));
  211. $this->assertEquals($violations, $this->walker->getViolations());
  212. }
  213. public function testWalkCascadedPropertyValidatesTraversableByDefault()
  214. {
  215. $entity = new Entity();
  216. $entityMetadata = new ClassMetadata(get_class($entity));
  217. $this->factory->addClassMetadata($entityMetadata);
  218. $this->factory->addClassMetadata(new ClassMetadata('ArrayIterator'));
  219. // add a constraint for the entity that always fails
  220. $entityMetadata->addConstraint(new FailingConstraint());
  221. // validate array when validating the property "reference"
  222. $this->metadata->addPropertyConstraint('reference', new Valid());
  223. $this->walker->walkPropertyValue(
  224. $this->metadata,
  225. 'reference',
  226. new \ArrayIterator(array('key' => $entity)),
  227. 'Default',
  228. 'path'
  229. );
  230. $violations = new ConstraintViolationList();
  231. $violations->add(new ConstraintViolation(
  232. '',
  233. array(),
  234. 'Root',
  235. 'path[key]',
  236. $entity
  237. ));
  238. $this->assertEquals($violations, $this->walker->getViolations());
  239. }
  240. public function testWalkCascadedPropertyDoesNotValidateTraversableIfDisabled()
  241. {
  242. $entity = new Entity();
  243. $entityMetadata = new ClassMetadata(get_class($entity));
  244. $this->factory->addClassMetadata($entityMetadata);
  245. $this->factory->addClassMetadata(new ClassMetadata('ArrayIterator'));
  246. // add a constraint for the entity that always fails
  247. $entityMetadata->addConstraint(new FailingConstraint());
  248. // validate array when validating the property "reference"
  249. $this->metadata->addPropertyConstraint('reference', new Valid(array(
  250. 'traverse' => false,
  251. )));
  252. $this->walker->walkPropertyValue(
  253. $this->metadata,
  254. 'reference',
  255. new \ArrayIterator(array('key' => $entity)),
  256. 'Default',
  257. 'path'
  258. );
  259. $violations = new ConstraintViolationList();
  260. $this->assertEquals($violations, $this->walker->getViolations());
  261. }
  262. public function testWalkCascadedPropertyDoesNotValidateNullValues()
  263. {
  264. $this->metadata->addPropertyConstraint('reference', new Valid());
  265. $this->walker->walkPropertyValue(
  266. $this->metadata,
  267. 'reference',
  268. null,
  269. 'Default',
  270. ''
  271. );
  272. $this->assertEquals(0, count($this->walker->getViolations()));
  273. }
  274. public function testWalkCascadedPropertyRequiresObjectOrArray()
  275. {
  276. $this->metadata->addPropertyConstraint('reference', new Valid());
  277. $this->setExpectedException('Symfony\Component\Validator\Exception\UnexpectedTypeException');
  278. $this->walker->walkPropertyValue(
  279. $this->metadata,
  280. 'reference',
  281. 'no object',
  282. 'Default',
  283. ''
  284. );
  285. }
  286. public function testWalkConstraintBuildsAViolationIfFailed()
  287. {
  288. $constraint = new ConstraintA();
  289. $this->walker->walkConstraint($constraint, 'foobar', 'Default', 'firstName.path');
  290. $violations = new ConstraintViolationList();
  291. $violations->add(new ConstraintViolation(
  292. 'message',
  293. array('param' => 'value'),
  294. 'Root',
  295. 'firstName.path',
  296. 'foobar'
  297. ));
  298. $this->assertEquals($violations, $this->walker->getViolations());
  299. }
  300. public function testWalkConstraintBuildsNoViolationIfSuccessful()
  301. {
  302. $constraint = new ConstraintA();
  303. $this->walker->walkConstraint($constraint, 'VALID', 'Default', 'firstName.path');
  304. $this->assertEquals(0, count($this->walker->getViolations()));
  305. }
  306. }