EntityChoiceFieldTest.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  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\Form;
  11. require_once __DIR__.'/DoctrineOrmTestCase.php';
  12. require_once __DIR__.'/Fixtures/SingleIdentEntity.php';
  13. require_once __DIR__.'/Fixtures/CompositeIdentEntity.php';
  14. use Symfony\Component\Form\EntityChoiceField;
  15. use Symfony\Component\Form\Exception\UnexpectedTypeException;
  16. use Symfony\Tests\Component\Form\Fixtures\SingleIdentEntity;
  17. use Symfony\Tests\Component\Form\Fixtures\CompositeIdentEntity;
  18. use Doctrine\ORM\Tools\SchemaTool;
  19. use Doctrine\Common\Collections\ArrayCollection;
  20. class EntityChoiceFieldTest extends DoctrineOrmTestCase
  21. {
  22. const SINGLE_IDENT_CLASS = 'Symfony\Tests\Component\Form\Fixtures\SingleIdentEntity';
  23. const COMPOSITE_IDENT_CLASS = 'Symfony\Tests\Component\Form\Fixtures\CompositeIdentEntity';
  24. /**
  25. * @var EntityManager
  26. */
  27. private $em;
  28. protected function setUp()
  29. {
  30. parent::setUp();
  31. $this->em = $this->createTestEntityManager();
  32. $schemaTool = new SchemaTool($this->em);
  33. $classes = array(
  34. $this->em->getClassMetadata(self::SINGLE_IDENT_CLASS),
  35. $this->em->getClassMetadata(self::COMPOSITE_IDENT_CLASS),
  36. );
  37. try {
  38. $schemaTool->dropSchema($classes);
  39. } catch(\Exception $e) {
  40. }
  41. try {
  42. $schemaTool->createSchema($classes);
  43. } catch(\Exception $e) {
  44. }
  45. }
  46. protected function persist(array $entities)
  47. {
  48. foreach ($entities as $entity) {
  49. $this->em->persist($entity);
  50. }
  51. $this->em->flush();
  52. // no clear, because entities managed by the choice field must
  53. // be managed!
  54. }
  55. public function testNonRequiredContainsEmptyField()
  56. {
  57. $entity1 = new SingleIdentEntity(1, 'Foo');
  58. $entity2 = new SingleIdentEntity(2, 'Bar');
  59. $this->persist(array($entity1, $entity2));
  60. $field = new EntityChoiceField('name', array(
  61. 'em' => $this->em,
  62. 'class' => self::SINGLE_IDENT_CLASS,
  63. 'required' => false,
  64. 'property' => 'name'
  65. ));
  66. $this->assertEquals(array('' => '', 1 => 'Foo', 2 => 'Bar'), $field->getOtherChoices());
  67. }
  68. // public function testSetDataToUninitializedEntityWithNonRequired()
  69. // {
  70. // $entity1 = new SingleIdentEntity(1, 'Foo');
  71. // $entity2 = new SingleIdentEntity(2, 'Bar');
  72. //
  73. // $this->persist(array($entity1, $entity2));
  74. //
  75. // $field = new EntityChoiceField('name', array(
  76. // 'em' => $this->em,
  77. // 'class' => self::SINGLE_IDENT_CLASS,
  78. // 'required' => false,
  79. // 'property' => 'name'
  80. // ));
  81. //
  82. // $this->assertEquals(array('' => '', 1 => 'Foo', 2 => 'Bar'), $field->getOtherChoices());
  83. //
  84. // }
  85. /**
  86. * @expectedException Symfony\Component\Form\Exception\InvalidOptionsException
  87. */
  88. public function testConfigureQueryBuilderWithNonQueryBuilderAndNonClosure()
  89. {
  90. $field = new EntityChoiceField('name', array(
  91. 'em' => $this->em,
  92. 'class' => self::SINGLE_IDENT_CLASS,
  93. 'query_builder' => new \stdClass(),
  94. ));
  95. }
  96. /**
  97. * @expectedException Symfony\Component\Form\Exception\InvalidOptionsException
  98. */
  99. public function testConfigureQueryBuilderWithClosureReturningNonQueryBuilder()
  100. {
  101. $field = new EntityChoiceField('name', array(
  102. 'em' => $this->em,
  103. 'class' => self::SINGLE_IDENT_CLASS,
  104. 'query_builder' => function () {
  105. return new \stdClass();
  106. },
  107. ));
  108. $field->submit('2');
  109. }
  110. /**
  111. * @expectedException Symfony\Component\Form\Exception\FormException
  112. */
  113. public function testChoicesMustBeManaged()
  114. {
  115. $entity1 = new SingleIdentEntity(1, 'Foo');
  116. $entity2 = new SingleIdentEntity(2, 'Bar');
  117. // no persist here!
  118. $field = new EntityChoiceField('name', array(
  119. 'multiple' => false,
  120. 'em' => $this->em,
  121. 'class' => self::SINGLE_IDENT_CLASS,
  122. 'choices' => array($entity1, $entity2),
  123. 'property' => 'name',
  124. ));
  125. }
  126. public function testSetDataSingle_null()
  127. {
  128. $field = new EntityChoiceField('name', array(
  129. 'multiple' => false,
  130. 'em' => $this->em,
  131. 'class' => self::SINGLE_IDENT_CLASS,
  132. ));
  133. $field->setData(null);
  134. $this->assertEquals(null, $field->getData());
  135. $this->assertEquals('', $field->getDisplayedData());
  136. }
  137. public function testSetDataMultipleExpanded_null()
  138. {
  139. $field = new EntityChoiceField('name', array(
  140. 'multiple' => true,
  141. 'expanded' => true,
  142. 'em' => $this->em,
  143. 'class' => self::SINGLE_IDENT_CLASS,
  144. ));
  145. $field->setData(null);
  146. $this->assertEquals(new ArrayCollection(), $field->getData());
  147. $this->assertEquals(array(), $field->getDisplayedData());
  148. }
  149. public function testSetDataMultipleNonExpanded_null()
  150. {
  151. $field = new EntityChoiceField('name', array(
  152. 'multiple' => true,
  153. 'expanded' => false,
  154. 'em' => $this->em,
  155. 'class' => self::SINGLE_IDENT_CLASS,
  156. ));
  157. $field->setData(null);
  158. $this->assertEquals(new ArrayCollection(), $field->getData());
  159. $this->assertEquals('', $field->getDisplayedData());
  160. }
  161. public function testSubmitSingleExpanded_null()
  162. {
  163. $field = new EntityChoiceField('name', array(
  164. 'multiple' => false,
  165. 'expanded' => true,
  166. 'em' => $this->em,
  167. 'class' => self::SINGLE_IDENT_CLASS,
  168. ));
  169. $field->submit(null);
  170. $this->assertEquals(null, $field->getData());
  171. $this->assertEquals(array(), $field->getDisplayedData());
  172. }
  173. public function testSubmitSingleNonExpanded_null()
  174. {
  175. $field = new EntityChoiceField('name', array(
  176. 'multiple' => false,
  177. 'expanded' => false,
  178. 'em' => $this->em,
  179. 'class' => self::SINGLE_IDENT_CLASS,
  180. ));
  181. $field->submit(null);
  182. $this->assertEquals(null, $field->getData());
  183. $this->assertEquals('', $field->getDisplayedData());
  184. }
  185. public function testSubmitMultiple_null()
  186. {
  187. $field = new EntityChoiceField('name', array(
  188. 'multiple' => true,
  189. 'em' => $this->em,
  190. 'class' => self::SINGLE_IDENT_CLASS,
  191. ));
  192. $field->submit(null);
  193. $this->assertEquals(new ArrayCollection(), $field->getData());
  194. $this->assertEquals(array(), $field->getDisplayedData());
  195. }
  196. public function testSubmitSingleNonExpanded_singleIdentifier()
  197. {
  198. $entity1 = new SingleIdentEntity(1, 'Foo');
  199. $entity2 = new SingleIdentEntity(2, 'Bar');
  200. $this->persist(array($entity1, $entity2));
  201. $field = new EntityChoiceField('name', array(
  202. 'multiple' => false,
  203. 'expanded' => false,
  204. 'em' => $this->em,
  205. 'class' => self::SINGLE_IDENT_CLASS,
  206. 'property' => 'name',
  207. ));
  208. $field->submit('2');
  209. $this->assertTrue($field->isTransformationSuccessful());
  210. $this->assertEquals($entity2, $field->getData());
  211. $this->assertEquals(2, $field->getDisplayedData());
  212. }
  213. public function testSubmitSingleNonExpanded_compositeIdentifier()
  214. {
  215. $entity1 = new CompositeIdentEntity(10, 20, 'Foo');
  216. $entity2 = new CompositeIdentEntity(30, 40, 'Bar');
  217. $this->persist(array($entity1, $entity2));
  218. $field = new EntityChoiceField('name', array(
  219. 'multiple' => false,
  220. 'expanded' => false,
  221. 'em' => $this->em,
  222. 'class' => self::COMPOSITE_IDENT_CLASS,
  223. 'property' => 'name',
  224. ));
  225. // the collection key is used here
  226. $field->submit('1');
  227. $this->assertTrue($field->isTransformationSuccessful());
  228. $this->assertEquals($entity2, $field->getData());
  229. $this->assertEquals(1, $field->getDisplayedData());
  230. }
  231. public function testSubmitMultipleNonExpanded_singleIdentifier()
  232. {
  233. $entity1 = new SingleIdentEntity(1, 'Foo');
  234. $entity2 = new SingleIdentEntity(2, 'Bar');
  235. $entity3 = new SingleIdentEntity(3, 'Baz');
  236. $this->persist(array($entity1, $entity2, $entity3));
  237. $field = new EntityChoiceField('name', array(
  238. 'multiple' => true,
  239. 'expanded' => false,
  240. 'em' => $this->em,
  241. 'class' => self::SINGLE_IDENT_CLASS,
  242. 'property' => 'name',
  243. ));
  244. $field->submit(array('1', '3'));
  245. $expected = new ArrayCollection(array($entity1, $entity3));
  246. $this->assertTrue($field->isTransformationSuccessful());
  247. $this->assertEquals($expected, $field->getData());
  248. $this->assertEquals(array(1, 3), $field->getDisplayedData());
  249. }
  250. public function testSubmitMultipleNonExpanded_singleIdentifier_existingData()
  251. {
  252. $entity1 = new SingleIdentEntity(1, 'Foo');
  253. $entity2 = new SingleIdentEntity(2, 'Bar');
  254. $entity3 = new SingleIdentEntity(3, 'Baz');
  255. $this->persist(array($entity1, $entity2, $entity3));
  256. $field = new EntityChoiceField('name', array(
  257. 'multiple' => true,
  258. 'expanded' => false,
  259. 'em' => $this->em,
  260. 'class' => self::SINGLE_IDENT_CLASS,
  261. 'property' => 'name',
  262. ));
  263. $existing = new ArrayCollection(array($entity2));
  264. $field->setData($existing);
  265. $field->submit(array('1', '3'));
  266. // entry with index 0 was removed
  267. $expected = new ArrayCollection(array(1 => $entity1, 2 => $entity3));
  268. $this->assertTrue($field->isTransformationSuccessful());
  269. $this->assertEquals($expected, $field->getData());
  270. // same object still, useful if it is a PersistentCollection
  271. $this->assertSame($existing, $field->getData());
  272. $this->assertEquals(array(1, 3), $field->getDisplayedData());
  273. }
  274. public function testSubmitMultipleNonExpanded_compositeIdentifier()
  275. {
  276. $entity1 = new CompositeIdentEntity(10, 20, 'Foo');
  277. $entity2 = new CompositeIdentEntity(30, 40, 'Bar');
  278. $entity3 = new CompositeIdentEntity(50, 60, 'Baz');
  279. $this->persist(array($entity1, $entity2, $entity3));
  280. $field = new EntityChoiceField('name', array(
  281. 'multiple' => true,
  282. 'expanded' => false,
  283. 'em' => $this->em,
  284. 'class' => self::COMPOSITE_IDENT_CLASS,
  285. 'property' => 'name',
  286. ));
  287. // because of the composite key collection keys are used
  288. $field->submit(array('0', '2'));
  289. $expected = new ArrayCollection(array($entity1, $entity3));
  290. $this->assertTrue($field->isTransformationSuccessful());
  291. $this->assertEquals($expected, $field->getData());
  292. $this->assertEquals(array(0, 2), $field->getDisplayedData());
  293. }
  294. public function testSubmitMultipleNonExpanded_compositeIdentifier_existingData()
  295. {
  296. $entity1 = new CompositeIdentEntity(10, 20, 'Foo');
  297. $entity2 = new CompositeIdentEntity(30, 40, 'Bar');
  298. $entity3 = new CompositeIdentEntity(50, 60, 'Baz');
  299. $this->persist(array($entity1, $entity2, $entity3));
  300. $field = new EntityChoiceField('name', array(
  301. 'multiple' => true,
  302. 'expanded' => false,
  303. 'em' => $this->em,
  304. 'class' => self::COMPOSITE_IDENT_CLASS,
  305. 'property' => 'name',
  306. ));
  307. $existing = new ArrayCollection(array(0 => $entity2));
  308. $field->setData($existing);
  309. $field->submit(array('0', '2'));
  310. // entry with index 0 was removed
  311. $expected = new ArrayCollection(array(1 => $entity1, 2 => $entity3));
  312. $this->assertTrue($field->isTransformationSuccessful());
  313. $this->assertEquals($expected, $field->getData());
  314. // same object still, useful if it is a PersistentCollection
  315. $this->assertSame($existing, $field->getData());
  316. $this->assertEquals(array(0, 2), $field->getDisplayedData());
  317. }
  318. public function testSubmitSingleExpanded()
  319. {
  320. $entity1 = new SingleIdentEntity(1, 'Foo');
  321. $entity2 = new SingleIdentEntity(2, 'Bar');
  322. $this->persist(array($entity1, $entity2));
  323. $field = new EntityChoiceField('name', array(
  324. 'multiple' => false,
  325. 'expanded' => true,
  326. 'em' => $this->em,
  327. 'class' => self::SINGLE_IDENT_CLASS,
  328. 'property' => 'name',
  329. ));
  330. $field->submit('2');
  331. $this->assertTrue($field->isTransformationSuccessful());
  332. $this->assertEquals($entity2, $field->getData());
  333. $this->assertSame(false, $field['1']->getData());
  334. $this->assertSame(true, $field['2']->getData());
  335. $this->assertSame('', $field['1']->getDisplayedData());
  336. $this->assertSame('1', $field['2']->getDisplayedData());
  337. $this->assertSame(array('1' => '', '2' => '1'), $field->getDisplayedData());
  338. }
  339. public function testSubmitMultipleExpanded()
  340. {
  341. $entity1 = new SingleIdentEntity(1, 'Foo');
  342. $entity2 = new SingleIdentEntity(2, 'Bar');
  343. $entity3 = new SingleIdentEntity(3, 'Bar');
  344. $this->persist(array($entity1, $entity2, $entity3));
  345. $field = new EntityChoiceField('name', array(
  346. 'multiple' => true,
  347. 'expanded' => true,
  348. 'em' => $this->em,
  349. 'class' => self::SINGLE_IDENT_CLASS,
  350. 'property' => 'name',
  351. ));
  352. $field->submit(array('1' => '1', '3' => '3'));
  353. $expected = new ArrayCollection(array($entity1, $entity3));
  354. $this->assertTrue($field->isTransformationSuccessful());
  355. $this->assertEquals($expected, $field->getData());
  356. $this->assertSame(true, $field['1']->getData());
  357. $this->assertSame(false, $field['2']->getData());
  358. $this->assertSame(true, $field['3']->getData());
  359. $this->assertSame('1', $field['1']->getDisplayedData());
  360. $this->assertSame('', $field['2']->getDisplayedData());
  361. $this->assertSame('1', $field['3']->getDisplayedData());
  362. $this->assertSame(array('1' => '1', '2' => '', '3' => '1'), $field->getDisplayedData());
  363. }
  364. public function testOverrideChoices()
  365. {
  366. $entity1 = new SingleIdentEntity(1, 'Foo');
  367. $entity2 = new SingleIdentEntity(2, 'Bar');
  368. $entity3 = new SingleIdentEntity(3, 'Baz');
  369. $this->persist(array($entity1, $entity2, $entity3));
  370. $field = new EntityChoiceField('name', array(
  371. 'em' => $this->em,
  372. 'class' => self::SINGLE_IDENT_CLASS,
  373. // not all persisted entities should be displayed
  374. 'choices' => array($entity1, $entity2),
  375. 'property' => 'name',
  376. ));
  377. $field->submit('2');
  378. $this->assertEquals(array(1 => 'Foo', 2 => 'Bar'), $field->getOtherChoices());
  379. $this->assertTrue($field->isTransformationSuccessful());
  380. $this->assertEquals($entity2, $field->getData());
  381. $this->assertEquals(2, $field->getDisplayedData());
  382. }
  383. public function testDisallowChoicesThatAreNotIncluded_choices_singleIdentifier()
  384. {
  385. $entity1 = new SingleIdentEntity(1, 'Foo');
  386. $entity2 = new SingleIdentEntity(2, 'Bar');
  387. $entity3 = new SingleIdentEntity(3, 'Baz');
  388. $this->persist(array($entity1, $entity2, $entity3));
  389. $field = new EntityChoiceField('name', array(
  390. 'em' => $this->em,
  391. 'class' => self::SINGLE_IDENT_CLASS,
  392. 'choices' => array($entity1, $entity2),
  393. 'property' => 'name',
  394. ));
  395. $field->submit('3');
  396. $this->assertFalse($field->isTransformationSuccessful());
  397. $this->assertNull($field->getData());
  398. }
  399. public function testDisallowChoicesThatAreNotIncluded_choices_compositeIdentifier()
  400. {
  401. $entity1 = new CompositeIdentEntity(10, 20, 'Foo');
  402. $entity2 = new CompositeIdentEntity(30, 40, 'Bar');
  403. $entity3 = new CompositeIdentEntity(50, 60, 'Baz');
  404. $this->persist(array($entity1, $entity2, $entity3));
  405. $field = new EntityChoiceField('name', array(
  406. 'em' => $this->em,
  407. 'class' => self::COMPOSITE_IDENT_CLASS,
  408. 'choices' => array($entity1, $entity2),
  409. 'property' => 'name',
  410. ));
  411. $field->submit('2');
  412. $this->assertFalse($field->isTransformationSuccessful());
  413. $this->assertNull($field->getData());
  414. }
  415. public function testDisallowChoicesThatAreNotIncluded_queryBuilder_singleIdentifier()
  416. {
  417. $entity1 = new SingleIdentEntity(1, 'Foo');
  418. $entity2 = new SingleIdentEntity(2, 'Bar');
  419. $entity3 = new SingleIdentEntity(3, 'Baz');
  420. $this->persist(array($entity1, $entity2, $entity3));
  421. $repository = $this->em->getRepository(self::SINGLE_IDENT_CLASS);
  422. $field = new EntityChoiceField('name', array(
  423. 'em' => $this->em,
  424. 'class' => self::SINGLE_IDENT_CLASS,
  425. 'query_builder' => $repository->createQueryBuilder('e')
  426. ->where('e.id IN (1, 2)'),
  427. 'property' => 'name',
  428. ));
  429. $field->submit('3');
  430. $this->assertFalse($field->isTransformationSuccessful());
  431. $this->assertNull($field->getData());
  432. }
  433. public function testDisallowChoicesThatAreNotIncluded_queryBuilderAsClosure_singleIdentifier()
  434. {
  435. $entity1 = new SingleIdentEntity(1, 'Foo');
  436. $entity2 = new SingleIdentEntity(2, 'Bar');
  437. $entity3 = new SingleIdentEntity(3, 'Baz');
  438. $this->persist(array($entity1, $entity2, $entity3));
  439. $field = new EntityChoiceField('name', array(
  440. 'em' => $this->em,
  441. 'class' => self::SINGLE_IDENT_CLASS,
  442. 'query_builder' => function ($repository) {
  443. return $repository->createQueryBuilder('e')
  444. ->where('e.id IN (1, 2)');
  445. },
  446. 'property' => 'name',
  447. ));
  448. $field->submit('3');
  449. $this->assertFalse($field->isTransformationSuccessful());
  450. $this->assertNull($field->getData());
  451. }
  452. public function testDisallowChoicesThatAreNotIncluded_queryBuilderAsClosure_compositeIdentifier()
  453. {
  454. $entity1 = new CompositeIdentEntity(10, 20, 'Foo');
  455. $entity2 = new CompositeIdentEntity(30, 40, 'Bar');
  456. $entity3 = new CompositeIdentEntity(50, 60, 'Baz');
  457. $this->persist(array($entity1, $entity2, $entity3));
  458. $field = new EntityChoiceField('name', array(
  459. 'em' => $this->em,
  460. 'class' => self::COMPOSITE_IDENT_CLASS,
  461. 'query_builder' => function ($repository) {
  462. return $repository->createQueryBuilder('e')
  463. ->where('e.id1 IN (10, 50)');
  464. },
  465. 'property' => 'name',
  466. ));
  467. $field->submit('2');
  468. $this->assertFalse($field->isTransformationSuccessful());
  469. $this->assertNull($field->getData());
  470. }
  471. }