ÿØÿà JFIF    ÿÛ „ ( %!1!%*+...983,7(-.- Symfony/Component/Form/Tests/AbstractTableLayoutTest.php000064400000036100152374770060017454 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\FormError; use Symfony\Component\Security\Csrf\CsrfToken; abstract class AbstractTableLayoutTest extends AbstractLayoutTest { public function testRow() { $form = $this->factory->createNamed('name', 'text'); $form->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $html = $this->renderRow($view); $this->assertMatchesXpath($html, '/tr [ ./td [./label[@for="name"]] /following-sibling::td [ ./ul [./li[.="[trans]Error![/trans]"]] [count(./li)=1] /following-sibling::input[@id="name"] ] ] ' ); } public function testLabelIsNotRenderedWhenSetToFalse() { $form = $this->factory->createNamed('name', 'text', null, array( 'label' => false )); $html = $this->renderRow($form->createView()); $this->assertMatchesXpath($html, '/tr [ ./td [count(//label)=0] /following-sibling::td [./input[@id="name"]] ] ' ); } public function testRepeatedRow() { $form = $this->factory->createNamed('name', 'repeated'); $html = $this->renderRow($form->createView()); $this->assertMatchesXpath($html, '/tr [ ./td [./label[@for="name_first"]] /following-sibling::td [./input[@id="name_first"]] ] /following-sibling::tr [ ./td [./label[@for="name_second"]] /following-sibling::td [./input[@id="name_second"]] ] /following-sibling::tr[@style="display: none"] [./td[@colspan="2"]/input [@type="hidden"] [@id="name__token"] ] [count(../tr)=3] ' ); } public function testRepeatedRowWithErrors() { $form = $this->factory->createNamed('name', 'repeated'); $form->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $html = $this->renderRow($view); // The errors of the form are not rendered by intention! // In practice, repeated fields cannot have errors as all errors // on them are mapped to the first child. // (see RepeatedTypeValidatorExtension) $this->assertMatchesXpath($html, '/tr [ ./td [./label[@for="name_first"]] /following-sibling::td [./input[@id="name_first"]] ] /following-sibling::tr [ ./td [./label[@for="name_second"]] /following-sibling::td [./input[@id="name_second"]] ] /following-sibling::tr[@style="display: none"] [./td[@colspan="2"]/input [@type="hidden"] [@id="name__token"] ] [count(../tr)=3] ' ); } public function testButtonRow() { $form = $this->factory->createNamed('name', 'button'); $view = $form->createView(); $html = $this->renderRow($view); $this->assertMatchesXpath($html, '/tr [ ./td [.=""] /following-sibling::td [./button[@type="button"][@name="name"]] ] [count(//label)=0] ' ); } public function testRest() { $view = $this->factory->createNamedBuilder('name', 'form') ->add('field1', 'text') ->add('field2', 'repeated') ->add('field3', 'text') ->add('field4', 'text') ->getForm() ->createView(); // Render field2 row -> does not implicitly call renderWidget because // it is a repeated field! $this->renderRow($view['field2']); // Render field3 widget $this->renderWidget($view['field3']); // Rest should only contain field1 and field4 $html = $this->renderRest($view); $this->assertMatchesXpath($html, '/tr [ ./td [./label[@for="name_field1"]] /following-sibling::td [./input[@id="name_field1"]] ] /following-sibling::tr [ ./td [./label[@for="name_field4"]] /following-sibling::td [./input[@id="name_field4"]] ] [count(../tr)=3] [count(..//label)=2] [count(..//input)=3] /following-sibling::tr[@style="display: none"] [./td[@colspan="2"]/input [@type="hidden"] [@id="name__token"] ] ' ); } public function testCollection() { $form = $this->factory->createNamed('name', 'collection', array('a', 'b'), array( 'type' => 'text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/table [ ./tr[./td/input[@type="text"][@value="a"]] /following-sibling::tr[./td/input[@type="text"][@value="b"]] /following-sibling::tr[@style="display: none"][./td[@colspan="2"]/input[@type="hidden"][@id="name__token"]] ] [count(./tr[./td/input])=3] ' ); } public function testEmptyCollection() { $form = $this->factory->createNamed('name', 'collection', array(), array( 'type' => 'text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/table [./tr[@style="display: none"][./td[@colspan="2"]/input[@type="hidden"][@id="name__token"]]] [count(./tr[./td/input])=1] ' ); } public function testForm() { $view = $this->factory->createNamedBuilder('name', 'form') ->setMethod('PUT') ->setAction('http://example.com') ->add('firstName', 'text') ->add('lastName', 'text') ->getForm() ->createView(); $html = $this->renderForm($view, array( 'id' => 'my&id', 'attr' => array('class' => 'my&class'), )); $this->assertMatchesXpath($html, '/form [ ./input[@type="hidden"][@name="_method"][@value="PUT"] /following-sibling::table [ ./tr [ ./td [./label[@for="name_firstName"]] /following-sibling::td [./input[@id="name_firstName"]] ] /following-sibling::tr [ ./td [./label[@for="name_lastName"]] /following-sibling::td [./input[@id="name_lastName"]] ] /following-sibling::tr[@style="display: none"] [./td[@colspan="2"]/input [@type="hidden"] [@id="name__token"] ] ] [count(.//input)=3] [@id="my&id"] [@class="my&class"] ] [@method="post"] [@action="http://example.com"] [@class="my&class"] ' ); } public function testFormWidget() { $view = $this->factory->createNamedBuilder('name', 'form') ->add('firstName', 'text') ->add('lastName', 'text') ->getForm() ->createView(); $this->assertWidgetMatchesXpath($view, array(), '/table [ ./tr [ ./td [./label[@for="name_firstName"]] /following-sibling::td [./input[@id="name_firstName"]] ] /following-sibling::tr [ ./td [./label[@for="name_lastName"]] /following-sibling::td [./input[@id="name_lastName"]] ] /following-sibling::tr[@style="display: none"] [./td[@colspan="2"]/input [@type="hidden"] [@id="name__token"] ] ] [count(.//input)=3] ' ); } // https://github.com/symfony/symfony/issues/2308 public function testNestedFormError() { $form = $this->factory->createNamedBuilder('name', 'form') ->add($this->factory ->createNamedBuilder('child', 'form', null, array('error_bubbling' => false)) ->add('grandChild', 'form') ) ->getForm(); $form->get('child')->addError(new FormError('[trans]Error![/trans]')); $this->assertWidgetMatchesXpath($form->createView(), array(), '/table [ ./tr/td/ul[./li[.="[trans]Error![/trans]"]] /following-sibling::table[@id="name_child"] ] [count(.//li[.="[trans]Error![/trans]"])=1] ' ); } public function testCsrf() { $this->csrfTokenManager->expects($this->any()) ->method('getToken') ->will($this->returnValue(new CsrfToken('token_id', 'foo&bar'))); $form = $this->factory->createNamedBuilder('name', 'form') ->add($this->factory // No CSRF protection on nested forms ->createNamedBuilder('child', 'form') ->add($this->factory->createNamedBuilder('grandchild', 'text')) ) ->getForm(); $this->assertWidgetMatchesXpath($form->createView(), array(), '/table [ ./tr[@style="display: none"] [./td[@colspan="2"]/input [@type="hidden"] [@id="name__token"] ] ] [count(.//input[@type="hidden"])=1] ' ); } public function testRepeated() { $form = $this->factory->createNamed('name', 'repeated', 'foobar', array( 'type' => 'text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/table [ ./tr [ ./td [./label[@for="name_first"]] /following-sibling::td [./input[@type="text"][@id="name_first"]] ] /following-sibling::tr [ ./td [./label[@for="name_second"]] /following-sibling::td [./input[@type="text"][@id="name_second"]] ] /following-sibling::tr[@style="display: none"] [./td[@colspan="2"]/input [@type="hidden"] [@id="name__token"] ] ] [count(.//input)=3] ' ); } public function testRepeatedWithCustomOptions() { $form = $this->factory->createNamed('name', 'repeated', 'foobar', array( 'type' => 'password', 'first_options' => array('label' => 'Test', 'required' => false), 'second_options' => array('label' => 'Test2') )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/table [ ./tr [ ./td [./label[@for="name_first"][.="[trans]Test[/trans]"]] /following-sibling::td [./input[@type="password"][@id="name_first"][@required="required"]] ] /following-sibling::tr [ ./td [./label[@for="name_second"][.="[trans]Test2[/trans]"]] /following-sibling::td [./input[@type="password"][@id="name_second"][@required="required"]] ] /following-sibling::tr[@style="display: none"] [./td[@colspan="2"]/input [@type="hidden"] [@id="name__token"] ] ] [count(.//input)=3] ' ); } /** * The block "_name_child_label" should be overridden in the theme of the * implemented driver. */ public function testCollectionRowWithCustomBlock() { $collection = array('one', 'two', 'three'); $form = $this->factory->createNamedBuilder('name', 'collection', $collection) ->getForm(); $this->assertWidgetMatchesXpath($form->createView(), array(), '/table [ ./tr[./td/label[.="Custom label: [trans]0[/trans]"]] /following-sibling::tr[./td/label[.="Custom label: [trans]1[/trans]"]] /following-sibling::tr[./td/label[.="Custom label: [trans]2[/trans]"]] ] ' ); } public function testFormEndWithRest() { $view = $this->factory->createNamedBuilder('name', 'form') ->add('field1', 'text') ->add('field2', 'text') ->getForm() ->createView(); $this->renderWidget($view['field1']); // Rest should only contain field2 $html = $this->renderEnd($view); // Insert the start tag, the end tag should be rendered by the helper // Unfortunately this is not valid HTML, because the surrounding table // tag is missing. If someone renders a form with table layout // manually, she should call form_rest() explicitly within the // tag. $this->assertMatchesXpath('' . $html, '/form [ ./tr [ ./td [./label[@for="name_field2"]] /following-sibling::td [./input[@id="name_field2"]] ] /following-sibling::tr[@style="display: none"] [./td[@colspan="2"]/input [@type="hidden"] [@id="name__token"] ] ] ' ); } public function testFormEndWithoutRest() { $view = $this->factory->createNamedBuilder('name', 'form') ->add('field1', 'text') ->add('field2', 'text') ->getForm() ->createView(); $this->renderWidget($view['field1']); // Rest should only contain field2, but isn't rendered $html = $this->renderEnd($view, array('render_rest' => false)); $this->assertEquals('', $html); } public function testWidgetContainerAttributes() { $form = $this->factory->createNamed('form', 'form', null, array( 'attr' => array('class' => 'foobar', 'data-foo' => 'bar'), )); $form->add('text', 'text'); $html = $this->renderWidget($form->createView()); // compare plain HTML to check the whitespace $this->assertContains('
', $html); } public function testWidgetContainerAttributeNameRepeatedIfTrue() { $form = $this->factory->createNamed('form', 'form', null, array( 'attr' => array('foo' => true), )); $html = $this->renderWidget($form->createView()); // foo="foo" $this->assertContains('
', $html); } public function testWidgetContainerAttributeHiddenIfFalse() { $form = $this->factory->createNamed('form', 'form', null, array( 'attr' => array('foo' => false), )); $html = $this->renderWidget($form->createView()); // no foo $this->assertContains('
', $html); } } Symfony/Component/Form/Tests/SimpleFormTest.php000064400000075646152374770060015642 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\Form; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\FormError; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; use Symfony\Component\Form\Tests\Fixtures\FixedFilterListener; class SimpleFormTest_Countable implements \Countable { private $count; public function __construct($count) { $this->count = $count; } public function count() { return $this->count; } } class SimpleFormTest_Traversable implements \IteratorAggregate { private $iterator; public function __construct($count) { $this->iterator = new \ArrayIterator($count > 0 ? array_fill(0, $count, 'Foo') : array()); } public function getIterator() { return $this->iterator; } } class SimpleFormTest extends AbstractFormTest { public function testDataIsInitializedToConfiguredValue() { $model = new FixedDataTransformer(array( 'default' => 'foo', )); $view = new FixedDataTransformer(array( 'foo' => 'bar', )); $config = new FormConfigBuilder('name', null, $this->dispatcher); $config->addViewTransformer($view); $config->addModelTransformer($model); $config->setData('default'); $form = new Form($config); $this->assertSame('default', $form->getData()); $this->assertSame('foo', $form->getNormData()); $this->assertSame('bar', $form->getViewData()); } // https://github.com/symfony/symfony/commit/d4f4038f6daf7cf88ca7c7ab089473cce5ebf7d8#commitcomment-1632879 public function testDataIsInitializedFromSubmit() { $mock = $this->getMockBuilder('\stdClass') ->setMethods(array('preSetData', 'preSubmit')) ->getMock(); $mock->expects($this->at(0)) ->method('preSetData'); $mock->expects($this->at(1)) ->method('preSubmit'); $config = new FormConfigBuilder('name', null, $this->dispatcher); $config->addEventListener(FormEvents::PRE_SET_DATA, array($mock, 'preSetData')); $config->addEventListener(FormEvents::PRE_SUBMIT, array($mock, 'preSubmit')); $form = new Form($config); // no call to setData() or similar where the object would be // initialized otherwise $form->submit('foobar'); } // https://github.com/symfony/symfony/pull/7789 public function testFalseIsConvertedToNull() { $mock = $this->getMockBuilder('\stdClass') ->setMethods(array('preBind')) ->getMock(); $mock->expects($this->once()) ->method('preBind') ->with($this->callback(function ($event) { return null === $event->getData(); })); $config = new FormConfigBuilder('name', null, $this->dispatcher); $config->addEventListener(FormEvents::PRE_BIND, array($mock, 'preBind')); $form = new Form($config); $form->bind(false); $this->assertTrue($form->isValid()); $this->assertNull($form->getData()); } /** * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException */ public function testSubmitThrowsExceptionIfAlreadySubmitted() { $this->form->submit(array()); $this->form->submit(array()); } public function testSubmitIsIgnoredIfDisabled() { $form = $this->getBuilder() ->setDisabled(true) ->setData('initial') ->getForm(); $form->submit('new'); $this->assertEquals('initial', $form->getData()); $this->assertTrue($form->isSubmitted()); } public function testNeverRequiredIfParentNotRequired() { $parent = $this->getBuilder()->setRequired(false)->getForm(); $child = $this->getBuilder()->setRequired(true)->getForm(); $child->setParent($parent); $this->assertFalse($child->isRequired()); } public function testRequired() { $parent = $this->getBuilder()->setRequired(true)->getForm(); $child = $this->getBuilder()->setRequired(true)->getForm(); $child->setParent($parent); $this->assertTrue($child->isRequired()); } public function testNotRequired() { $parent = $this->getBuilder()->setRequired(true)->getForm(); $child = $this->getBuilder()->setRequired(false)->getForm(); $child->setParent($parent); $this->assertFalse($child->isRequired()); } public function testAlwaysDisabledIfParentDisabled() { $parent = $this->getBuilder()->setDisabled(true)->getForm(); $child = $this->getBuilder()->setDisabled(false)->getForm(); $child->setParent($parent); $this->assertTrue($child->isDisabled()); } public function testDisabled() { $parent = $this->getBuilder()->setDisabled(false)->getForm(); $child = $this->getBuilder()->setDisabled(true)->getForm(); $child->setParent($parent); $this->assertTrue($child->isDisabled()); } public function testNotDisabled() { $parent = $this->getBuilder()->setDisabled(false)->getForm(); $child = $this->getBuilder()->setDisabled(false)->getForm(); $child->setParent($parent); $this->assertFalse($child->isDisabled()); } public function testGetRootReturnsRootOfParent() { $parent = $this->getMockForm(); $parent->expects($this->once()) ->method('getRoot') ->will($this->returnValue('ROOT')); $this->form->setParent($parent); $this->assertEquals('ROOT', $this->form->getRoot()); } public function testGetRootReturnsSelfIfNoParent() { $this->assertSame($this->form, $this->form->getRoot()); } public function testEmptyIfEmptyArray() { $this->form->setData(array()); $this->assertTrue($this->form->isEmpty()); } public function testEmptyIfEmptyCountable() { $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Countable', $this->dispatcher)); $this->form->setData(new SimpleFormTest_Countable(0)); $this->assertTrue($this->form->isEmpty()); } public function testNotEmptyIfFilledCountable() { $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Countable', $this->dispatcher)); $this->form->setData(new SimpleFormTest_Countable(1)); $this->assertFalse($this->form->isEmpty()); } public function testEmptyIfEmptyTraversable() { $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Traversable', $this->dispatcher)); $this->form->setData(new SimpleFormTest_Traversable(0)); $this->assertTrue($this->form->isEmpty()); } public function testNotEmptyIfFilledTraversable() { $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Traversable', $this->dispatcher)); $this->form->setData(new SimpleFormTest_Traversable(1)); $this->assertFalse($this->form->isEmpty()); } public function testEmptyIfNull() { $this->form->setData(null); $this->assertTrue($this->form->isEmpty()); } public function testEmptyIfEmptyString() { $this->form->setData(''); $this->assertTrue($this->form->isEmpty()); } public function testNotEmptyIfText() { $this->form->setData('foobar'); $this->assertFalse($this->form->isEmpty()); } public function testValidIfSubmitted() { $form = $this->getBuilder()->getForm(); $form->submit('foobar'); $this->assertTrue($form->isValid()); } public function testValidIfSubmittedAndDisabled() { $form = $this->getBuilder()->setDisabled(true)->getForm(); $form->submit('foobar'); $this->assertTrue($form->isValid()); } public function testNotValidIfNotSubmitted() { $this->assertFalse($this->form->isValid()); } public function testNotValidIfErrors() { $form = $this->getBuilder()->getForm(); $form->submit('foobar'); $form->addError(new FormError('Error!')); $this->assertFalse($form->isValid()); } public function testHasErrors() { $this->form->addError(new FormError('Error!')); $this->assertCount(1, $this->form->getErrors()); } public function testHasNoErrors() { $this->assertCount(0, $this->form->getErrors()); } /** * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException */ public function testSetParentThrowsExceptionIfAlreadySubmitted() { $this->form->submit(array()); $this->form->setParent($this->getBuilder('parent')->getForm()); } public function testSubmitted() { $form = $this->getBuilder()->getForm(); $form->submit('foobar'); $this->assertTrue($form->isSubmitted()); } public function testNotSubmitted() { $this->assertFalse($this->form->isSubmitted()); } /** * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException */ public function testSetDataThrowsExceptionIfAlreadySubmitted() { $this->form->submit(array()); $this->form->setData(null); } public function testSetDataClonesObjectIfNotByReference() { $data = new \stdClass(); $form = $this->getBuilder('name', null, '\stdClass')->setByReference(false)->getForm(); $form->setData($data); $this->assertNotSame($data, $form->getData()); $this->assertEquals($data, $form->getData()); } public function testSetDataDoesNotCloneObjectIfByReference() { $data = new \stdClass(); $form = $this->getBuilder('name', null, '\stdClass')->setByReference(true)->getForm(); $form->setData($data); $this->assertSame($data, $form->getData()); } public function testSetDataExecutesTransformationChain() { // use real event dispatcher now $form = $this->getBuilder('name', new EventDispatcher()) ->addEventSubscriber(new FixedFilterListener(array( 'preSetData' => array( 'app' => 'filtered', ), ))) ->addModelTransformer(new FixedDataTransformer(array( '' => '', 'filtered' => 'norm', ))) ->addViewTransformer(new FixedDataTransformer(array( '' => '', 'norm' => 'client', ))) ->getForm(); $form->setData('app'); $this->assertEquals('filtered', $form->getData()); $this->assertEquals('norm', $form->getNormData()); $this->assertEquals('client', $form->getViewData()); } public function testSetDataExecutesViewTransformersInOrder() { $form = $this->getBuilder() ->addViewTransformer(new FixedDataTransformer(array( '' => '', 'first' => 'second', ))) ->addViewTransformer(new FixedDataTransformer(array( '' => '', 'second' => 'third', ))) ->getForm(); $form->setData('first'); $this->assertEquals('third', $form->getViewData()); } public function testSetDataExecutesModelTransformersInReverseOrder() { $form = $this->getBuilder() ->addModelTransformer(new FixedDataTransformer(array( '' => '', 'second' => 'third', ))) ->addModelTransformer(new FixedDataTransformer(array( '' => '', 'first' => 'second', ))) ->getForm(); $form->setData('first'); $this->assertEquals('third', $form->getNormData()); } /* * When there is no data transformer, the data must have the same format * in all three representations */ public function testSetDataConvertsScalarToStringIfNoTransformer() { $form = $this->getBuilder()->getForm(); $form->setData(1); $this->assertSame('1', $form->getData()); $this->assertSame('1', $form->getNormData()); $this->assertSame('1', $form->getViewData()); } /* * Data in client format should, if possible, always be a string to * facilitate differentiation between '0' and '' */ public function testSetDataConvertsScalarToStringIfOnlyModelTransformer() { $form = $this->getBuilder() ->addModelTransformer(new FixedDataTransformer(array( '' => '', 1 => 23, ))) ->getForm(); $form->setData(1); $this->assertSame(1, $form->getData()); $this->assertSame(23, $form->getNormData()); $this->assertSame('23', $form->getViewData()); } /* * NULL remains NULL in app and norm format to remove the need to treat * empty values and NULL explicitly in the application */ public function testSetDataConvertsNullToStringIfNoTransformer() { $form = $this->getBuilder()->getForm(); $form->setData(null); $this->assertNull($form->getData()); $this->assertNull($form->getNormData()); $this->assertSame('', $form->getViewData()); } public function testSetDataIsIgnoredIfDataIsLocked() { $form = $this->getBuilder() ->setData('default') ->setDataLocked(true) ->getForm(); $form->setData('foobar'); $this->assertSame('default', $form->getData()); } public function testSubmitConvertsEmptyToNullIfNoTransformer() { $form = $this->getBuilder()->getForm(); $form->submit(''); $this->assertNull($form->getData()); $this->assertNull($form->getNormData()); $this->assertSame('', $form->getViewData()); } public function testSubmitExecutesTransformationChain() { // use real event dispatcher now $form = $this->getBuilder('name', new EventDispatcher()) ->addEventSubscriber(new FixedFilterListener(array( 'preSubmit' => array( 'client' => 'filteredclient', ), 'onSubmit' => array( 'norm' => 'filterednorm', ), ))) ->addViewTransformer(new FixedDataTransformer(array( '' => '', // direction is reversed! 'norm' => 'filteredclient', 'filterednorm' => 'cleanedclient' ))) ->addModelTransformer(new FixedDataTransformer(array( '' => '', // direction is reversed! 'app' => 'filterednorm', ))) ->getForm(); $form->submit('client'); $this->assertEquals('app', $form->getData()); $this->assertEquals('filterednorm', $form->getNormData()); $this->assertEquals('cleanedclient', $form->getViewData()); } public function testSubmitExecutesViewTransformersInReverseOrder() { $form = $this->getBuilder() ->addViewTransformer(new FixedDataTransformer(array( '' => '', 'third' => 'second', ))) ->addViewTransformer(new FixedDataTransformer(array( '' => '', 'second' => 'first', ))) ->getForm(); $form->submit('first'); $this->assertEquals('third', $form->getNormData()); } public function testSubmitExecutesModelTransformersInOrder() { $form = $this->getBuilder() ->addModelTransformer(new FixedDataTransformer(array( '' => '', 'second' => 'first', ))) ->addModelTransformer(new FixedDataTransformer(array( '' => '', 'third' => 'second', ))) ->getForm(); $form->submit('first'); $this->assertEquals('third', $form->getData()); } public function testSynchronizedByDefault() { $this->assertTrue($this->form->isSynchronized()); } public function testSynchronizedAfterSubmission() { $this->form->submit('foobar'); $this->assertTrue($this->form->isSynchronized()); } public function testNotSynchronizedIfViewReverseTransformationFailed() { $transformer = $this->getDataTransformer(); $transformer->expects($this->once()) ->method('reverseTransform') ->will($this->throwException(new TransformationFailedException())); $form = $this->getBuilder() ->addViewTransformer($transformer) ->getForm(); $form->submit('foobar'); $this->assertFalse($form->isSynchronized()); } public function testNotSynchronizedIfModelReverseTransformationFailed() { $transformer = $this->getDataTransformer(); $transformer->expects($this->once()) ->method('reverseTransform') ->will($this->throwException(new TransformationFailedException())); $form = $this->getBuilder() ->addModelTransformer($transformer) ->getForm(); $form->submit('foobar'); $this->assertFalse($form->isSynchronized()); } public function testEmptyDataCreatedBeforeTransforming() { $form = $this->getBuilder() ->setEmptyData('foo') ->addViewTransformer(new FixedDataTransformer(array( '' => '', // direction is reversed! 'bar' => 'foo', ))) ->getForm(); $form->submit(''); $this->assertEquals('bar', $form->getData()); } public function testEmptyDataFromClosure() { $test = $this; $form = $this->getBuilder() ->setEmptyData(function ($form) use ($test) { // the form instance is passed to the closure to allow use // of form data when creating the empty value $test->assertInstanceOf('Symfony\Component\Form\FormInterface', $form); return 'foo'; }) ->addViewTransformer(new FixedDataTransformer(array( '' => '', // direction is reversed! 'bar' => 'foo', ))) ->getForm(); $form->submit(''); $this->assertEquals('bar', $form->getData()); } public function testSubmitResetsErrors() { $this->form->addError(new FormError('Error!')); $this->form->submit('foobar'); $this->assertSame(array(), $this->form->getErrors()); } public function testCreateView() { $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $view = $this->getMock('Symfony\Component\Form\FormView'); $form = $this->getBuilder()->setType($type)->getForm(); $type->expects($this->once()) ->method('createView') ->with($form) ->will($this->returnValue($view)); $this->assertSame($view, $form->createView()); } public function testCreateViewWithParent() { $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $view = $this->getMock('Symfony\Component\Form\FormView'); $parentForm = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $parentView = $this->getMock('Symfony\Component\Form\FormView'); $form = $this->getBuilder()->setType($type)->getForm(); $form->setParent($parentForm); $parentForm->expects($this->once()) ->method('createView') ->will($this->returnValue($parentView)); $type->expects($this->once()) ->method('createView') ->with($form, $parentView) ->will($this->returnValue($view)); $this->assertSame($view, $form->createView()); } public function testCreateViewWithExplicitParent() { $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $view = $this->getMock('Symfony\Component\Form\FormView'); $parentView = $this->getMock('Symfony\Component\Form\FormView'); $form = $this->getBuilder()->setType($type)->getForm(); $type->expects($this->once()) ->method('createView') ->with($form, $parentView) ->will($this->returnValue($view)); $this->assertSame($view, $form->createView($parentView)); } public function testGetErrorsAsString() { $this->form->addError(new FormError('Error!')); $this->assertEquals("ERROR: Error!\n", $this->form->getErrorsAsString()); } public function testFormCanHaveEmptyName() { $form = $this->getBuilder('')->getForm(); $this->assertEquals('', $form->getName()); } public function testSetNullParentWorksWithEmptyName() { $form = $this->getBuilder('')->getForm(); $form->setParent(null); $this->assertNull($form->getParent()); } /** * @expectedException \Symfony\Component\Form\Exception\LogicException * @expectedExceptionMessage A form with an empty name cannot have a parent form. */ public function testFormCannotHaveEmptyNameNotInRootLevel() { $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->add($this->getBuilder('')) ->getForm(); } public function testGetPropertyPathReturnsConfiguredPath() { $form = $this->getBuilder()->setPropertyPath('address.street')->getForm(); $this->assertEquals(new PropertyPath('address.street'), $form->getPropertyPath()); } // see https://github.com/symfony/symfony/issues/3903 public function testGetPropertyPathDefaultsToNameIfParentHasDataClass() { $parent = $this->getBuilder(null, null, 'stdClass') ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $form = $this->getBuilder('name')->getForm(); $parent->add($form); $this->assertEquals(new PropertyPath('name'), $form->getPropertyPath()); } // see https://github.com/symfony/symfony/issues/3903 public function testGetPropertyPathDefaultsToIndexedNameIfParentDataClassIsNull() { $parent = $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $form = $this->getBuilder('name')->getForm(); $parent->add($form); $this->assertEquals(new PropertyPath('[name]'), $form->getPropertyPath()); } public function testGetPropertyPathDefaultsToNameIfFirstParentWithoutInheritDataHasDataClass() { $grandParent = $this->getBuilder(null, null, 'stdClass') ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $parent = $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->setInheritData(true) ->getForm(); $form = $this->getBuilder('name')->getForm(); $grandParent->add($parent); $parent->add($form); $this->assertEquals(new PropertyPath('name'), $form->getPropertyPath()); } public function testGetPropertyPathDefaultsToIndexedNameIfDataClassOfFirstParentWithoutInheritDataIsNull() { $grandParent = $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $parent = $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->setInheritData(true) ->getForm(); $form = $this->getBuilder('name')->getForm(); $grandParent->add($parent); $parent->add($form); $this->assertEquals(new PropertyPath('[name]'), $form->getPropertyPath()); } /** * @expectedException \Symfony\Component\Form\Exception\LogicException */ public function testViewDataMustNotBeObjectIfDataClassIsNull() { $config = new FormConfigBuilder('name', null, $this->dispatcher); $config->addViewTransformer(new FixedDataTransformer(array( '' => '', 'foo' => new \stdClass(), ))); $form = new Form($config); $form->setData('foo'); } public function testViewDataMayBeArrayAccessIfDataClassIsNull() { $arrayAccess = $this->getMock('\ArrayAccess'); $config = new FormConfigBuilder('name', null, $this->dispatcher); $config->addViewTransformer(new FixedDataTransformer(array( '' => '', 'foo' => $arrayAccess, ))); $form = new Form($config); $form->setData('foo'); $this->assertSame($arrayAccess, $form->getViewData()); } /** * @expectedException \Symfony\Component\Form\Exception\LogicException */ public function testViewDataMustBeObjectIfDataClassIsSet() { $config = new FormConfigBuilder('name', 'stdClass', $this->dispatcher); $config->addViewTransformer(new FixedDataTransformer(array( '' => '', 'foo' => array('bar' => 'baz'), ))); $form = new Form($config); $form->setData('foo'); } /** * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testSetDataCannotInvokeItself() { // Cycle detection to prevent endless loops $config = new FormConfigBuilder('name', 'stdClass', $this->dispatcher); $config->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { $event->getForm()->setData('bar'); }); $form = new Form($config); $form->setData('foo'); } public function testSubmittingWrongDataIsIgnored() { $test = $this; $child = $this->getBuilder('child', $this->dispatcher); $child->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($test) { // child form doesn't receive the wrong data that is submitted on parent $test->assertNull($event->getData()); }); $parent = $this->getBuilder('parent', new EventDispatcher()) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->add($child) ->getForm(); $parent->submit('not-an-array'); } public function testHandleRequestForwardsToRequestHandler() { $handler = $this->getMock('Symfony\Component\Form\RequestHandlerInterface'); $form = $this->getBuilder() ->setRequestHandler($handler) ->getForm(); $handler->expects($this->once()) ->method('handleRequest') ->with($this->identicalTo($form), 'REQUEST'); $this->assertSame($form, $form->handleRequest('REQUEST')); } public function testFormInheritsParentData() { $child = $this->getBuilder('child') ->setInheritData(true); $parent = $this->getBuilder('parent') ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->setData('foo') ->addModelTransformer(new FixedDataTransformer(array( 'foo' => 'norm[foo]', ))) ->addViewTransformer(new FixedDataTransformer(array( 'norm[foo]' => 'view[foo]', ))) ->add($child) ->getForm(); $this->assertSame('foo', $parent->get('child')->getData()); $this->assertSame('norm[foo]', $parent->get('child')->getNormData()); $this->assertSame('view[foo]', $parent->get('child')->getViewData()); } /** * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testInheritDataDisallowsSetData() { $form = $this->getBuilder() ->setInheritData(true) ->getForm(); $form->setData('foo'); } /** * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testGetDataRequiresParentToBeSetIfInheritData() { $form = $this->getBuilder() ->setInheritData(true) ->getForm(); $form->getData(); } /** * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testGetNormDataRequiresParentToBeSetIfInheritData() { $form = $this->getBuilder() ->setInheritData(true) ->getForm(); $form->getNormData(); } /** * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testGetViewDataRequiresParentToBeSetIfInheritData() { $form = $this->getBuilder() ->setInheritData(true) ->getForm(); $form->getViewData(); } public function testPostSubmitDataIsNullIfInheritData() { $test = $this; $form = $this->getBuilder() ->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) use ($test) { $test->assertNull($event->getData()); }) ->setInheritData(true) ->getForm(); $form->submit('foo'); } public function testSubmitIsNeverFiredIfInheritData() { $test = $this; $form = $this->getBuilder() ->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) use ($test) { $test->fail('The SUBMIT event should not be fired'); }) ->setInheritData(true) ->getForm(); $form->submit('foo'); } public function testInitializeSetsDefaultData() { $config = $this->getBuilder()->setData('DEFAULT')->getFormConfig(); $form = $this->getMock('Symfony\Component\Form\Form', array('setData'), array($config)); $form->expects($this->once()) ->method('setData') ->with($this->identicalTo('DEFAULT')); /* @var Form $form */ $form->initialize(); } /** * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testInitializeFailsIfParent() { $parent = $this->getBuilder()->setRequired(false)->getForm(); $child = $this->getBuilder()->setRequired(true)->getForm(); $child->setParent($parent); $child->initialize(); } protected function createForm() { return $this->getBuilder()->getForm(); } } Symfony/Component/Form/Tests/FormFactoryTest.php000064400000051245152374770060016005 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\FormTypeGuesserChain; use Symfony\Component\Form\FormFactory; use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Form\Guess\ValueGuess; use Symfony\Component\Form\Guess\TypeGuess; use Symfony\Component\Form\Tests\Fixtures\Author; use Symfony\Component\Form\Tests\Fixtures\FooType; use Symfony\Component\Form\Tests\Fixtures\FooSubType; use Symfony\Component\Form\Tests\Fixtures\FooSubTypeWithParentInstance; /** * @author Bernhard Schussek */ class FormFactoryTest extends \PHPUnit_Framework_TestCase { /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $guesser1; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $guesser2; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $registry; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $resolvedTypeFactory; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $builder; /** * @var FormFactory */ private $factory; protected function setUp() { $this->resolvedTypeFactory = $this->getMock('Symfony\Component\Form\ResolvedFormTypeFactoryInterface'); $this->guesser1 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); $this->guesser2 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); $this->registry = $this->getMock('Symfony\Component\Form\FormRegistryInterface'); $this->builder = $this->getMock('Symfony\Component\Form\Test\FormBuilderInterface'); $this->factory = new FormFactory($this->registry, $this->resolvedTypeFactory); $this->registry->expects($this->any()) ->method('getTypeGuesser') ->will($this->returnValue(new FormTypeGuesserChain(array( $this->guesser1, $this->guesser2, )))); } public function testCreateNamedBuilderWithTypeName() { $options = array('a' => '1', 'b' => '2'); $resolvedOptions = array('a' => '2', 'b' => '3'); $resolvedType = $this->getMockResolvedType(); $this->registry->expects($this->once()) ->method('getType') ->with('type') ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'name', $options) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', 'type', null, $options)); } public function testCreateNamedBuilderWithTypeInstance() { $options = array('a' => '1', 'b' => '2'); $resolvedOptions = array('a' => '2', 'b' => '3'); $type = new FooType(); $resolvedType = $this->getMockResolvedType(); $this->resolvedTypeFactory->expects($this->once()) ->method('createResolvedType') ->with($type) ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'name', $options) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', $type, null, $options)); } public function testCreateNamedBuilderWithTypeInstanceWithParentType() { $options = array('a' => '1', 'b' => '2'); $resolvedOptions = array('a' => '2', 'b' => '3'); $type = new FooSubType(); $resolvedType = $this->getMockResolvedType(); $parentResolvedType = $this->getMockResolvedType(); $this->registry->expects($this->once()) ->method('getType') ->with('foo') ->will($this->returnValue($parentResolvedType)); $this->resolvedTypeFactory->expects($this->once()) ->method('createResolvedType') ->with($type, array(), $parentResolvedType) ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'name', $options) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', $type, null, $options)); } public function testCreateNamedBuilderWithTypeInstanceWithParentTypeInstance() { $options = array('a' => '1', 'b' => '2'); $resolvedOptions = array('a' => '2', 'b' => '3'); $type = new FooSubTypeWithParentInstance(); $resolvedType = $this->getMockResolvedType(); $parentResolvedType = $this->getMockResolvedType(); $this->resolvedTypeFactory->expects($this->at(0)) ->method('createResolvedType') ->with($type->getParent()) ->will($this->returnValue($parentResolvedType)); $this->resolvedTypeFactory->expects($this->at(1)) ->method('createResolvedType') ->with($type, array(), $parentResolvedType) ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'name', $options) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', $type, null, $options)); } public function testCreateNamedBuilderWithResolvedTypeInstance() { $options = array('a' => '1', 'b' => '2'); $resolvedOptions = array('a' => '2', 'b' => '3'); $resolvedType = $this->getMockResolvedType(); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'name', $options) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', $resolvedType, null, $options)); } public function testCreateNamedBuilderFillsDataOption() { $givenOptions = array('a' => '1', 'b' => '2'); $expectedOptions = array_merge($givenOptions, array('data' => 'DATA')); $resolvedOptions = array('a' => '2', 'b' => '3', 'data' => 'DATA'); $resolvedType = $this->getMockResolvedType(); $this->registry->expects($this->once()) ->method('getType') ->with('type') ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'name', $expectedOptions) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', 'type', 'DATA', $givenOptions)); } public function testCreateNamedBuilderDoesNotOverrideExistingDataOption() { $options = array('a' => '1', 'b' => '2', 'data' => 'CUSTOM'); $resolvedOptions = array('a' => '2', 'b' => '3', 'data' => 'CUSTOM'); $resolvedType = $this->getMockResolvedType(); $this->registry->expects($this->once()) ->method('getType') ->with('type') ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'name', $options) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->assertSame($this->builder, $this->factory->createNamedBuilder('name', 'type', 'DATA', $options)); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException * @expectedExceptionMessage Expected argument of type "string, Symfony\Component\Form\ResolvedFormTypeInterface or Symfony\Component\Form\FormTypeInterface", "stdClass" given */ public function testCreateNamedBuilderThrowsUnderstandableException() { $this->factory->createNamedBuilder('name', new \stdClass()); } public function testCreateUsesTypeNameIfTypeGivenAsString() { $options = array('a' => '1', 'b' => '2'); $resolvedOptions = array('a' => '2', 'b' => '3'); $resolvedType = $this->getMockResolvedType(); $this->registry->expects($this->once()) ->method('getType') ->with('TYPE') ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'TYPE', $options) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->builder->expects($this->once()) ->method('getForm') ->will($this->returnValue('FORM')); $this->assertSame('FORM', $this->factory->create('TYPE', null, $options)); } public function testCreateUsesTypeNameIfTypeGivenAsObject() { $options = array('a' => '1', 'b' => '2'); $resolvedOptions = array('a' => '2', 'b' => '3'); $resolvedType = $this->getMockResolvedType(); $resolvedType->expects($this->once()) ->method('getName') ->will($this->returnValue('TYPE')); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'TYPE', $options) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->builder->expects($this->once()) ->method('getForm') ->will($this->returnValue('FORM')); $this->assertSame('FORM', $this->factory->create($resolvedType, null, $options)); } public function testCreateNamed() { $options = array('a' => '1', 'b' => '2'); $resolvedOptions = array('a' => '2', 'b' => '3'); $resolvedType = $this->getMockResolvedType(); $this->registry->expects($this->once()) ->method('getType') ->with('type') ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->once()) ->method('createBuilder') ->with($this->factory, 'name', $options) ->will($this->returnValue($this->builder)); $this->builder->expects($this->any()) ->method('getOptions') ->will($this->returnValue($resolvedOptions)); $resolvedType->expects($this->once()) ->method('buildForm') ->with($this->builder, $resolvedOptions); $this->builder->expects($this->once()) ->method('getForm') ->will($this->returnValue('FORM')); $this->assertSame('FORM', $this->factory->createNamed('name', 'type', null, $options)); } public function testCreateBuilderForPropertyWithoutTypeGuesser() { $registry = $this->getMock('Symfony\Component\Form\FormRegistryInterface'); $factory = $this->getMockBuilder('Symfony\Component\Form\FormFactory') ->setMethods(array('createNamedBuilder')) ->setConstructorArgs(array($registry, $this->resolvedTypeFactory)) ->getMock(); $factory->expects($this->once()) ->method('createNamedBuilder') ->with('firstName', 'text', null, array()) ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty('Application\Author', 'firstName'); $this->assertEquals('builderInstance', $this->builder); } public function testCreateBuilderForPropertyCreatesFormWithHighestConfidence() { $this->guesser1->expects($this->once()) ->method('guessType') ->with('Application\Author', 'firstName') ->will($this->returnValue(new TypeGuess( 'text', array('max_length' => 10), Guess::MEDIUM_CONFIDENCE ))); $this->guesser2->expects($this->once()) ->method('guessType') ->with('Application\Author', 'firstName') ->will($this->returnValue(new TypeGuess( 'password', array('max_length' => 7), Guess::HIGH_CONFIDENCE ))); $factory = $this->getMockFactory(array('createNamedBuilder')); $factory->expects($this->once()) ->method('createNamedBuilder') ->with('firstName', 'password', null, array('max_length' => 7)) ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty('Application\Author', 'firstName'); $this->assertEquals('builderInstance', $this->builder); } public function testCreateBuilderCreatesTextFormIfNoGuess() { $this->guesser1->expects($this->once()) ->method('guessType') ->with('Application\Author', 'firstName') ->will($this->returnValue(null)); $factory = $this->getMockFactory(array('createNamedBuilder')); $factory->expects($this->once()) ->method('createNamedBuilder') ->with('firstName', 'text') ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty('Application\Author', 'firstName'); $this->assertEquals('builderInstance', $this->builder); } public function testOptionsCanBeOverridden() { $this->guesser1->expects($this->once()) ->method('guessType') ->with('Application\Author', 'firstName') ->will($this->returnValue(new TypeGuess( 'text', array('max_length' => 10), Guess::MEDIUM_CONFIDENCE ))); $factory = $this->getMockFactory(array('createNamedBuilder')); $factory->expects($this->once()) ->method('createNamedBuilder') ->with('firstName', 'text', null, array('max_length' => 11)) ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty( 'Application\Author', 'firstName', null, array('max_length' => 11) ); $this->assertEquals('builderInstance', $this->builder); } public function testCreateBuilderUsesMaxLengthIfFound() { $this->guesser1->expects($this->once()) ->method('guessMaxLength') ->with('Application\Author', 'firstName') ->will($this->returnValue(new ValueGuess( 15, Guess::MEDIUM_CONFIDENCE ))); $this->guesser2->expects($this->once()) ->method('guessMaxLength') ->with('Application\Author', 'firstName') ->will($this->returnValue(new ValueGuess( 20, Guess::HIGH_CONFIDENCE ))); $factory = $this->getMockFactory(array('createNamedBuilder')); $factory->expects($this->once()) ->method('createNamedBuilder') ->with('firstName', 'text', null, array('max_length' => 20)) ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty( 'Application\Author', 'firstName' ); $this->assertEquals('builderInstance', $this->builder); } public function testCreateBuilderUsesRequiredSettingWithHighestConfidence() { $this->guesser1->expects($this->once()) ->method('guessRequired') ->with('Application\Author', 'firstName') ->will($this->returnValue(new ValueGuess( true, Guess::MEDIUM_CONFIDENCE ))); $this->guesser2->expects($this->once()) ->method('guessRequired') ->with('Application\Author', 'firstName') ->will($this->returnValue(new ValueGuess( false, Guess::HIGH_CONFIDENCE ))); $factory = $this->getMockFactory(array('createNamedBuilder')); $factory->expects($this->once()) ->method('createNamedBuilder') ->with('firstName', 'text', null, array('required' => false)) ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty( 'Application\Author', 'firstName' ); $this->assertEquals('builderInstance', $this->builder); } public function testCreateBuilderUsesPatternIfFound() { $this->guesser1->expects($this->once()) ->method('guessPattern') ->with('Application\Author', 'firstName') ->will($this->returnValue(new ValueGuess( '[a-z]', Guess::MEDIUM_CONFIDENCE ))); $this->guesser2->expects($this->once()) ->method('guessPattern') ->with('Application\Author', 'firstName') ->will($this->returnValue(new ValueGuess( '[a-zA-Z]', Guess::HIGH_CONFIDENCE ))); $factory = $this->getMockFactory(array('createNamedBuilder')); $factory->expects($this->once()) ->method('createNamedBuilder') ->with('firstName', 'text', null, array('pattern' => '[a-zA-Z]')) ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty( 'Application\Author', 'firstName' ); $this->assertEquals('builderInstance', $this->builder); } private function getMockFactory(array $methods = array()) { return $this->getMockBuilder('Symfony\Component\Form\FormFactory') ->setMethods($methods) ->setConstructorArgs(array($this->registry, $this->resolvedTypeFactory)) ->getMock(); } private function getMockResolvedType() { return $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); } private function getMockType() { return $this->getMock('Symfony\Component\Form\FormTypeInterface'); } } Symfony/Component/Form/Tests/CompoundFormTest.php000064400000075156152374770060016171 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; use Symfony\Component\Form\FormError; use Symfony\Component\Form\Forms; use Symfony\Component\Form\FormView; use Symfony\Component\Form\SubmitButtonBuilder; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; class CompoundFormTest extends AbstractFormTest { public function testValidIfAllChildrenAreValid() { $this->form->add($this->getBuilder('firstName')->getForm()); $this->form->add($this->getBuilder('lastName')->getForm()); $this->form->submit(array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', )); $this->assertTrue($this->form->isValid()); } public function testInvalidIfChildIsInvalid() { $this->form->add($this->getBuilder('firstName')->getForm()); $this->form->add($this->getBuilder('lastName')->getForm()); $this->form->submit(array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', )); $this->form->get('lastName')->addError(new FormError('Invalid')); $this->assertFalse($this->form->isValid()); } public function testValidIfChildIsNotSubmitted() { $this->form->add($this->getBuilder('firstName')->getForm()); $this->form->add($this->getBuilder('lastName')->getForm()); $this->form->submit(array( 'firstName' => 'Bernhard', )); // "lastName" is not "valid" because it was not submitted. This happens // for example in PATCH requests. The parent form should still be // considered valid. $this->assertTrue($this->form->isValid()); } public function testDisabledFormsValidEvenIfChildrenInvalid() { $form = $this->getBuilder('person') ->setDisabled(true) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->add($this->getBuilder('name')) ->getForm(); $form->submit(array('name' => 'Jacques Doe')); $form->get('name')->addError(new FormError('Invalid')); $this->assertTrue($form->isValid()); } public function testSubmitForwardsNullIfNotClearMissingButValueIsExplicitlyNull() { $child = $this->getMockForm('firstName'); $this->form->add($child); $child->expects($this->once()) ->method('submit') ->with($this->equalTo(null)); $this->form->submit(array('firstName' => null), false); } public function testSubmitForwardsNullIfValueIsMissing() { $child = $this->getMockForm('firstName'); $this->form->add($child); $child->expects($this->once()) ->method('submit') ->with($this->equalTo(null)); $this->form->submit(array()); } public function testSubmitDoesNotForwardNullIfNotClearMissing() { $child = $this->getMockForm('firstName'); $this->form->add($child); $child->expects($this->never()) ->method('submit'); $this->form->submit(array(), false); } public function testSubmitDoesNotAddExtraFieldForNullValues() { $factory = Forms::createFormFactoryBuilder() ->getFormFactory(); $child = $factory->create('file', null, array('auto_initialize' => false)); $this->form->add($child); $this->form->submit(array('file' => null), false); $this->assertCount(0, $this->form->getExtraData()); } public function testClearMissingFlagIsForwarded() { $child = $this->getMockForm('firstName'); $this->form->add($child); $child->expects($this->once()) ->method('submit') ->with($this->equalTo('foo'), false); $this->form->submit(array('firstName' => 'foo'), false); } public function testCloneChildren() { $child = $this->getBuilder('child')->getForm(); $this->form->add($child); $clone = clone $this->form; $this->assertNotSame($this->form, $clone); $this->assertNotSame($child, $clone['child']); $this->assertNotSame($this->form['child'], $clone['child']); } public function testNotEmptyIfChildNotEmpty() { $child = $this->getMockForm(); $child->expects($this->once()) ->method('isEmpty') ->will($this->returnValue(false)); $this->form->setData(null); $this->form->add($child); $this->assertFalse($this->form->isEmpty()); } public function testAdd() { $child = $this->getBuilder('foo')->getForm(); $this->form->add($child); $this->assertTrue($this->form->has('foo')); $this->assertSame($this->form, $child->getParent()); $this->assertSame(array('foo' => $child), $this->form->all()); } public function testAddUsingNameAndType() { $child = $this->getBuilder('foo')->getForm(); $this->factory->expects($this->once()) ->method('createNamed') ->with('foo', 'text', null, array( 'bar' => 'baz', 'auto_initialize' => false, )) ->will($this->returnValue($child)); $this->form->add('foo', 'text', array('bar' => 'baz')); $this->assertTrue($this->form->has('foo')); $this->assertSame($this->form, $child->getParent()); $this->assertSame(array('foo' => $child), $this->form->all()); } public function testAddUsingIntegerNameAndType() { $child = $this->getBuilder(0)->getForm(); $this->factory->expects($this->once()) ->method('createNamed') ->with('0', 'text', null, array( 'bar' => 'baz', 'auto_initialize' => false, )) ->will($this->returnValue($child)); // in order to make casting unnecessary $this->form->add(0, 'text', array('bar' => 'baz')); $this->assertTrue($this->form->has(0)); $this->assertSame($this->form, $child->getParent()); $this->assertSame(array(0 => $child), $this->form->all()); } public function testAddUsingNameButNoType() { $this->form = $this->getBuilder('name', null, '\stdClass') ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $child = $this->getBuilder('foo')->getForm(); $this->factory->expects($this->once()) ->method('createForProperty') ->with('\stdClass', 'foo') ->will($this->returnValue($child)); $this->form->add('foo'); $this->assertTrue($this->form->has('foo')); $this->assertSame($this->form, $child->getParent()); $this->assertSame(array('foo' => $child), $this->form->all()); } public function testAddUsingNameButNoTypeAndOptions() { $this->form = $this->getBuilder('name', null, '\stdClass') ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $child = $this->getBuilder('foo')->getForm(); $this->factory->expects($this->once()) ->method('createForProperty') ->with('\stdClass', 'foo', null, array( 'bar' => 'baz', 'auto_initialize' => false, )) ->will($this->returnValue($child)); $this->form->add('foo', null, array('bar' => 'baz')); $this->assertTrue($this->form->has('foo')); $this->assertSame($this->form, $child->getParent()); $this->assertSame(array('foo' => $child), $this->form->all()); } /** * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException */ public function testAddThrowsExceptionIfAlreadySubmitted() { $this->form->submit(array()); $this->form->add($this->getBuilder('foo')->getForm()); } public function testRemove() { $child = $this->getBuilder('foo')->getForm(); $this->form->add($child); $this->form->remove('foo'); $this->assertNull($child->getParent()); $this->assertCount(0, $this->form); } /** * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException */ public function testRemoveThrowsExceptionIfAlreadySubmitted() { $this->form->add($this->getBuilder('foo')->setCompound(false)->getForm()); $this->form->submit(array('foo' => 'bar')); $this->form->remove('foo'); } public function testRemoveIgnoresUnknownName() { $this->form->remove('notexisting'); } public function testArrayAccess() { $child = $this->getBuilder('foo')->getForm(); $this->form[] = $child; $this->assertTrue(isset($this->form['foo'])); $this->assertSame($child, $this->form['foo']); unset($this->form['foo']); $this->assertFalse(isset($this->form['foo'])); } public function testCountable() { $this->form->add($this->getBuilder('foo')->getForm()); $this->form->add($this->getBuilder('bar')->getForm()); $this->assertCount(2, $this->form); } public function testIterator() { $this->form->add($this->getBuilder('foo')->getForm()); $this->form->add($this->getBuilder('bar')->getForm()); $this->assertSame($this->form->all(), iterator_to_array($this->form)); } public function testAddMapsViewDataToFormIfInitialized() { $test = $this; $mapper = $this->getDataMapper(); $form = $this->getBuilder() ->setCompound(true) ->setDataMapper($mapper) ->addViewTransformer(new FixedDataTransformer(array( '' => '', 'foo' => 'bar', ))) ->setData('foo') ->getForm(); $child = $this->getBuilder()->getForm(); $mapper->expects($this->once()) ->method('mapDataToForms') ->with('bar', $this->isInstanceOf('\RecursiveIteratorIterator')) ->will($this->returnCallback(function ($data, \RecursiveIteratorIterator $iterator) use ($child, $test) { $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator()); $test->assertSame(array($child), iterator_to_array($iterator)); })); $form->initialize(); $form->add($child); } public function testAddDoesNotMapViewDataToFormIfNotInitialized() { $mapper = $this->getDataMapper(); $form = $this->getBuilder() ->setCompound(true) ->setDataMapper($mapper) ->getForm(); $child = $this->getBuilder()->getForm(); $mapper->expects($this->never()) ->method('mapDataToForms'); $form->add($child); } public function testAddDoesNotMapViewDataToFormIfInheritData() { $mapper = $this->getDataMapper(); $form = $this->getBuilder() ->setCompound(true) ->setDataMapper($mapper) ->setInheritData(true) ->getForm(); $child = $this->getBuilder()->getForm(); $mapper->expects($this->never()) ->method('mapDataToForms'); $form->initialize(); $form->add($child); } public function testSetDataSupportsDynamicAdditionAndRemovalOfChildren() { $form = $this->getBuilder() ->setCompound(true) // We test using PropertyPathMapper on purpose. The traversal logic // is currently contained in InheritDataAwareIterator, but even // if that changes, this test should still function. ->setDataMapper(new PropertyPathMapper()) ->getForm(); $child = $this->getMockForm('child'); $childToBeRemoved = $this->getMockForm('removed'); $childToBeAdded = $this->getMockForm('added'); $form->add($child); $form->add($childToBeRemoved); $child->expects($this->once()) ->method('setData') ->will($this->returnCallback(function () use ($form, $childToBeAdded) { $form->remove('removed'); $form->add($childToBeAdded); })); $childToBeRemoved->expects($this->never()) ->method('setData'); // once when it it is created, once when it is added $childToBeAdded->expects($this->exactly(2)) ->method('setData'); // pass NULL to all children $form->setData(array()); } public function testSetDataMapsViewDataToChildren() { $test = $this; $mapper = $this->getDataMapper(); $form = $this->getBuilder() ->setCompound(true) ->setDataMapper($mapper) ->addViewTransformer(new FixedDataTransformer(array( '' => '', 'foo' => 'bar', ))) ->getForm(); $form->add($child1 = $this->getBuilder('firstName')->getForm()); $form->add($child2 = $this->getBuilder('lastName')->getForm()); $mapper->expects($this->once()) ->method('mapDataToForms') ->with('bar', $this->isInstanceOf('\RecursiveIteratorIterator')) ->will($this->returnCallback(function ($data, \RecursiveIteratorIterator $iterator) use ($child1, $child2, $test) { $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator()); $test->assertSame(array('firstName' => $child1, 'lastName' => $child2), iterator_to_array($iterator)); })); $form->setData('foo'); } public function testSubmitSupportsDynamicAdditionAndRemovalOfChildren() { $child = $this->getMockForm('child'); $childToBeRemoved = $this->getMockForm('removed'); $childToBeAdded = $this->getMockForm('added'); $this->form->add($child); $this->form->add($childToBeRemoved); $form = $this->form; $child->expects($this->once()) ->method('submit') ->will($this->returnCallback(function () use ($form, $childToBeAdded) { $form->remove('removed'); $form->add($childToBeAdded); })); $childToBeRemoved->expects($this->never()) ->method('submit'); $childToBeAdded->expects($this->once()) ->method('submit'); // pass NULL to all children $this->form->submit(array()); } public function testSubmitMapsSubmittedChildrenOntoExistingViewData() { $test = $this; $mapper = $this->getDataMapper(); $form = $this->getBuilder() ->setCompound(true) ->setDataMapper($mapper) ->addViewTransformer(new FixedDataTransformer(array( '' => '', 'foo' => 'bar', ))) ->setData('foo') ->getForm(); $form->add($child1 = $this->getBuilder('firstName')->setCompound(false)->getForm()); $form->add($child2 = $this->getBuilder('lastName')->setCompound(false)->getForm()); $mapper->expects($this->once()) ->method('mapFormsToData') ->with($this->isInstanceOf('\RecursiveIteratorIterator'), 'bar') ->will($this->returnCallback(function (\RecursiveIteratorIterator $iterator) use ($child1, $child2, $test) { $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator()); $test->assertSame(array('firstName' => $child1, 'lastName' => $child2), iterator_to_array($iterator)); $test->assertEquals('Bernhard', $child1->getData()); $test->assertEquals('Schussek', $child2->getData()); })); $form->submit(array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', )); } public function testMapFormsToDataIsNotInvokedIfInheritData() { $mapper = $this->getDataMapper(); $form = $this->getBuilder() ->setCompound(true) ->setDataMapper($mapper) ->setInheritData(true) ->addViewTransformer(new FixedDataTransformer(array( '' => '', 'foo' => 'bar', ))) ->getForm(); $form->add($child1 = $this->getBuilder('firstName')->setCompound(false)->getForm()); $form->add($child2 = $this->getBuilder('lastName')->setCompound(false)->getForm()); $mapper->expects($this->never()) ->method('mapFormsToData'); $form->submit(array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', )); } /* * https://github.com/symfony/symfony/issues/4480 */ public function testSubmitRestoresViewDataIfCompoundAndEmpty() { $mapper = $this->getDataMapper(); $object = new \stdClass(); $form = $this->getBuilder('name', null, 'stdClass') ->setCompound(true) ->setDataMapper($mapper) ->setData($object) ->getForm(); $form->submit(array()); $this->assertSame($object, $form->getData()); } public function testSubmitMapsSubmittedChildrenOntoEmptyData() { $test = $this; $mapper = $this->getDataMapper(); $object = new \stdClass(); $form = $this->getBuilder() ->setCompound(true) ->setDataMapper($mapper) ->setEmptyData($object) ->setData(null) ->getForm(); $form->add($child = $this->getBuilder('name')->setCompound(false)->getForm()); $mapper->expects($this->once()) ->method('mapFormsToData') ->with($this->isInstanceOf('\RecursiveIteratorIterator'), $object) ->will($this->returnCallback(function (\RecursiveIteratorIterator $iterator) use ($child, $test) { $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator()); $test->assertSame(array('name' => $child), iterator_to_array($iterator)); })); $form->submit(array( 'name' => 'Bernhard', )); } public function requestMethodProvider() { return array( array('POST'), array('PUT'), array('DELETE'), array('PATCH'), ); } /** * @dataProvider requestMethodProvider */ public function testSubmitPostOrPutRequest($method) { $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); $values = array( 'author' => array( 'name' => 'Bernhard', 'image' => array('filename' => 'foobar.png'), ), ); $files = array( 'author' => array( 'error' => array('image' => UPLOAD_ERR_OK), 'name' => array('image' => 'upload.png'), 'size' => array('image' => 123), 'tmp_name' => array('image' => $path), 'type' => array('image' => 'image/png'), ), ); $request = new Request(array(), $values, array(), array(), $files, array( 'REQUEST_METHOD' => $method, )); $form = $this->getBuilder('author') ->setMethod($method) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->setRequestHandler(new HttpFoundationRequestHandler()) ->getForm(); $form->add($this->getBuilder('name')->getForm()); $form->add($this->getBuilder('image')->getForm()); $form->handleRequest($request); $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); $this->assertEquals('Bernhard', $form['name']->getData()); $this->assertEquals($file, $form['image']->getData()); unlink($path); } /** * @dataProvider requestMethodProvider */ public function testSubmitPostOrPutRequestWithEmptyRootFormName($method) { $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); $values = array( 'name' => 'Bernhard', 'extra' => 'data', ); $files = array( 'image' => array( 'error' => UPLOAD_ERR_OK, 'name' => 'upload.png', 'size' => 123, 'tmp_name' => $path, 'type' => 'image/png', ), ); $request = new Request(array(), $values, array(), array(), $files, array( 'REQUEST_METHOD' => $method, )); $form = $this->getBuilder('') ->setMethod($method) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->setRequestHandler(new HttpFoundationRequestHandler()) ->getForm(); $form->add($this->getBuilder('name')->getForm()); $form->add($this->getBuilder('image')->getForm()); $form->handleRequest($request); $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); $this->assertEquals('Bernhard', $form['name']->getData()); $this->assertEquals($file, $form['image']->getData()); $this->assertEquals(array('extra' => 'data'), $form->getExtraData()); unlink($path); } /** * @dataProvider requestMethodProvider */ public function testSubmitPostOrPutRequestWithSingleChildForm($method) { $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); $files = array( 'image' => array( 'error' => UPLOAD_ERR_OK, 'name' => 'upload.png', 'size' => 123, 'tmp_name' => $path, 'type' => 'image/png', ), ); $request = new Request(array(), array(), array(), array(), $files, array( 'REQUEST_METHOD' => $method, )); $form = $this->getBuilder('image') ->setMethod($method) ->setRequestHandler(new HttpFoundationRequestHandler()) ->getForm(); $form->handleRequest($request); $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); $this->assertEquals($file, $form->getData()); unlink($path); } /** * @dataProvider requestMethodProvider */ public function testSubmitPostOrPutRequestWithSingleChildFormUploadedFile($method) { $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); $values = array( 'name' => 'Bernhard', ); $request = new Request(array(), $values, array(), array(), array(), array( 'REQUEST_METHOD' => $method, )); $form = $this->getBuilder('name') ->setMethod($method) ->setRequestHandler(new HttpFoundationRequestHandler()) ->getForm(); $form->handleRequest($request); $this->assertEquals('Bernhard', $form->getData()); unlink($path); } public function testSubmitGetRequest() { $values = array( 'author' => array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', ), ); $request = new Request($values, array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', )); $form = $this->getBuilder('author') ->setMethod('GET') ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->setRequestHandler(new HttpFoundationRequestHandler()) ->getForm(); $form->add($this->getBuilder('firstName')->getForm()); $form->add($this->getBuilder('lastName')->getForm()); $form->handleRequest($request); $this->assertEquals('Bernhard', $form['firstName']->getData()); $this->assertEquals('Schussek', $form['lastName']->getData()); } public function testSubmitGetRequestWithEmptyRootFormName() { $values = array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', 'extra' => 'data' ); $request = new Request($values, array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', )); $form = $this->getBuilder('') ->setMethod('GET') ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->setRequestHandler(new HttpFoundationRequestHandler()) ->getForm(); $form->add($this->getBuilder('firstName')->getForm()); $form->add($this->getBuilder('lastName')->getForm()); $form->handleRequest($request); $this->assertEquals('Bernhard', $form['firstName']->getData()); $this->assertEquals('Schussek', $form['lastName']->getData()); $this->assertEquals(array('extra' => 'data'), $form->getExtraData()); } public function testGetErrorsAsStringDeep() { $parent = $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $this->form->addError(new FormError('Error!')); $parent->add($this->form); $parent->add($this->getBuilder('foo')->getForm()); $this->assertEquals("name:\n ERROR: Error!\nfoo:\n No errors\n", $parent->getErrorsAsString()); } // Basic cases are covered in SimpleFormTest public function testCreateViewWithChildren() { $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $options = array('a' => 'Foo', 'b' => 'Bar'); $field1 = $this->getMockForm('foo'); $field2 = $this->getMockForm('bar'); $view = new FormView(); $field1View = new FormView(); $field2View = new FormView(); $this->form = $this->getBuilder('form', null, null, $options) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->setType($type) ->getForm(); $this->form->add($field1); $this->form->add($field2); $test = $this; $assertChildViewsEqual = function (array $childViews) use ($test) { return function (FormView $view) use ($test, $childViews) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertSame($childViews, $view->children); }; }; // First create the view $type->expects($this->once()) ->method('createView') ->will($this->returnValue($view)); // Then build it for the form itself $type->expects($this->once()) ->method('buildView') ->with($view, $this->form, $options) ->will($this->returnCallback($assertChildViewsEqual(array()))); // Then add the first child form $field1->expects($this->once()) ->method('createView') ->will($this->returnValue($field1View)); // Then the second child form $field2->expects($this->once()) ->method('createView') ->will($this->returnValue($field2View)); // Again build the view for the form itself. This time the child views // exist. $type->expects($this->once()) ->method('finishView') ->with($view, $this->form, $options) ->will($this->returnCallback($assertChildViewsEqual(array('foo' => $field1View, 'bar' => $field2View)))); $this->assertSame($view, $this->form->createView()); } public function testNoClickedButtonBeforeSubmission() { $this->assertNull($this->form->getClickedButton()); } public function testNoClickedButton() { $button = $this->getMockBuilder('Symfony\Component\Form\SubmitButton') ->setConstructorArgs(array(new SubmitButtonBuilder('submit'))) ->setMethods(array('isClicked')) ->getMock(); $button->expects($this->any()) ->method('isClicked') ->will($this->returnValue(false)); $parentForm = $this->getBuilder('parent')->getForm(); $nestedForm = $this->getBuilder('nested')->getForm(); $this->form->setParent($parentForm); $this->form->add($button); $this->form->add($nestedForm); $this->form->submit(array()); $this->assertNull($this->form->getClickedButton()); } public function testClickedButton() { $button = $this->getMockBuilder('Symfony\Component\Form\SubmitButton') ->setConstructorArgs(array(new SubmitButtonBuilder('submit'))) ->setMethods(array('isClicked')) ->getMock(); $button->expects($this->any()) ->method('isClicked') ->will($this->returnValue(true)); $this->form->add($button); $this->form->submit(array()); $this->assertSame($button, $this->form->getClickedButton()); } public function testClickedButtonFromNestedForm() { $button = $this->getBuilder('submit')->getForm(); $nestedForm = $this->getMockBuilder('Symfony\Component\Form\Form') ->setConstructorArgs(array($this->getBuilder('nested'))) ->setMethods(array('getClickedButton')) ->getMock(); $nestedForm->expects($this->any()) ->method('getClickedButton') ->will($this->returnValue($button)); $this->form->add($nestedForm); $this->form->submit(array()); $this->assertSame($button, $this->form->getClickedButton()); } public function testClickedButtonFromParentForm() { $button = $this->getBuilder('submit')->getForm(); $parentForm = $this->getMockBuilder('Symfony\Component\Form\Form') ->setConstructorArgs(array($this->getBuilder('parent'))) ->setMethods(array('getClickedButton')) ->getMock(); $parentForm->expects($this->any()) ->method('getClickedButton') ->will($this->returnValue($button)); $this->form->setParent($parentForm); $this->form->submit(array()); $this->assertSame($button, $this->form->getClickedButton()); } protected function createForm() { return $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); } } Symfony/Component/Form/Tests/NativeRequestHandlerTest.php000064400000013441152374770060017643 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\NativeRequestHandler; /** * @author Bernhard Schussek */ class NativeRequestHandlerTest extends AbstractRequestHandlerTest { private static $serverBackup; public static function setUpBeforeClass() { self::$serverBackup = $_SERVER; } protected function setUp() { parent::setUp(); $_GET = array(); $_POST = array(); $_FILES = array(); $_SERVER = array( // PHPUnit needs this entry 'SCRIPT_NAME' => self::$serverBackup['SCRIPT_NAME'], ); } protected function tearDown() { parent::tearDown(); $_GET = array(); $_POST = array(); $_FILES = array(); $_SERVER = self::$serverBackup; } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testRequestShouldBeNull() { $this->requestHandler->handleRequest($this->getMockForm('name', 'GET'), 'request'); } public function testMethodOverrideHeaderTakesPrecedenceIfPost() { $form = $this->getMockForm('param1', 'PUT'); $this->setRequestData('POST', array( 'param1' => 'DATA', )); $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT'; $form->expects($this->once()) ->method('submit') ->with('DATA'); $this->requestHandler->handleRequest($form, $this->request); } public function testConvertEmptyUploadedFilesToNull() { $form = $this->getMockForm('param1', 'POST', false); $this->setRequestData('POST', array(), array('param1' => array( 'name' => '', 'type' => '', 'tmp_name' => '', 'error' => UPLOAD_ERR_NO_FILE, 'size' => 0 ))); $form->expects($this->once()) ->method('submit') ->with($this->identicalTo(null)); $this->requestHandler->handleRequest($form, $this->request); } public function testFixBuggyFilesArray() { $form = $this->getMockForm('param1', 'POST', false); $this->setRequestData('POST', array(), array('param1' => array( 'name' => array( 'field' => 'upload.txt', ), 'type' => array( 'field' => 'text/plain', ), 'tmp_name' => array( 'field' => 'owfdskjasdfsa', ), 'error' => array( 'field' => UPLOAD_ERR_OK, ), 'size' => array( 'field' => 100, ), ))); $form->expects($this->once()) ->method('submit') ->with(array( 'field' => array( 'name' => 'upload.txt', 'type' => 'text/plain', 'tmp_name' => 'owfdskjasdfsa', 'error' => UPLOAD_ERR_OK, 'size' => 100, ), )); $this->requestHandler->handleRequest($form, $this->request); } public function testFixBuggyNestedFilesArray() { $form = $this->getMockForm('param1', 'POST'); $this->setRequestData('POST', array(), array('param1' => array( 'name' => array( 'field' => array('subfield' => 'upload.txt'), ), 'type' => array( 'field' => array('subfield' => 'text/plain'), ), 'tmp_name' => array( 'field' => array('subfield' => 'owfdskjasdfsa'), ), 'error' => array( 'field' => array('subfield' => UPLOAD_ERR_OK), ), 'size' => array( 'field' => array('subfield' => 100), ), ))); $form->expects($this->once()) ->method('submit') ->with(array( 'field' => array( 'subfield' => array( 'name' => 'upload.txt', 'type' => 'text/plain', 'tmp_name' => 'owfdskjasdfsa', 'error' => UPLOAD_ERR_OK, 'size' => 100, ), ), )); $this->requestHandler->handleRequest($form, $this->request); } public function testMethodOverrideHeaderIgnoredIfNotPost() { $form = $this->getMockForm('param1', 'POST'); $this->setRequestData('GET', array( 'param1' => 'DATA', )); $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT'; $form->expects($this->never()) ->method('submit'); $this->requestHandler->handleRequest($form, $this->request); } protected function setRequestData($method, $data, $files = array()) { if ('GET' === $method) { $_GET = $data; $_FILES = array(); } else { $_POST = $data; $_FILES = $files; } $_SERVER = array( 'REQUEST_METHOD' => $method, // PHPUnit needs this entry 'SCRIPT_NAME' => self::$serverBackup['SCRIPT_NAME'], ); } protected function getRequestHandler() { return new NativeRequestHandler(); } protected function getMockFile() { return array( 'name' => 'upload.txt', 'type' => 'text/plain', 'tmp_name' => 'owfdskjasdfsa', 'error' => UPLOAD_ERR_OK, 'size' => 100, ); } } Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php000064400000027347152374770060023632 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Csrf\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormError; use Symfony\Component\Form\Test\TypeTestCase; use Symfony\Component\Form\Extension\Csrf\CsrfExtension; use Symfony\Component\Security\Csrf\CsrfToken; class FormTypeCsrfExtensionTest_ChildType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { // The form needs a child in order to trigger CSRF protection by // default $builder->add('name', 'text'); } public function getName() { return 'csrf_collection_test'; } } class FormTypeCsrfExtensionTest extends TypeTestCase { /** * @var \PHPUnit_Framework_MockObject_MockObject */ protected $tokenManager; /** * @var \PHPUnit_Framework_MockObject_MockObject */ protected $translator; protected function setUp() { $this->tokenManager = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface'); $this->translator = $this->getMock('Symfony\Component\Translation\TranslatorInterface'); parent::setUp(); } protected function tearDown() { $this->tokenManager = null; $this->translator = null; parent::tearDown(); } protected function getExtensions() { return array_merge(parent::getExtensions(), array( new CsrfExtension($this->tokenManager, $this->translator), )); } public function testCsrfProtectionByDefaultIfRootAndCompound() { $view = $this->factory ->create('form', null, array( 'csrf_field_name' => 'csrf', 'compound' => true, )) ->createView(); $this->assertTrue(isset($view['csrf'])); } public function testNoCsrfProtectionByDefaultIfCompoundButNotRoot() { $view = $this->factory ->createNamedBuilder('root', 'form') ->add($this->factory ->createNamedBuilder('form', 'form', null, array( 'csrf_field_name' => 'csrf', 'compound' => true, )) ) ->getForm() ->get('form') ->createView(); $this->assertFalse(isset($view['csrf'])); } public function testNoCsrfProtectionByDefaultIfRootButNotCompound() { $view = $this->factory ->create('form', null, array( 'csrf_field_name' => 'csrf', 'compound' => false, )) ->createView(); $this->assertFalse(isset($view['csrf'])); } public function testCsrfProtectionCanBeDisabled() { $view = $this->factory ->create('form', null, array( 'csrf_field_name' => 'csrf', 'csrf_protection' => false, 'compound' => true, )) ->createView(); $this->assertFalse(isset($view['csrf'])); } public function testGenerateCsrfToken() { $this->tokenManager->expects($this->once()) ->method('getToken') ->with('TOKEN_ID') ->will($this->returnValue(new CsrfToken('TOKEN_ID', 'token'))); $view = $this->factory ->create('form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'csrf_token_id' => 'TOKEN_ID', 'compound' => true, )) ->createView(); $this->assertEquals('token', $view['csrf']->vars['value']); } public function testGenerateCsrfTokenUsesFormNameAsIntentionByDefault() { $this->tokenManager->expects($this->once()) ->method('getToken') ->with('FORM_NAME') ->will($this->returnValue('token')); $view = $this->factory ->createNamed('FORM_NAME', 'form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'compound' => true, )) ->createView(); $this->assertEquals('token', $view['csrf']->vars['value']); } public function testGenerateCsrfTokenUsesTypeClassAsIntentionIfEmptyFormName() { $this->tokenManager->expects($this->once()) ->method('getToken') ->with('Symfony\Component\Form\Extension\Core\Type\FormType') ->will($this->returnValue('token')); $view = $this->factory ->createNamed('', 'form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'compound' => true, )) ->createView(); $this->assertEquals('token', $view['csrf']->vars['value']); } public function provideBoolean() { return array( array(true), array(false), ); } /** * @dataProvider provideBoolean */ public function testValidateTokenOnSubmitIfRootAndCompound($valid) { $this->tokenManager->expects($this->once()) ->method('isTokenValid') ->with(new CsrfToken('TOKEN_ID', 'token')) ->will($this->returnValue($valid)); $form = $this->factory ->createBuilder('form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'csrf_token_id' => 'TOKEN_ID', 'compound' => true, )) ->add('child', 'text') ->getForm(); $form->submit(array( 'child' => 'foobar', 'csrf' => 'token', )); // Remove token from data $this->assertSame(array('child' => 'foobar'), $form->getData()); // Validate accordingly $this->assertSame($valid, $form->isValid()); } /** * @dataProvider provideBoolean */ public function testValidateTokenOnSubmitIfRootAndCompoundUsesFormNameAsIntentionByDefault($valid) { $this->tokenManager->expects($this->once()) ->method('isTokenValid') ->with(new CsrfToken('FORM_NAME', 'token')) ->will($this->returnValue($valid)); $form = $this->factory ->createNamedBuilder('FORM_NAME', 'form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'compound' => true, )) ->add('child', 'text') ->getForm(); $form->submit(array( 'child' => 'foobar', 'csrf' => 'token', )); // Remove token from data $this->assertSame(array('child' => 'foobar'), $form->getData()); // Validate accordingly $this->assertSame($valid, $form->isValid()); } /** * @dataProvider provideBoolean */ public function testValidateTokenOnSubmitIfRootAndCompoundUsesTypeClassAsIntentionIfEmptyFormName($valid) { $this->tokenManager->expects($this->once()) ->method('isTokenValid') ->with(new CsrfToken('Symfony\Component\Form\Extension\Core\Type\FormType', 'token')) ->will($this->returnValue($valid)); $form = $this->factory ->createNamedBuilder('', 'form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'compound' => true, )) ->add('child', 'text') ->getForm(); $form->submit(array( 'child' => 'foobar', 'csrf' => 'token', )); // Remove token from data $this->assertSame(array('child' => 'foobar'), $form->getData()); // Validate accordingly $this->assertSame($valid, $form->isValid()); } public function testFailIfRootAndCompoundAndTokenMissing() { $this->tokenManager->expects($this->never()) ->method('isTokenValid'); $form = $this->factory ->createBuilder('form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'csrf_token_id' => 'TOKEN_ID', 'compound' => true, )) ->add('child', 'text') ->getForm(); $form->submit(array( 'child' => 'foobar', // token is missing )); // Remove token from data $this->assertSame(array('child' => 'foobar'), $form->getData()); // Validate accordingly $this->assertFalse($form->isValid()); } public function testDontValidateTokenIfCompoundButNoRoot() { $this->tokenManager->expects($this->never()) ->method('isTokenValid'); $form = $this->factory ->createNamedBuilder('root', 'form') ->add($this->factory ->createNamedBuilder('form', 'form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'csrf_token_id' => 'TOKEN_ID', 'compound' => true, )) ) ->getForm() ->get('form'); $form->submit(array( 'child' => 'foobar', 'csrf' => 'token', )); } public function testDontValidateTokenIfRootButNotCompound() { $this->tokenManager->expects($this->never()) ->method('isTokenValid'); $form = $this->factory ->create('form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'csrf_token_id' => 'TOKEN_ID', 'compound' => false, )); $form->submit(array( 'csrf' => 'token', )); } public function testNoCsrfProtectionOnPrototype() { $prototypeView = $this->factory ->create('collection', null, array( 'type' => new FormTypeCsrfExtensionTest_ChildType(), 'options' => array( 'csrf_field_name' => 'csrf', ), 'prototype' => true, 'allow_add' => true, )) ->createView() ->vars['prototype']; $this->assertFalse(isset($prototypeView['csrf'])); $this->assertCount(1, $prototypeView); } public function testsTranslateCustomErrorMessage() { $this->tokenManager->expects($this->once()) ->method('isTokenValid') ->with(new CsrfToken('TOKEN_ID', 'token')) ->will($this->returnValue(false)); $this->translator->expects($this->once()) ->method('trans') ->with('Foobar') ->will($this->returnValue('[trans]Foobar[/trans]')); $form = $this->factory ->createBuilder('form', null, array( 'csrf_field_name' => 'csrf', 'csrf_token_manager' => $this->tokenManager, 'csrf_message' => 'Foobar', 'csrf_token_id' => 'TOKEN_ID', 'compound' => true, )) ->getForm(); $form->submit(array( 'csrf' => 'token', )); $errors = $form->getErrors(); $this->assertGreaterThan(0, count($errors)); $this->assertEquals(new FormError('[trans]Foobar[/trans]'), $errors[0]); } } Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php000064400000003604152374770060025003 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Csrf\CsrfProvider; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider; class SessionCsrfProviderTest extends \PHPUnit_Framework_TestCase { protected $provider; protected $session; protected function setUp() { $this->session = $this->getMock( 'Symfony\Component\HttpFoundation\Session\Session', array(), array(), '', false // don't call constructor ); $this->provider = new SessionCsrfProvider($this->session, 'SECRET'); } protected function tearDown() { $this->provider = null; $this->session = null; } public function testGenerateCsrfToken() { $this->session->expects($this->once()) ->method('getId') ->will($this->returnValue('ABCDEF')); $token = $this->provider->generateCsrfToken('foo'); $this->assertEquals(sha1('SECRET'.'foo'.'ABCDEF'), $token); } public function testIsCsrfTokenValidSucceeds() { $this->session->expects($this->once()) ->method('getId') ->will($this->returnValue('ABCDEF')); $token = sha1('SECRET'.'foo'.'ABCDEF'); $this->assertTrue($this->provider->isCsrfTokenValid('foo', $token)); } public function testIsCsrfTokenValidFails() { $this->session->expects($this->once()) ->method('getId') ->will($this->returnValue('ABCDEF')); $token = sha1('SECRET'.'bar'.'ABCDEF'); $this->assertFalse($this->provider->isCsrfTokenValid('foo', $token)); } } Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php000064400000003755152374770060024753 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Csrf\CsrfProvider; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider; /** * @runTestsInSeparateProcesses */ class DefaultCsrfProviderTest extends \PHPUnit_Framework_TestCase { protected $provider; public static function setUpBeforeClass() { ini_set('session.save_handler', 'files'); ini_set('session.save_path', sys_get_temp_dir()); } protected function setUp() { $this->provider = new DefaultCsrfProvider('SECRET'); } protected function tearDown() { $this->provider = null; } public function testGenerateCsrfToken() { session_start(); $token = $this->provider->generateCsrfToken('foo'); $this->assertEquals(sha1('SECRET'.'foo'.session_id()), $token); } public function testGenerateCsrfTokenOnUnstartedSession() { session_id('touti'); if (!version_compare(PHP_VERSION, '5.4', '>=')) { $this->markTestSkipped('This test requires PHP >= 5.4'); } $this->assertSame(PHP_SESSION_NONE, session_status()); $token = $this->provider->generateCsrfToken('foo'); $this->assertEquals(sha1('SECRET'.'foo'.session_id()), $token); $this->assertSame(PHP_SESSION_ACTIVE, session_status()); } public function testIsCsrfTokenValidSucceeds() { session_start(); $token = sha1('SECRET'.'foo'.session_id()); $this->assertTrue($this->provider->isCsrfTokenValid('foo', $token)); } public function testIsCsrfTokenValidFails() { session_start(); $token = sha1('SECRET'.'bar'.session_id()); $this->assertFalse($this->provider->isCsrfTokenValid('foo', $token)); } } Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php000064400000004301152374770060025617 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Csrf\EventListener; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener; class CsrfValidationListenerTest extends \PHPUnit_Framework_TestCase { protected $dispatcher; protected $factory; protected $tokenManager; protected $form; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->tokenManager = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface'); $this->form = $this->getBuilder('post') ->setDataMapper($this->getDataMapper()) ->getForm(); } protected function tearDown() { $this->dispatcher = null; $this->factory = null; $this->tokenManager = null; $this->form = null; } protected function getBuilder($name = 'name') { return new FormBuilder($name, null, $this->dispatcher, $this->factory, array('compound' => true)); } protected function getForm($name = 'name') { return $this->getBuilder($name)->getForm(); } protected function getDataMapper() { return $this->getMock('Symfony\Component\Form\DataMapperInterface'); } protected function getMockForm() { return $this->getMock('Symfony\Component\Form\Test\FormInterface'); } // https://github.com/symfony/symfony/pull/5838 public function testStringFormData() { $data = "XP4HUzmHPi"; $event = new FormEvent($this->form, $data); $validation = new CsrfValidationListener('csrf', $this->tokenManager, 'unknown', 'Invalid.'); $validation->preSubmit($event); // Validate accordingly $this->assertSame($data, $event->getData()); } } Symfony/Component/Form/Tests/Extension/DataCollector/Type/DataCollectorTypeExtensionTest.php000064400000002630152374770060026440 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\DataCollector\Type; use Symfony\Component\Form\Extension\DataCollector\Type\DataCollectorTypeExtension; class DataCollectorTypeExtensionTest extends \PHPUnit_Framework_TestCase { /** * @var DataCollectorTypeExtension */ private $extension; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dataCollector; public function setUp() { $this->dataCollector = $this->getMock('Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface'); $this->extension = new DataCollectorTypeExtension($this->dataCollector); } public function testGetExtendedType() { $this->assertEquals('form', $this->extension->getExtendedType()); } public function testBuildForm() { $builder = $this->getMock('Symfony\Component\Form\Test\FormBuilderInterface'); $builder->expects($this->atLeastOnce()) ->method('addEventSubscriber') ->with($this->isInstanceOf('Symfony\Component\Form\Extension\DataCollector\EventListener\DataCollectorListener')); $this->extension->buildForm($builder, array()); } } Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.php000064400000037365152374770060023621 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\DataCollector; use Symfony\Component\Form\Extension\DataCollector\FormDataCollector; use Symfony\Component\Form\Form; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormView; class FormDataCollectorTest extends \PHPUnit_Framework_TestCase { /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dataExtractor; /** * @var FormDataCollector */ private $dataCollector; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dispatcher; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $factory; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dataMapper; /** * @var Form */ private $form; /** * @var Form */ private $childForm; /** * @var FormView */ private $view; /** * @var FormView */ private $childView; protected function setUp() { $this->dataExtractor = $this->getMock('Symfony\Component\Form\Extension\DataCollector\FormDataExtractorInterface'); $this->dataCollector = new FormDataCollector($this->dataExtractor); $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->dataMapper = $this->getMock('Symfony\Component\Form\DataMapperInterface'); $this->form = $this->createForm('name'); $this->childForm = $this->createForm('child'); $this->view = new FormView(); $this->childView = new FormView(); } public function testBuildPreliminaryFormTree() { $this->form->add($this->childForm); $this->dataExtractor->expects($this->at(0)) ->method('extractConfiguration') ->with($this->form) ->will($this->returnValue(array('config' => 'foo'))); $this->dataExtractor->expects($this->at(1)) ->method('extractConfiguration') ->with($this->childForm) ->will($this->returnValue(array('config' => 'bar'))); $this->dataExtractor->expects($this->at(2)) ->method('extractDefaultData') ->with($this->form) ->will($this->returnValue(array('default_data' => 'foo'))); $this->dataExtractor->expects($this->at(3)) ->method('extractDefaultData') ->with($this->childForm) ->will($this->returnValue(array('default_data' => 'bar'))); $this->dataExtractor->expects($this->at(4)) ->method('extractSubmittedData') ->with($this->form) ->will($this->returnValue(array('submitted_data' => 'foo'))); $this->dataExtractor->expects($this->at(5)) ->method('extractSubmittedData') ->with($this->childForm) ->will($this->returnValue(array('submitted_data' => 'bar'))); $this->dataCollector->collectConfiguration($this->form); $this->dataCollector->collectDefaultData($this->form); $this->dataCollector->collectSubmittedData($this->form); $this->dataCollector->buildPreliminaryFormTree($this->form); $this->assertSame(array( 'forms' => array( 'name' => array( 'config' => 'foo', 'default_data' => 'foo', 'submitted_data' => 'foo', 'children' => array( 'child' => array( 'config' => 'bar', 'default_data' => 'bar', 'submitted_data' => 'bar', 'children' => array(), ), ), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); } public function testBuildMultiplePreliminaryFormTrees() { $form1 = $this->createForm('form1'); $form2 = $this->createForm('form2'); $this->dataExtractor->expects($this->at(0)) ->method('extractConfiguration') ->with($form1) ->will($this->returnValue(array('config' => 'foo'))); $this->dataExtractor->expects($this->at(1)) ->method('extractConfiguration') ->with($form2) ->will($this->returnValue(array('config' => 'bar'))); $this->dataCollector->collectConfiguration($form1); $this->dataCollector->collectConfiguration($form2); $this->dataCollector->buildPreliminaryFormTree($form1); $this->assertSame(array( 'forms' => array( 'form1' => array( 'config' => 'foo', 'children' => array(), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); $this->dataCollector->buildPreliminaryFormTree($form2); $this->assertSame(array( 'forms' => array( 'form1' => array( 'config' => 'foo', 'children' => array(), ), 'form2' => array( 'config' => 'bar', 'children' => array(), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); } public function testBuildSamePreliminaryFormTreeMultipleTimes() { $this->dataExtractor->expects($this->at(0)) ->method('extractConfiguration') ->with($this->form) ->will($this->returnValue(array('config' => 'foo'))); $this->dataExtractor->expects($this->at(1)) ->method('extractDefaultData') ->with($this->form) ->will($this->returnValue(array('default_data' => 'foo'))); $this->dataCollector->collectConfiguration($this->form); $this->dataCollector->buildPreliminaryFormTree($this->form); $this->assertSame(array( 'forms' => array( 'name' => array( 'config' => 'foo', 'children' => array(), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); $this->dataCollector->collectDefaultData($this->form); $this->dataCollector->buildPreliminaryFormTree($this->form); $this->assertSame(array( 'forms' => array( 'name' => array( 'config' => 'foo', 'default_data' => 'foo', 'children' => array(), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); } public function testBuildPreliminaryFormTreeWithoutCollectingAnyData() { $this->dataCollector->buildPreliminaryFormTree($this->form); $this->assertSame(array( 'forms' => array( 'name' => array( 'children' => array(), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); } public function testBuildFinalFormTree() { $this->form->add($this->childForm); $this->view->children['child'] = $this->childView; $this->dataExtractor->expects($this->at(0)) ->method('extractConfiguration') ->with($this->form) ->will($this->returnValue(array('config' => 'foo'))); $this->dataExtractor->expects($this->at(1)) ->method('extractConfiguration') ->with($this->childForm) ->will($this->returnValue(array('config' => 'bar'))); $this->dataExtractor->expects($this->at(2)) ->method('extractDefaultData') ->with($this->form) ->will($this->returnValue(array('default_data' => 'foo'))); $this->dataExtractor->expects($this->at(3)) ->method('extractDefaultData') ->with($this->childForm) ->will($this->returnValue(array('default_data' => 'bar'))); $this->dataExtractor->expects($this->at(4)) ->method('extractSubmittedData') ->with($this->form) ->will($this->returnValue(array('submitted_data' => 'foo'))); $this->dataExtractor->expects($this->at(5)) ->method('extractSubmittedData') ->with($this->childForm) ->will($this->returnValue(array('submitted_data' => 'bar'))); $this->dataExtractor->expects($this->at(6)) ->method('extractViewVariables') ->with($this->view) ->will($this->returnValue(array('view_vars' => 'foo'))); $this->dataExtractor->expects($this->at(7)) ->method('extractViewVariables') ->with($this->childView) ->will($this->returnValue(array('view_vars' => 'bar'))); $this->dataCollector->collectConfiguration($this->form); $this->dataCollector->collectDefaultData($this->form); $this->dataCollector->collectSubmittedData($this->form); $this->dataCollector->collectViewVariables($this->view); $this->dataCollector->buildFinalFormTree($this->form, $this->view); $this->assertSame(array( 'forms' => array( 'name' => array( 'view_vars' => 'foo', 'config' => 'foo', 'default_data' => 'foo', 'submitted_data' => 'foo', 'children' => array( 'child' => array( 'view_vars' => 'bar', 'config' => 'bar', 'default_data' => 'bar', 'submitted_data' => 'bar', 'children' => array(), ), ), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); } public function testFinalFormReliesOnFormViewStructure() { $this->form->add($this->createForm('first')); $this->form->add($this->createForm('second')); $this->view->children['second'] = $this->childView; $this->dataCollector->buildPreliminaryFormTree($this->form); $this->assertSame(array( 'forms' => array( 'name' => array( 'children' => array( 'first' => array( 'children' => array(), ), 'second' => array( 'children' => array(), ), ), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); $this->dataCollector->buildFinalFormTree($this->form, $this->view); $this->assertSame(array( 'forms' => array( 'name' => array( 'children' => array( // "first" not present in FormView 'second' => array( 'children' => array(), ), ), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); } public function testChildViewsCanBeWithoutCorrespondingChildForms() { // don't add $this->childForm to $this->form! $this->view->children['child'] = $this->childView; $this->dataExtractor->expects($this->at(0)) ->method('extractConfiguration') ->with($this->form) ->will($this->returnValue(array('config' => 'foo'))); $this->dataExtractor->expects($this->at(1)) ->method('extractConfiguration') ->with($this->childForm) ->will($this->returnValue(array('config' => 'bar'))); // explicitly call collectConfiguration(), since $this->childForm is not // contained in the form tree $this->dataCollector->collectConfiguration($this->form); $this->dataCollector->collectConfiguration($this->childForm); $this->dataCollector->buildFinalFormTree($this->form, $this->view); $this->assertSame(array( 'forms' => array( 'name' => array( 'config' => 'foo', 'children' => array( 'child' => array( // no "config" key 'children' => array(), ), ), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); } public function testChildViewsWithoutCorrespondingChildFormsMayBeExplicitlyAssociated() { // don't add $this->childForm to $this->form! $this->view->children['child'] = $this->childView; // but associate the two $this->dataCollector->associateFormWithView($this->childForm, $this->childView); $this->dataExtractor->expects($this->at(0)) ->method('extractConfiguration') ->with($this->form) ->will($this->returnValue(array('config' => 'foo'))); $this->dataExtractor->expects($this->at(1)) ->method('extractConfiguration') ->with($this->childForm) ->will($this->returnValue(array('config' => 'bar'))); // explicitly call collectConfiguration(), since $this->childForm is not // contained in the form tree $this->dataCollector->collectConfiguration($this->form); $this->dataCollector->collectConfiguration($this->childForm); $this->dataCollector->buildFinalFormTree($this->form, $this->view); $this->assertSame(array( 'forms' => array( 'name' => array( 'config' => 'foo', 'children' => array( 'child' => array( 'config' => 'bar', 'children' => array(), ), ), ), ), 'nb_errors' => 0, ), $this->dataCollector->getData()); } public function testCollectSubmittedDataCountsErrors() { $form1 = $this->createForm('form1'); $childForm1 = $this->createForm('child1'); $form2 = $this->createForm('form2'); $form1->add($childForm1); $this->dataExtractor->expects($this->at(0)) ->method('extractSubmittedData') ->with($form1) ->will($this->returnValue(array('errors' => array('foo')))); $this->dataExtractor->expects($this->at(1)) ->method('extractSubmittedData') ->with($childForm1) ->will($this->returnValue(array('errors' => array('bar', 'bam')))); $this->dataExtractor->expects($this->at(2)) ->method('extractSubmittedData') ->with($form2) ->will($this->returnValue(array('errors' => array('baz')))); $this->dataCollector->collectSubmittedData($form1); $data = $this->dataCollector->getData(); $this->assertSame(3, $data['nb_errors']); $this->dataCollector->collectSubmittedData($form2); $data = $this->dataCollector->getData(); $this->assertSame(4, $data['nb_errors']); } private function createForm($name) { $builder = new FormBuilder($name, null, $this->dispatcher, $this->factory); $builder->setCompound(true); $builder->setDataMapper($this->dataMapper); return $builder->getForm(); } } Symfony/Component/Form/Tests/Extension/DataCollector/FormDataExtractorTest.php000064400000026343152374770060023640 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\DataCollector; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\DataCollector\FormDataExtractor; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; class FormDataExtractorTest_SimpleValueExporter extends ValueExporter { /** * {@inheritdoc} */ public function exportValue($value) { return var_export($value, true); } } /** * @author Bernhard Schussek */ class FormDataExtractorTest extends \PHPUnit_Framework_TestCase { /** * @var FormDataExtractorTest_SimpleValueExporter */ private $valueExporter; /** * @var FormDataExtractor */ private $dataExtractor; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dispatcher; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $factory; protected function setUp() { $this->valueExporter = new FormDataExtractorTest_SimpleValueExporter(); $this->dataExtractor = new FormDataExtractor($this->valueExporter); $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); } public function testExtractConfiguration() { $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $type->expects($this->any()) ->method('getName') ->will($this->returnValue('type_name')); $type->expects($this->any()) ->method('getInnerType') ->will($this->returnValue(new \stdClass())); $form = $this->createBuilder('name') ->setType($type) ->getForm(); $this->assertSame(array( 'id' => 'name', 'type' => 'type_name', 'type_class' => 'stdClass', 'synchronized' => 'true', 'passed_options' => array(), 'resolved_options' => array(), ), $this->dataExtractor->extractConfiguration($form)); } public function testExtractConfigurationSortsPassedOptions() { $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $type->expects($this->any()) ->method('getName') ->will($this->returnValue('type_name')); $type->expects($this->any()) ->method('getInnerType') ->will($this->returnValue(new \stdClass())); $options = array( 'b' => 'foo', 'a' => 'bar', 'c' => 'baz', ); $form = $this->createBuilder('name') ->setType($type) // passed options are stored in an attribute by // ResolvedTypeDataCollectorProxy ->setAttribute('data_collector/passed_options', $options) ->getForm(); $this->assertSame(array( 'id' => 'name', 'type' => 'type_name', 'type_class' => 'stdClass', 'synchronized' => 'true', 'passed_options' => array( 'a' => "'bar'", 'b' => "'foo'", 'c' => "'baz'", ), 'resolved_options' => array(), ), $this->dataExtractor->extractConfiguration($form)); } public function testExtractConfigurationSortsResolvedOptions() { $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $type->expects($this->any()) ->method('getName') ->will($this->returnValue('type_name')); $type->expects($this->any()) ->method('getInnerType') ->will($this->returnValue(new \stdClass())); $options = array( 'b' => 'foo', 'a' => 'bar', 'c' => 'baz', ); $form = $this->createBuilder('name', $options) ->setType($type) ->getForm(); $this->assertSame(array( 'id' => 'name', 'type' => 'type_name', 'type_class' => 'stdClass', 'synchronized' => 'true', 'passed_options' => array(), 'resolved_options' => array( 'a' => "'bar'", 'b' => "'foo'", 'c' => "'baz'", ), ), $this->dataExtractor->extractConfiguration($form)); } public function testExtractConfigurationBuildsIdRecursively() { $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $type->expects($this->any()) ->method('getName') ->will($this->returnValue('type_name')); $type->expects($this->any()) ->method('getInnerType') ->will($this->returnValue(new \stdClass())); $grandParent = $this->createBuilder('grandParent') ->setCompound(true) ->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface')) ->getForm(); $parent = $this->createBuilder('parent') ->setCompound(true) ->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface')) ->getForm(); $form = $this->createBuilder('name') ->setType($type) ->getForm(); $grandParent->add($parent); $parent->add($form); $this->assertSame(array( 'id' => 'grandParent_parent_name', 'type' => 'type_name', 'type_class' => 'stdClass', 'synchronized' => 'true', 'passed_options' => array(), 'resolved_options' => array(), ), $this->dataExtractor->extractConfiguration($form)); } public function testExtractDefaultData() { $form = $this->createBuilder('name')->getForm(); $form->setData('Foobar'); $this->assertSame(array( 'default_data' => array( 'norm' => "'Foobar'", ), 'submitted_data' => array(), ), $this->dataExtractor->extractDefaultData($form)); } public function testExtractDefaultDataStoresModelDataIfDifferent() { $form = $this->createBuilder('name') ->addModelTransformer(new FixedDataTransformer(array( 'Foo' => 'Bar' ))) ->getForm(); $form->setData('Foo'); $this->assertSame(array( 'default_data' => array( 'norm' => "'Bar'", 'model' => "'Foo'", ), 'submitted_data' => array(), ), $this->dataExtractor->extractDefaultData($form)); } public function testExtractDefaultDataStoresViewDataIfDifferent() { $form = $this->createBuilder('name') ->addViewTransformer(new FixedDataTransformer(array( 'Foo' => 'Bar' ))) ->getForm(); $form->setData('Foo'); $this->assertSame(array( 'default_data' => array( 'norm' => "'Foo'", 'view' => "'Bar'", ), 'submitted_data' => array(), ), $this->dataExtractor->extractDefaultData($form)); } public function testExtractSubmittedData() { $form = $this->createBuilder('name')->getForm(); $form->submit('Foobar'); $this->assertSame(array( 'submitted_data' => array( 'norm' => "'Foobar'", ), 'errors' => array(), 'synchronized' => 'true', ), $this->dataExtractor->extractSubmittedData($form)); } public function testExtractSubmittedDataStoresModelDataIfDifferent() { $form = $this->createBuilder('name') ->addModelTransformer(new FixedDataTransformer(array( 'Foo' => 'Bar', '' => '', ))) ->getForm(); $form->submit('Bar'); $this->assertSame(array( 'submitted_data' => array( 'norm' => "'Bar'", 'model' => "'Foo'", ), 'errors' => array(), 'synchronized' => 'true', ), $this->dataExtractor->extractSubmittedData($form)); } public function testExtractSubmittedDataStoresViewDataIfDifferent() { $form = $this->createBuilder('name') ->addViewTransformer(new FixedDataTransformer(array( 'Foo' => 'Bar', '' => '', ))) ->getForm(); $form->submit('Bar'); $this->assertSame(array( 'submitted_data' => array( 'norm' => "'Foo'", 'view' => "'Bar'", ), 'errors' => array(), 'synchronized' => 'true', ), $this->dataExtractor->extractSubmittedData($form)); } public function testExtractSubmittedDataStoresErrors() { $form = $this->createBuilder('name')->getForm(); $form->submit('Foobar'); $form->addError(new FormError('Invalid!')); $this->assertSame(array( 'submitted_data' => array( 'norm' => "'Foobar'", ), 'errors' => array( array('message' => 'Invalid!'), ), 'synchronized' => 'true', ), $this->dataExtractor->extractSubmittedData($form)); } public function testExtractSubmittedDataRemembersIfNonSynchronized() { $form = $this->createBuilder('name') ->addModelTransformer(new CallbackTransformer( function () {}, function () { throw new TransformationFailedException('Fail!'); } )) ->getForm(); $form->submit('Foobar'); $this->assertSame(array( 'submitted_data' => array( 'norm' => "'Foobar'", 'model' => 'NULL', ), 'errors' => array(), 'synchronized' => 'false', ), $this->dataExtractor->extractSubmittedData($form)); } public function testExtractViewVariables() { $view = new FormView(); $view->vars = array( 'b' => 'foo', 'a' => 'bar', 'c' => 'baz', 'id' => 'foo_bar', ); $this->assertSame(array( 'id' => 'foo_bar', 'view_vars' => array( 'a' => "'bar'", 'b' => "'foo'", 'c' => "'baz'", 'id' => "'foo_bar'", ), ), $this->dataExtractor->extractViewVariables($view)); } /** * @param string $name * @param array $options * * @return FormBuilder */ private function createBuilder($name, array $options = array()) { return new FormBuilder($name, null, $this->dispatcher, $this->factory, $options); } } Symfony/Component/Form/Tests/Extension/DataCollector/DataCollectorExtensionTest.php000064400000002474152374770060024663 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\DataCollector; use Symfony\Component\Form\Extension\DataCollector\DataCollectorExtension; /** * @covers Symfony\Component\Form\Extension\DataCollector\DataCollectorExtension */ class DataCollectorExtensionTest extends \PHPUnit_Framework_TestCase { /** * @var DataCollectorExtension */ private $extension; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dataCollector; public function setUp() { $this->dataCollector = $this->getMock('Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface'); $this->extension = new DataCollectorExtension($this->dataCollector); } public function testLoadTypeExtensions() { $typeExtensions = $this->extension->getTypeExtensions('form'); $this->assertInternalType('array', $typeExtensions); $this->assertCount(1, $typeExtensions); $this->assertInstanceOf('Symfony\Component\Form\Extension\DataCollector\Type\DataCollectorTypeExtension', array_shift($typeExtensions)); } } Symfony/Component/Form/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php000064400000020260152374770060027207 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\HttpFoundation\EventListener; use Symfony\Component\Form\Extension\HttpFoundation\EventListener\BindRequestListener; use Symfony\Component\Form\Form; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Test\DeprecationErrorHandler; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\File\UploadedFile; /** * @author Bernhard Schussek */ class BindRequestListenerTest extends \PHPUnit_Framework_TestCase { private $values; private $filesPlain; private $filesNested; /** * @var UploadedFile */ private $uploadedFile; protected function setUp() { $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); $this->values = array( 'name' => 'Bernhard', 'image' => array('filename' => 'foobar.png'), ); $this->filesPlain = array( 'image' => array( 'error' => UPLOAD_ERR_OK, 'name' => 'upload.png', 'size' => 123, 'tmp_name' => $path, 'type' => 'image/png' ), ); $this->filesNested = array( 'error' => array('image' => UPLOAD_ERR_OK), 'name' => array('image' => 'upload.png'), 'size' => array('image' => 123), 'tmp_name' => array('image' => $path), 'type' => array('image' => 'image/png'), ); $this->uploadedFile = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); } protected function tearDown() { unlink($this->uploadedFile->getRealPath()); } public function requestMethodProvider() { return array( array('POST'), array('PUT'), array('DELETE'), array('PATCH'), ); } /** * @dataProvider requestMethodProvider */ public function testSubmitRequest($method) { $values = array('author' => $this->values); $files = array('author' => $this->filesNested); $request = new Request(array(), $values, array(), array(), $files, array( 'REQUEST_METHOD' => $method, )); $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('author', null, $dispatcher); $form = new Form($config); $event = new FormEvent($form, $request); $listener = new BindRequestListener(); DeprecationErrorHandler::preBind($listener, $event); $this->assertEquals(array( 'name' => 'Bernhard', 'image' => $this->uploadedFile, ), $event->getData()); } /** * @dataProvider requestMethodProvider */ public function testSubmitRequestWithEmptyName($method) { $request = new Request(array(), $this->values, array(), array(), $this->filesPlain, array( 'REQUEST_METHOD' => $method, )); $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('', null, $dispatcher); $form = new Form($config); $event = new FormEvent($form, $request); $listener = new BindRequestListener(); DeprecationErrorHandler::preBind($listener, $event); $this->assertEquals(array( 'name' => 'Bernhard', 'image' => $this->uploadedFile, ), $event->getData()); } /** * @dataProvider requestMethodProvider */ public function testSubmitEmptyRequestToCompoundForm($method) { $request = new Request(array(), array(), array(), array(), array(), array( 'REQUEST_METHOD' => $method, )); $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('author', null, $dispatcher); $config->setCompound(true); $config->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface')); $form = new Form($config); $event = new FormEvent($form, $request); $listener = new BindRequestListener(); DeprecationErrorHandler::preBind($listener, $event); // Default to empty array $this->assertEquals(array(), $event->getData()); } /** * @dataProvider requestMethodProvider */ public function testSubmitEmptyRequestToSimpleForm($method) { $request = new Request(array(), array(), array(), array(), array(), array( 'REQUEST_METHOD' => $method, )); $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('author', null, $dispatcher); $config->setCompound(false); $form = new Form($config); $event = new FormEvent($form, $request); $listener = new BindRequestListener(); DeprecationErrorHandler::preBind($listener, $event); // Default to null $this->assertNull($event->getData()); } public function testSubmitGetRequest() { $values = array('author' => $this->values); $request = new Request($values, array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', )); $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('author', null, $dispatcher); $form = new Form($config); $event = new FormEvent($form, $request); $listener = new BindRequestListener(); DeprecationErrorHandler::preBind($listener, $event); $this->assertEquals(array( 'name' => 'Bernhard', 'image' => array('filename' => 'foobar.png'), ), $event->getData()); } public function testSubmitGetRequestWithEmptyName() { $request = new Request($this->values, array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', )); $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('', null, $dispatcher); $form = new Form($config); $event = new FormEvent($form, $request); $listener = new BindRequestListener(); DeprecationErrorHandler::preBind($listener, $event); $this->assertEquals(array( 'name' => 'Bernhard', 'image' => array('filename' => 'foobar.png'), ), $event->getData()); } public function testSubmitEmptyGetRequestToCompoundForm() { $request = new Request(array(), array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', )); $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('author', null, $dispatcher); $config->setCompound(true); $config->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface')); $form = new Form($config); $event = new FormEvent($form, $request); $listener = new BindRequestListener(); DeprecationErrorHandler::preBind($listener, $event); $this->assertEquals(array(), $event->getData()); } public function testSubmitEmptyGetRequestToSimpleForm() { $request = new Request(array(), array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', )); $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('author', null, $dispatcher); $config->setCompound(false); $form = new Form($config); $event = new FormEvent($form, $request); $listener = new BindRequestListener(); DeprecationErrorHandler::preBind($listener, $event); $this->assertNull($event->getData()); } } Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php000064400000003146152374770060026306 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\HttpFoundation; use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; use Symfony\Component\Form\Tests\AbstractRequestHandlerTest; use Symfony\Component\HttpFoundation\Request; /** * @author Bernhard Schussek */ class HttpFoundationRequestHandlerTest extends AbstractRequestHandlerTest { /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testRequestShouldNotBeNull() { $this->requestHandler->handleRequest($this->getMockForm('name', 'GET')); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testRequestShouldBeInstanceOfRequest() { $this->requestHandler->handleRequest($this->getMockForm('name', 'GET'), new \stdClass()); } protected function setRequestData($method, $data, $files = array()) { $this->request = Request::create('http://localhost', $method, $data, array(), $files); } protected function getRequestHandler() { return new HttpFoundationRequestHandler(); } protected function getMockFile() { return $this->getMockBuilder('Symfony\Component\HttpFoundation\File\UploadedFile') ->disableOriginalConstructor() ->getMock(); } } Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php000064400000027335152374770060024245 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataMapper; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\FormConfigInterface; use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase { /** * @var PropertyPathMapper */ private $mapper; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dispatcher; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $propertyAccessor; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->propertyAccessor = $this->getMock('Symfony\Component\PropertyAccess\PropertyAccessorInterface'); $this->mapper = new PropertyPathMapper($this->propertyAccessor); } /** * @param $path * @return \PHPUnit_Framework_MockObject_MockObject */ private function getPropertyPath($path) { return $this->getMockBuilder('Symfony\Component\PropertyAccess\PropertyPath') ->setConstructorArgs(array($path)) ->setMethods(array('getValue', 'setValue')) ->getMock(); } /** * @param FormConfigInterface $config * @param Boolean $synchronized * @param Boolean $submitted * @return \PHPUnit_Framework_MockObject_MockObject */ private function getForm(FormConfigInterface $config, $synchronized = true, $submitted = true) { $form = $this->getMockBuilder('Symfony\Component\Form\Form') ->setConstructorArgs(array($config)) ->setMethods(array('isSynchronized', 'isSubmitted')) ->getMock(); $form->expects($this->any()) ->method('isSynchronized') ->will($this->returnValue($synchronized)); $form->expects($this->any()) ->method('isSubmitted') ->will($this->returnValue($submitted)); return $form; } /** * @return \PHPUnit_Framework_MockObject_MockObject */ private function getDataMapper() { return $this->getMock('Symfony\Component\Form\DataMapperInterface'); } public function testMapDataToFormsPassesObjectRefIfByReference() { $car = new \stdClass(); $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->once()) ->method('getValue') ->with($car, $propertyPath) ->will($this->returnValue($engine)); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $form = $this->getForm($config); $this->mapper->mapDataToForms($car, array($form)); // Can't use isIdentical() above because mocks always clone their // arguments which can't be disabled in PHPUnit 3.6 $this->assertSame($engine, $form->getData()); } public function testMapDataToFormsPassesObjectCloneIfNotByReference() { $car = new \stdClass(); $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->once()) ->method('getValue') ->with($car, $propertyPath) ->will($this->returnValue($engine)); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(false); $config->setPropertyPath($propertyPath); $form = $this->getForm($config); $this->mapper->mapDataToForms($car, array($form)); $this->assertNotSame($engine, $form->getData()); $this->assertEquals($engine, $form->getData()); } public function testMapDataToFormsIgnoresEmptyPropertyPath() { $car = new \stdClass(); $config = new FormConfigBuilder(null, '\stdClass', $this->dispatcher); $config->setByReference(true); $form = $this->getForm($config); $this->assertNull($form->getPropertyPath()); $this->mapper->mapDataToForms($car, array($form)); $this->assertNull($form->getData()); } public function testMapDataToFormsIgnoresUnmapped() { $car = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->never()) ->method('getValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setMapped(false); $config->setPropertyPath($propertyPath); $form = $this->getForm($config); $this->mapper->mapDataToForms($car, array($form)); $this->assertNull($form->getData()); } public function testMapDataToFormsSetsDefaultDataIfPassedDataIsNull() { $default = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->never()) ->method('getValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($default); $form = $this->getMockBuilder('Symfony\Component\Form\Form') ->setConstructorArgs(array($config)) ->setMethods(array('setData')) ->getMock(); $form->expects($this->once()) ->method('setData') ->with($default); $this->mapper->mapDataToForms(null, array($form)); } public function testMapDataToFormsSetsDefaultDataIfPassedDataIsEmptyArray() { $default = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->never()) ->method('getValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($default); $form = $this->getMockBuilder('Symfony\Component\Form\Form') ->setConstructorArgs(array($config)) ->setMethods(array('setData')) ->getMock(); $form->expects($this->once()) ->method('setData') ->with($default); $this->mapper->mapDataToForms(array(), array($form)); } public function testMapFormsToDataWritesBackIfNotByReference() { $car = new \stdClass(); $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->once()) ->method('setValue') ->with($car, $propertyPath, $engine); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(false); $config->setPropertyPath($propertyPath); $config->setData($engine); $form = $this->getForm($config); $this->mapper->mapFormsToData(array($form), $car); } public function testMapFormsToDataWritesBackIfByReferenceButNoReference() { $car = new \stdClass(); $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->once()) ->method('setValue') ->with($car, $propertyPath, $engine); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($engine); $form = $this->getForm($config); $this->mapper->mapFormsToData(array($form), $car); } public function testMapFormsToDataWritesBackIfByReferenceAndReference() { $car = new \stdClass(); $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); // $car already contains the reference of $engine $this->propertyAccessor->expects($this->once()) ->method('getValue') ->with($car, $propertyPath) ->will($this->returnValue($engine)); $this->propertyAccessor->expects($this->never()) ->method('setValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($engine); $form = $this->getForm($config); $this->mapper->mapFormsToData(array($form), $car); } public function testMapFormsToDataIgnoresUnmapped() { $car = new \stdClass(); $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->never()) ->method('setValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($engine); $config->setMapped(false); $form = $this->getForm($config); $this->mapper->mapFormsToData(array($form), $car); } public function testMapFormsToDataIgnoresUnsubmittedForms() { $car = new \stdClass(); $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->never()) ->method('setValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($engine); $form = $this->getForm($config, true, false); $this->mapper->mapFormsToData(array($form), $car); } public function testMapFormsToDataIgnoresEmptyData() { $car = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->never()) ->method('setValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData(null); $form = $this->getForm($config); $this->mapper->mapFormsToData(array($form), $car); } public function testMapFormsToDataIgnoresUnsynchronized() { $car = new \stdClass(); $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->never()) ->method('setValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($engine); $form = $this->getForm($config, false); $this->mapper->mapFormsToData(array($form), $car); } public function testMapFormsToDataIgnoresDisabled() { $car = new \stdClass(); $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->never()) ->method('setValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); $config->setData($engine); $config->setDisabled(true); $form = $this->getForm($config); $this->mapper->mapFormsToData(array($form), $car); } } Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php000064400000003230152374770060021633 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Intl\Util\IntlTestHelper; class CountryTypeTest extends TypeTestCase { protected function setUp() { IntlTestHelper::requireIntl($this); parent::setUp(); } public function testCountriesAreSelectable() { $form = $this->factory->create('country'); $view = $form->createView(); $choices = $view->vars['choices']; // Don't check objects for identity $this->assertContains(new ChoiceView('DE', 'DE', 'Germany'), $choices, '', false, false); $this->assertContains(new ChoiceView('GB', 'GB', 'United Kingdom'), $choices, '', false, false); $this->assertContains(new ChoiceView('US', 'US', 'United States'), $choices, '', false, false); $this->assertContains(new ChoiceView('FR', 'FR', 'France'), $choices, '', false, false); $this->assertContains(new ChoiceView('MY', 'MY', 'Malaysia'), $choices, '', false, false); } public function testUnknownCountryIsNotIncluded() { $form = $this->factory->create('country', 'country'); $view = $form->createView(); $choices = $view->vars['choices']; foreach ($choices as $choice) { if ('ZZ' === $choice->value) { $this->fail('Should not contain choice "ZZ"'); } } } } Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.php000064400000002141152374770060021367 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Intl\Util\IntlTestHelper; class LocaleTypeTest extends TypeTestCase { protected function setUp() { IntlTestHelper::requireIntl($this); parent::setUp(); } public function testLocalesAreSelectable() { $form = $this->factory->create('locale'); $view = $form->createView(); $choices = $view->vars['choices']; $this->assertContains(new ChoiceView('en', 'en', 'English'), $choices, '', false, false); $this->assertContains(new ChoiceView('en_GB', 'en_GB', 'English (United Kingdom)'), $choices, '', false, false); $this->assertContains(new ChoiceView('zh_Hant_MO', 'zh_Hant_MO', 'Chinese (Traditional, Macau SAR China)'), $choices, '', false, false); } } Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php000064400000045123152374770060021075 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Form\FormError; use Symfony\Component\Intl\Util\IntlTestHelper; class TimeTypeTest extends TypeTestCase { protected function setUp() { IntlTestHelper::requireIntl($this); parent::setUp(); } public function testSubmitDateTime() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'datetime', )); $input = array( 'hour' => '3', 'minute' => '4', ); $form->submit($input); $dateTime = new \DateTime('1970-01-01 03:04:00 UTC'); $this->assertEquals($dateTime, $form->getData()); $this->assertEquals($input, $form->getViewData()); } public function testSubmitString() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'string', )); $input = array( 'hour' => '3', 'minute' => '4', ); $form->submit($input); $this->assertEquals('03:04:00', $form->getData()); $this->assertEquals($input, $form->getViewData()); } public function testSubmitTimestamp() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'timestamp', )); $input = array( 'hour' => '3', 'minute' => '4', ); $form->submit($input); $dateTime = new \DateTime('1970-01-01 03:04:00 UTC'); $this->assertEquals($dateTime->format('U'), $form->getData()); $this->assertEquals($input, $form->getViewData()); } public function testSubmitArray() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'array', )); $input = array( 'hour' => '3', 'minute' => '4', ); $form->submit($input); $this->assertEquals($input, $form->getData()); $this->assertEquals($input, $form->getViewData()); } public function testSubmitDatetimeSingleText() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'datetime', 'widget' => 'single_text', )); $form->submit('03:04'); $this->assertEquals(new \DateTime('1970-01-01 03:04:00 UTC'), $form->getData()); $this->assertEquals('03:04', $form->getViewData()); } public function testSubmitDatetimeSingleTextWithoutMinutes() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'datetime', 'widget' => 'single_text', 'with_minutes' => false, )); $form->submit('03'); $this->assertEquals(new \DateTime('1970-01-01 03:00:00 UTC'), $form->getData()); $this->assertEquals('03', $form->getViewData()); } public function testSubmitArraySingleText() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'array', 'widget' => 'single_text', )); $data = array( 'hour' => '3', 'minute' => '4', ); $form->submit('03:04'); $this->assertEquals($data, $form->getData()); $this->assertEquals('03:04', $form->getViewData()); } public function testSubmitArraySingleTextWithoutMinutes() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'array', 'widget' => 'single_text', 'with_minutes' => false, )); $data = array( 'hour' => '3', ); $form->submit('03'); $this->assertEquals($data, $form->getData()); $this->assertEquals('03', $form->getViewData()); } public function testSubmitArraySingleTextWithSeconds() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'array', 'widget' => 'single_text', 'with_seconds' => true, )); $data = array( 'hour' => '3', 'minute' => '4', 'second' => '5', ); $form->submit('03:04:05'); $this->assertEquals($data, $form->getData()); $this->assertEquals('03:04:05', $form->getViewData()); } public function testSubmitStringSingleText() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'string', 'widget' => 'single_text', )); $form->submit('03:04'); $this->assertEquals('03:04:00', $form->getData()); $this->assertEquals('03:04', $form->getViewData()); } public function testSubmitStringSingleTextWithoutMinutes() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'string', 'widget' => 'single_text', 'with_minutes' => false, )); $form->submit('03'); $this->assertEquals('03:00:00', $form->getData()); $this->assertEquals('03', $form->getViewData()); } public function testSetDataWithoutMinutes() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'datetime', 'with_minutes' => false, )); $form->setData(new \DateTime('03:04:05 UTC')); $this->assertEquals(array('hour' => 3), $form->getViewData()); } public function testSetDataWithSeconds() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'datetime', 'with_seconds' => true, )); $form->setData(new \DateTime('03:04:05 UTC')); $this->assertEquals(array('hour' => 3, 'minute' => 4, 'second' => 5), $form->getViewData()); } public function testSetDataDifferentTimezones() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'America/New_York', 'view_timezone' => 'Asia/Hong_Kong', 'input' => 'string', 'with_seconds' => true, )); $dateTime = new \DateTime('2013-01-01 12:04:05'); $dateTime->setTimezone(new \DateTimeZone('America/New_York')); $form->setData($dateTime->format('H:i:s')); $outputTime = clone $dateTime; $outputTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); $displayedData = array( 'hour' => (int) $outputTime->format('H'), 'minute' => (int) $outputTime->format('i'), 'second' => (int) $outputTime->format('s') ); $this->assertEquals($displayedData, $form->getViewData()); } public function testSetDataDifferentTimezonesDateTime() { $form = $this->factory->create('time', null, array( 'model_timezone' => 'America/New_York', 'view_timezone' => 'Asia/Hong_Kong', 'input' => 'datetime', 'with_seconds' => true, )); $dateTime = new \DateTime('12:04:05'); $dateTime->setTimezone(new \DateTimeZone('America/New_York')); $form->setData($dateTime); $outputTime = clone $dateTime; $outputTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); $displayedData = array( 'hour' => (int) $outputTime->format('H'), 'minute' => (int) $outputTime->format('i'), 'second' => (int) $outputTime->format('s') ); $this->assertDateTimeEquals($dateTime, $form->getData()); $this->assertEquals($displayedData, $form->getViewData()); } public function testHoursOption() { $form = $this->factory->create('time', null, array( 'hours' => array(6, 7), )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('6', '6', '06'), new ChoiceView('7', '7', '07'), ), $view['hour']->vars['choices']); } public function testIsMinuteWithinRangeReturnsTrueIfWithin() { $form = $this->factory->create('time', null, array( 'minutes' => array(6, 7), )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('6', '6', '06'), new ChoiceView('7', '7', '07'), ), $view['minute']->vars['choices']); } public function testIsSecondWithinRangeReturnsTrueIfWithin() { $form = $this->factory->create('time', null, array( 'seconds' => array(6, 7), 'with_seconds' => true, )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('6', '6', '06'), new ChoiceView('7', '7', '07'), ), $view['second']->vars['choices']); } public function testIsPartiallyFilledReturnsFalseIfCompletelyEmpty() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('time', null, array( 'widget' => 'choice', )); $form->submit(array( 'hour' => '', 'minute' => '', )); $this->assertFalse($form->isPartiallyFilled()); } public function testIsPartiallyFilledReturnsFalseIfCompletelyEmptyWithSeconds() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('time', null, array( 'widget' => 'choice', 'with_seconds' => true, )); $form->submit(array( 'hour' => '', 'minute' => '', 'second' => '', )); $this->assertFalse($form->isPartiallyFilled()); } public function testIsPartiallyFilledReturnsFalseIfCompletelyFilled() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('time', null, array( 'widget' => 'choice', )); $form->submit(array( 'hour' => '0', 'minute' => '0', )); $this->assertFalse($form->isPartiallyFilled()); } public function testIsPartiallyFilledReturnsFalseIfCompletelyFilledWithSeconds() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('time', null, array( 'widget' => 'choice', 'with_seconds' => true, )); $form->submit(array( 'hour' => '0', 'minute' => '0', 'second' => '0', )); $this->assertFalse($form->isPartiallyFilled()); } public function testIsPartiallyFilledReturnsTrueIfChoiceAndHourEmpty() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('time', null, array( 'widget' => 'choice', 'with_seconds' => true, )); $form->submit(array( 'hour' => '', 'minute' => '0', 'second' => '0', )); $this->assertTrue($form->isPartiallyFilled()); } public function testIsPartiallyFilledReturnsTrueIfChoiceAndMinuteEmpty() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('time', null, array( 'widget' => 'choice', 'with_seconds' => true, )); $form->submit(array( 'hour' => '0', 'minute' => '', 'second' => '0', )); $this->assertTrue($form->isPartiallyFilled()); } public function testIsPartiallyFilledReturnsTrueIfChoiceAndSecondsEmpty() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('time', null, array( 'widget' => 'choice', 'with_seconds' => true, )); $form->submit(array( 'hour' => '0', 'minute' => '0', 'second' => '', )); $this->assertTrue($form->isPartiallyFilled()); } // Bug fix public function testInitializeWithDateTime() { // Throws an exception if "data_class" option is not explicitly set // to null in the type $this->factory->create('time', new \DateTime()); } public function testSingleTextWidgetShouldUseTheRightInputType() { $form = $this->factory->create('time', null, array( 'widget' => 'single_text', )); $view = $form->createView(); $this->assertEquals('time', $view->vars['type']); } public function testPassDefaultEmptyValueToViewIfNotRequired() { $form = $this->factory->create('time', null, array( 'required' => false, 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('', $view['hour']->vars['empty_value']); $this->assertSame('', $view['minute']->vars['empty_value']); $this->assertSame('', $view['second']->vars['empty_value']); } public function testPassNoEmptyValueToViewIfRequired() { $form = $this->factory->create('time', null, array( 'required' => true, 'with_seconds' => true, )); $view = $form->createView(); $this->assertNull($view['hour']->vars['empty_value']); $this->assertNull($view['minute']->vars['empty_value']); $this->assertNull($view['second']->vars['empty_value']); } public function testPassEmptyValueAsString() { $form = $this->factory->create('time', null, array( 'empty_value' => 'Empty', 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('Empty', $view['hour']->vars['empty_value']); $this->assertSame('Empty', $view['minute']->vars['empty_value']); $this->assertSame('Empty', $view['second']->vars['empty_value']); } public function testPassEmptyValueAsArray() { $form = $this->factory->create('time', null, array( 'empty_value' => array( 'hour' => 'Empty hour', 'minute' => 'Empty minute', 'second' => 'Empty second', ), 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('Empty hour', $view['hour']->vars['empty_value']); $this->assertSame('Empty minute', $view['minute']->vars['empty_value']); $this->assertSame('Empty second', $view['second']->vars['empty_value']); } public function testPassEmptyValueAsPartialArrayAddEmptyIfNotRequired() { $form = $this->factory->create('time', null, array( 'required' => false, 'empty_value' => array( 'hour' => 'Empty hour', 'second' => 'Empty second', ), 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('Empty hour', $view['hour']->vars['empty_value']); $this->assertSame('', $view['minute']->vars['empty_value']); $this->assertSame('Empty second', $view['second']->vars['empty_value']); } public function testPassEmptyValueAsPartialArrayAddNullIfRequired() { $form = $this->factory->create('time', null, array( 'required' => true, 'empty_value' => array( 'hour' => 'Empty hour', 'second' => 'Empty second', ), 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('Empty hour', $view['hour']->vars['empty_value']); $this->assertNull($view['minute']->vars['empty_value']); $this->assertSame('Empty second', $view['second']->vars['empty_value']); } public function provideCompoundWidgets() { return array( array('text'), array('choice'), ); } /** * @dataProvider provideCompoundWidgets */ public function testHourErrorsBubbleUp($widget) { $error = new FormError('Invalid!'); $form = $this->factory->create('time', null, array( 'widget' => $widget, )); $form['hour']->addError($error); $this->assertSame(array(), $form['hour']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } /** * @dataProvider provideCompoundWidgets */ public function testMinuteErrorsBubbleUp($widget) { $error = new FormError('Invalid!'); $form = $this->factory->create('time', null, array( 'widget' => $widget, )); $form['minute']->addError($error); $this->assertSame(array(), $form['minute']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } /** * @dataProvider provideCompoundWidgets */ public function testSecondErrorsBubbleUp($widget) { $error = new FormError('Invalid!'); $form = $this->factory->create('time', null, array( 'widget' => $widget, 'with_seconds' => true, )); $form['second']->addError($error); $this->assertSame(array(), $form['second']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } /** * @expectedException \Symfony\Component\Form\Exception\InvalidConfigurationException */ public function testInitializeWithSecondsAndWithoutMinutes() { $this->factory->create('time', null, array( 'with_minutes' => false, 'with_seconds' => true, )); } } Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php000064400000001363152374770060021572 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Intl\Util\IntlTestHelper; class IntegerTypeTest extends TypeTestCase { protected function setUp() { IntlTestHelper::requireIntl($this); parent::setUp(); } public function testSubmitCastsToInteger() { $form = $this->factory->create('integer'); $form->submit('1.678'); $this->assertSame(1, $form->getData()); $this->assertSame('1', $form->getViewData()); } } Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php000064400000056202152374770060021054 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Form\FormError; use Symfony\Component\Intl\Util\IntlTestHelper; class DateTypeTest extends TypeTestCase { protected function setUp() { parent::setUp(); // we test against "de_AT", so we need the full implementation IntlTestHelper::requireFullIntl($this); \Locale::setDefault('de_AT'); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testInvalidWidgetOption() { $this->factory->create('date', null, array( 'widget' => 'fake_widget', )); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testInvalidInputOption() { $this->factory->create('date', null, array( 'input' => 'fake_input', )); } public function testSubmitFromSingleTextDateTimeWithDefaultFormat() { $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'datetime', )); $form->submit('2010-06-02'); $this->assertDateTimeEquals(new \DateTime('2010-06-02 UTC'), $form->getData()); $this->assertEquals('2010-06-02', $form->getViewData()); } public function testSubmitFromSingleTextDateTime() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'datetime', )); $form->submit('2.6.2010'); $this->assertDateTimeEquals(new \DateTime('2010-06-02 UTC'), $form->getData()); $this->assertEquals('02.06.2010', $form->getViewData()); } public function testSubmitFromSingleTextString() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'string', )); $form->submit('2.6.2010'); $this->assertEquals('2010-06-02', $form->getData()); $this->assertEquals('02.06.2010', $form->getViewData()); } public function testSubmitFromSingleTextTimestamp() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'timestamp', )); $form->submit('2.6.2010'); $dateTime = new \DateTime('2010-06-02 UTC'); $this->assertEquals($dateTime->format('U'), $form->getData()); $this->assertEquals('02.06.2010', $form->getViewData()); } public function testSubmitFromSingleTextRaw() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'array', )); $form->submit('2.6.2010'); $output = array( 'day' => '2', 'month' => '6', 'year' => '2010', ); $this->assertEquals($output, $form->getData()); $this->assertEquals('02.06.2010', $form->getViewData()); } public function testSubmitFromText() { $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'text', )); $text = array( 'day' => '2', 'month' => '6', 'year' => '2010', ); $form->submit($text); $dateTime = new \DateTime('2010-06-02 UTC'); $this->assertDateTimeEquals($dateTime, $form->getData()); $this->assertEquals($text, $form->getViewData()); } public function testSubmitFromChoice() { $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'choice', )); $text = array( 'day' => '2', 'month' => '6', 'year' => '2010', ); $form->submit($text); $dateTime = new \DateTime('2010-06-02 UTC'); $this->assertDateTimeEquals($dateTime, $form->getData()); $this->assertEquals($text, $form->getViewData()); } public function testSubmitFromChoiceEmpty() { $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'choice', 'required' => false, )); $text = array( 'day' => '', 'month' => '', 'year' => '', ); $form->submit($text); $this->assertNull($form->getData()); $this->assertEquals($text, $form->getViewData()); } public function testSubmitFromInputDateTimeDifferentPattern() { $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'format' => 'MM*yyyy*dd', 'widget' => 'single_text', 'input' => 'datetime', )); $form->submit('06*2010*02'); $this->assertDateTimeEquals(new \DateTime('2010-06-02 UTC'), $form->getData()); $this->assertEquals('06*2010*02', $form->getViewData()); } public function testSubmitFromInputStringDifferentPattern() { $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'format' => 'MM*yyyy*dd', 'widget' => 'single_text', 'input' => 'string', )); $form->submit('06*2010*02'); $this->assertEquals('2010-06-02', $form->getData()); $this->assertEquals('06*2010*02', $form->getViewData()); } public function testSubmitFromInputTimestampDifferentPattern() { $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'format' => 'MM*yyyy*dd', 'widget' => 'single_text', 'input' => 'timestamp', )); $form->submit('06*2010*02'); $dateTime = new \DateTime('2010-06-02 UTC'); $this->assertEquals($dateTime->format('U'), $form->getData()); $this->assertEquals('06*2010*02', $form->getViewData()); } public function testSubmitFromInputRawDifferentPattern() { $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'format' => 'MM*yyyy*dd', 'widget' => 'single_text', 'input' => 'array', )); $form->submit('06*2010*02'); $output = array( 'day' => '2', 'month' => '6', 'year' => '2010', ); $this->assertEquals($output, $form->getData()); $this->assertEquals('06*2010*02', $form->getViewData()); } /** * @dataProvider provideDateFormats */ public function testDatePatternWithFormatOption($format, $pattern) { $form = $this->factory->create('date', null, array( 'format' => $format, )); $view = $form->createView(); $this->assertEquals($pattern, $view->vars['date_pattern']); } public function provideDateFormats() { return array( array('dMy', '{{ day }}{{ month }}{{ year }}'), array('d-M-yyyy', '{{ day }}-{{ month }}-{{ year }}'), array('M d y', '{{ month }} {{ day }} {{ year }}'), ); } /** * This test is to check that the strings '0', '1', '2', '3' are not accepted * as valid IntlDateFormatter constants for FULL, LONG, MEDIUM or SHORT respectively. * * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testThrowExceptionIfFormatIsNoPattern() { $this->factory->create('date', null, array( 'format' => '0', 'widget' => 'single_text', 'input' => 'string', )); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testThrowExceptionIfFormatDoesNotContainYearMonthAndDay() { $this->factory->create('date', null, array( 'months' => array(6, 7), 'format' => 'yy', )); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testThrowExceptionIfFormatIsNoConstant() { $this->factory->create('date', null, array( 'format' => 105, )); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testThrowExceptionIfFormatIsInvalid() { $this->factory->create('date', null, array( 'format' => array(), )); } public function testSetDataWithDifferentTimezones() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, 'model_timezone' => 'America/New_York', 'view_timezone' => 'Pacific/Tahiti', 'input' => 'string', 'widget' => 'single_text', )); $form->setData('2010-06-02'); $this->assertEquals('01.06.2010', $form->getViewData()); } public function testSetDataWithDifferentTimezonesDateTime() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, 'model_timezone' => 'America/New_York', 'view_timezone' => 'Pacific/Tahiti', 'input' => 'datetime', 'widget' => 'single_text', )); $dateTime = new \DateTime('2010-06-02 America/New_York'); $form->setData($dateTime); $this->assertDateTimeEquals($dateTime, $form->getData()); $this->assertEquals('01.06.2010', $form->getViewData()); } public function testYearsOption() { $form = $this->factory->create('date', null, array( 'years' => array(2010, 2011), )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('2010', '2010', '2010'), new ChoiceView('2011', '2011', '2011'), ), $view['year']->vars['choices']); } public function testMonthsOption() { $form = $this->factory->create('date', null, array( 'months' => array(6, 7), )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('6', '6', '06'), new ChoiceView('7', '7', '07'), ), $view['month']->vars['choices']); } public function testMonthsOptionShortFormat() { $form = $this->factory->create('date', null, array( 'months' => array(1, 4), 'format' => 'dd.MMM.yy', )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('1', '1', 'Jän'), new ChoiceView('4', '4', 'Apr.') ), $view['month']->vars['choices']); } public function testMonthsOptionLongFormat() { $form = $this->factory->create('date', null, array( 'months' => array(1, 4), 'format' => 'dd.MMMM.yy', )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('1', '1', 'Jänner'), new ChoiceView('4', '4', 'April'), ), $view['month']->vars['choices']); } public function testMonthsOptionLongFormatWithDifferentTimezone() { $form = $this->factory->create('date', null, array( 'months' => array(1, 4), 'format' => 'dd.MMMM.yy', )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('1', '1', 'Jänner'), new ChoiceView('4', '4', 'April'), ), $view['month']->vars['choices']); } public function testIsDayWithinRangeReturnsTrueIfWithin() { $form = $this->factory->create('date', null, array( 'days' => array(6, 7), )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('6', '6', '06'), new ChoiceView('7', '7', '07'), ), $view['day']->vars['choices']); } public function testIsPartiallyFilledReturnsFalseIfSingleText() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'single_text', )); $form->submit('7.6.2010'); $this->assertFalse($form->isPartiallyFilled()); } public function testIsPartiallyFilledReturnsFalseIfChoiceAndCompletelyEmpty() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'choice', )); $form->submit(array( 'day' => '', 'month' => '', 'year' => '', )); $this->assertFalse($form->isPartiallyFilled()); } public function testIsPartiallyFilledReturnsFalseIfChoiceAndCompletelyFilled() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'choice', )); $form->submit(array( 'day' => '2', 'month' => '6', 'year' => '2010', )); $this->assertFalse($form->isPartiallyFilled()); } public function testIsPartiallyFilledReturnsTrueIfChoiceAndDayEmpty() { $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('date', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'choice', )); $form->submit(array( 'day' => '', 'month' => '6', 'year' => '2010', )); $this->assertTrue($form->isPartiallyFilled()); } public function testPassDatePatternToView() { $form = $this->factory->create('date'); $view = $form->createView(); $this->assertSame('{{ day }}{{ month }}{{ year }}', $view->vars['date_pattern']); } public function testPassDatePatternToViewDifferentFormat() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::LONG, )); $view = $form->createView(); $this->assertSame('{{ day }}{{ month }}{{ year }}', $view->vars['date_pattern']); } public function testPassDatePatternToViewDifferentPattern() { $form = $this->factory->create('date', null, array( 'format' => 'MMyyyydd' )); $view = $form->createView(); $this->assertSame('{{ month }}{{ year }}{{ day }}', $view->vars['date_pattern']); } public function testPassDatePatternToViewDifferentPatternWithSeparators() { $form = $this->factory->create('date', null, array( 'format' => 'MM*yyyy*dd' )); $view = $form->createView(); $this->assertSame('{{ month }}*{{ year }}*{{ day }}', $view->vars['date_pattern']); } public function testDontPassDatePatternIfText() { $form = $this->factory->create('date', null, array( 'widget' => 'single_text', )); $view = $form->createView(); $this->assertFalse(isset($view->vars['date_pattern'])); } public function testPassWidgetToView() { $form = $this->factory->create('date', null, array( 'widget' => 'single_text', )); $view = $form->createView(); $this->assertSame('single_text', $view->vars['widget']); } // Bug fix public function testInitializeWithDateTime() { // Throws an exception if "data_class" option is not explicitly set // to null in the type $this->factory->create('date', new \DateTime()); } public function testSingleTextWidgetShouldUseTheRightInputType() { $form = $this->factory->create('date', null, array( 'widget' => 'single_text', )); $view = $form->createView(); $this->assertEquals('date', $view->vars['type']); } public function testPassDefaultEmptyValueToViewIfNotRequired() { $form = $this->factory->create('date', null, array( 'required' => false, )); $view = $form->createView(); $this->assertSame('', $view['year']->vars['empty_value']); $this->assertSame('', $view['month']->vars['empty_value']); $this->assertSame('', $view['day']->vars['empty_value']); } public function testPassNoEmptyValueToViewIfRequired() { $form = $this->factory->create('date', null, array( 'required' => true, )); $view = $form->createView(); $this->assertNull($view['year']->vars['empty_value']); $this->assertNull($view['month']->vars['empty_value']); $this->assertNull($view['day']->vars['empty_value']); } public function testPassEmptyValueAsString() { $form = $this->factory->create('date', null, array( 'empty_value' => 'Empty', )); $view = $form->createView(); $this->assertSame('Empty', $view['year']->vars['empty_value']); $this->assertSame('Empty', $view['month']->vars['empty_value']); $this->assertSame('Empty', $view['day']->vars['empty_value']); } public function testPassEmptyValueAsArray() { $form = $this->factory->create('date', null, array( 'empty_value' => array( 'year' => 'Empty year', 'month' => 'Empty month', 'day' => 'Empty day', ), )); $view = $form->createView(); $this->assertSame('Empty year', $view['year']->vars['empty_value']); $this->assertSame('Empty month', $view['month']->vars['empty_value']); $this->assertSame('Empty day', $view['day']->vars['empty_value']); } public function testPassEmptyValueAsPartialArrayAddEmptyIfNotRequired() { $form = $this->factory->create('date', null, array( 'required' => false, 'empty_value' => array( 'year' => 'Empty year', 'day' => 'Empty day', ), )); $view = $form->createView(); $this->assertSame('Empty year', $view['year']->vars['empty_value']); $this->assertSame('', $view['month']->vars['empty_value']); $this->assertSame('Empty day', $view['day']->vars['empty_value']); } public function testPassEmptyValueAsPartialArrayAddNullIfRequired() { $form = $this->factory->create('date', null, array( 'required' => true, 'empty_value' => array( 'year' => 'Empty year', 'day' => 'Empty day', ), )); $view = $form->createView(); $this->assertSame('Empty year', $view['year']->vars['empty_value']); $this->assertNull($view['month']->vars['empty_value']); $this->assertSame('Empty day', $view['day']->vars['empty_value']); } public function testPassHtml5TypeIfSingleTextAndHtml5Format() { $form = $this->factory->create('date', null, array( 'widget' => 'single_text', )); $view = $form->createView(); $this->assertSame('date', $view->vars['type']); } public function testDontPassHtml5TypeIfNotHtml5Format() { $form = $this->factory->create('date', null, array( 'widget' => 'single_text', 'format' => \IntlDateFormatter::MEDIUM, )); $view = $form->createView(); $this->assertFalse(isset($view->vars['type'])); } public function testDontPassHtml5TypeIfNotSingleText() { $form = $this->factory->create('date', null, array( 'widget' => 'text', )); $view = $form->createView(); $this->assertFalse(isset($view->vars['type'])); } public function provideCompoundWidgets() { return array( array('text'), array('choice'), ); } /** * @dataProvider provideCompoundWidgets */ public function testYearErrorsBubbleUp($widget) { $error = new FormError('Invalid!'); $form = $this->factory->create('date', null, array( 'widget' => $widget, )); $form['year']->addError($error); $this->assertSame(array(), $form['year']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } /** * @dataProvider provideCompoundWidgets */ public function testMonthErrorsBubbleUp($widget) { $error = new FormError('Invalid!'); $form = $this->factory->create('date', null, array( 'widget' => $widget, )); $form['month']->addError($error); $this->assertSame(array(), $form['month']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } /** * @dataProvider provideCompoundWidgets */ public function testDayErrorsBubbleUp($widget) { $error = new FormError('Invalid!'); $form = $this->factory->create('date', null, array( 'widget' => $widget, )); $form['day']->addError($error); $this->assertSame(array(), $form['day']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } public function testYearsFor32BitsMachines() { if (4 !== PHP_INT_SIZE) { $this->markTestSkipped( 'PHP must be compiled in 32 bit mode to run this test'); } $form = $this->factory->create('date', null, array( 'years' => range(1900, 2040), )); $view = $form->createView(); $listChoices = array(); foreach (range(1902, 2037) as $y) { $listChoices[] = new ChoiceView($y, $y, $y); } $this->assertEquals($listChoices, $view['year']->vars['choices']); } } Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php000064400000004351152374770060021054 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; class FileTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { // https://github.com/symfony/symfony/pull/5028 public function testSetData() { $form = $this->factory->createBuilder('file')->getForm(); $data = $this->createUploadedFileMock('abcdef', 'original.jpg', true); $form->setData($data); $this->assertSame($data, $form->getData()); } public function testSubmit() { $form = $this->factory->createBuilder('file')->getForm(); $data = $this->createUploadedFileMock('abcdef', 'original.jpg', true); $form->submit($data); $this->assertSame($data, $form->getData()); } // https://github.com/symfony/symfony/issues/6134 public function testSubmitEmpty() { $form = $this->factory->createBuilder('file')->getForm(); $form->submit(null); $this->assertNull($form->getData()); } public function testDontPassValueToView() { $form = $this->factory->create('file'); $form->submit(array( 'file' => $this->createUploadedFileMock('abcdef', 'original.jpg', true), )); $view = $form->createView(); $this->assertEquals('', $view->vars['value']); } private function createUploadedFileMock($name, $originalName, $valid) { $file = $this ->getMockBuilder('Symfony\Component\HttpFoundation\File\UploadedFile') ->disableOriginalConstructor() ->getMock() ; $file ->expects($this->any()) ->method('getBasename') ->will($this->returnValue($name)) ; $file ->expects($this->any()) ->method('getClientOriginalName') ->will($this->returnValue($originalName)) ; $file ->expects($this->any()) ->method('isValid') ->will($this->returnValue($valid)) ; return $file; } } Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php000064400000010650152374770060021046 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; /** * @author Bernhard Schussek */ abstract class BaseTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { public function testPassDisabledAsOption() { $form = $this->factory->create($this->getTestedType(), null, array('disabled' => true)); $this->assertTrue($form->isDisabled()); } public function testPassIdAndNameToView() { $view = $this->factory->createNamed('name', $this->getTestedType()) ->createView(); $this->assertEquals('name', $view->vars['id']); $this->assertEquals('name', $view->vars['name']); $this->assertEquals('name', $view->vars['full_name']); } public function testStripLeadingUnderscoresAndDigitsFromId() { $view = $this->factory->createNamed('_09name', $this->getTestedType()) ->createView(); $this->assertEquals('name', $view->vars['id']); $this->assertEquals('_09name', $view->vars['name']); $this->assertEquals('_09name', $view->vars['full_name']); } public function testPassIdAndNameToViewWithParent() { $view = $this->factory->createNamedBuilder('parent', 'form') ->add('child', $this->getTestedType()) ->getForm() ->createView(); $this->assertEquals('parent_child', $view['child']->vars['id']); $this->assertEquals('child', $view['child']->vars['name']); $this->assertEquals('parent[child]', $view['child']->vars['full_name']); } public function testPassIdAndNameToViewWithGrandParent() { $builder = $this->factory->createNamedBuilder('parent', 'form') ->add('child', 'form'); $builder->get('child')->add('grand_child', $this->getTestedType()); $view = $builder->getForm()->createView(); $this->assertEquals('parent_child_grand_child', $view['child']['grand_child']->vars['id']); $this->assertEquals('grand_child', $view['child']['grand_child']->vars['name']); $this->assertEquals('parent[child][grand_child]', $view['child']['grand_child']->vars['full_name']); } public function testPassTranslationDomainToView() { $form = $this->factory->create($this->getTestedType(), null, array( 'translation_domain' => 'domain', )); $view = $form->createView(); $this->assertSame('domain', $view->vars['translation_domain']); } public function testInheritTranslationDomainFromParent() { $view = $this->factory ->createNamedBuilder('parent', 'form', null, array( 'translation_domain' => 'domain', )) ->add('child', $this->getTestedType()) ->getForm() ->createView(); $this->assertEquals('domain', $view['child']->vars['translation_domain']); } public function testPreferOwnTranslationDomain() { $view = $this->factory ->createNamedBuilder('parent', 'form', null, array( 'translation_domain' => 'parent_domain', )) ->add('child', $this->getTestedType(), array( 'translation_domain' => 'domain', )) ->getForm() ->createView(); $this->assertEquals('domain', $view['child']->vars['translation_domain']); } public function testDefaultTranslationDomain() { $view = $this->factory->createNamedBuilder('parent', 'form') ->add('child', $this->getTestedType()) ->getForm() ->createView(); $this->assertEquals('messages', $view['child']->vars['translation_domain']); } public function testPassLabelToView() { $form = $this->factory->createNamed('__test___field', $this->getTestedType(), null, array('label' => 'My label')); $view = $form->createView(); $this->assertSame('My label', $view->vars['label']); } public function testPassMultipartFalseToView() { $form = $this->factory->create($this->getTestedType()); $view = $form->createView(); $this->assertFalse($view->vars['multipart']); } abstract protected function getTestedType(); } Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php000064400000121266152374770060021374 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { private $choices = array( 'a' => 'Bernhard', 'b' => 'Fabien', 'c' => 'Kris', 'd' => 'Jon', 'e' => 'Roman', ); private $numericChoices = array( 0 => 'Bernhard', 1 => 'Fabien', 2 => 'Kris', 3 => 'Jon', 4 => 'Roman', ); private $objectChoices; protected $groupedChoices = array( 'Symfony' => array( 'a' => 'Bernhard', 'b' => 'Fabien', 'c' => 'Kris', ), 'Doctrine' => array( 'd' => 'Jon', 'e' => 'Roman', ) ); protected function setUp() { parent::setUp(); $this->objectChoices = array( (object) array('id' => 1, 'name' => 'Bernhard'), (object) array('id' => 2, 'name' => 'Fabien'), (object) array('id' => 3, 'name' => 'Kris'), (object) array('id' => 4, 'name' => 'Jon'), (object) array('id' => 5, 'name' => 'Roman'), ); } protected function tearDown() { parent::tearDown(); $this->objectChoices = null; } /** * @expectedException \PHPUnit_Framework_Error */ public function testChoicesOptionExpectsArray() { $this->factory->create('choice', null, array( 'choices' => new \ArrayObject(), )); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testChoiceListOptionExpectsChoiceListInterface() { $this->factory->create('choice', null, array( 'choice_list' => array('foo' => 'foo'), )); } public function testChoiceListAndChoicesCanBeEmpty() { $this->factory->create('choice'); } public function testExpandedChoicesOptionsTurnIntoChildren() { $form = $this->factory->create('choice', null, array( 'expanded' => true, 'choices' => $this->choices, )); $this->assertCount(count($this->choices), $form, 'Each choice should become a new field'); } public function testPlaceholderPresentOnNonRequiredExpandedSingleChoice() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => false, 'choices' => $this->choices, )); $this->assertTrue(isset($form['placeholder'])); $this->assertCount(count($this->choices) + 1, $form, 'Each choice should become a new field'); } public function testPlaceholderNotPresentIfRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => true, 'choices' => $this->choices, )); $this->assertFalse(isset($form['placeholder'])); $this->assertCount(count($this->choices), $form, 'Each choice should become a new field'); } public function testPlaceholderNotPresentIfMultiple() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => true, 'required' => false, 'choices' => $this->choices, )); $this->assertFalse(isset($form['placeholder'])); $this->assertCount(count($this->choices), $form, 'Each choice should become a new field'); } public function testPlaceholderNotPresentIfEmptyChoice() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => false, 'choices' => array( '' => 'Empty', 1 => 'Not empty', ), )); $this->assertFalse(isset($form['placeholder'])); $this->assertCount(2, $form, 'Each choice should become a new field'); } public function testExpandedChoicesOptionsAreFlattened() { $form = $this->factory->create('choice', null, array( 'expanded' => true, 'choices' => $this->groupedChoices, )); $flattened = array(); foreach ($this->groupedChoices as $choices) { $flattened = array_merge($flattened, array_keys($choices)); } $this->assertCount($form->count(), $flattened, 'Each nested choice should become a new field, not the groups'); foreach ($flattened as $value => $choice) { $this->assertTrue($form->has($value), 'Flattened choice is named after it\'s value'); } } public function testExpandedCheckboxesAreNeverRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => true, 'required' => true, 'choices' => $this->choices, )); foreach ($form as $child) { $this->assertFalse($child->isRequired()); } } public function testExpandedRadiosAreRequiredIfChoiceChildIsRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => true, 'choices' => $this->choices, )); foreach ($form as $child) { $this->assertTrue($child->isRequired()); } } public function testExpandedRadiosAreNotRequiredIfChoiceChildIsNotRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => false, 'choices' => $this->choices, )); foreach ($form as $child) { $this->assertFalse($child->isRequired()); } } public function testSubmitSingleNonExpanded() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => false, 'choices' => $this->choices, )); $form->submit('b'); $this->assertEquals('b', $form->getData()); $this->assertEquals('b', $form->getViewData()); } public function testSubmitSingleNonExpandedInvalidChoice() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => false, 'choices' => $this->choices, )); $form->submit('foobar'); $this->assertNull($form->getData()); $this->assertEquals('foobar', $form->getViewData()); $this->assertFalse($form->isSynchronized()); } public function testSubmitSingleNonExpandedObjectChoices() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => false, 'choice_list' => new ObjectChoiceList( $this->objectChoices, // label path 'name', array(), null, // value path 'id' ), )); // "id" value of the second entry $form->submit('2'); $this->assertEquals($this->objectChoices[1], $form->getData()); $this->assertEquals('2', $form->getViewData()); } public function testSubmitMultipleNonExpanded() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => false, 'choices' => $this->choices, )); $form->submit(array('a', 'b')); $this->assertEquals(array('a', 'b'), $form->getData()); $this->assertEquals(array('a', 'b'), $form->getViewData()); } public function testSubmitMultipleNonExpandedInvalidScalarChoice() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => false, 'choices' => $this->choices, )); $form->submit('foobar'); $this->assertNull($form->getData()); $this->assertEquals('foobar', $form->getViewData()); $this->assertFalse($form->isSynchronized()); } public function testSubmitMultipleNonExpandedInvalidArrayChoice() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => false, 'choices' => $this->choices, )); $form->submit(array('a', 'foobar')); $this->assertNull($form->getData()); $this->assertEquals(array('a', 'foobar'), $form->getViewData()); $this->assertFalse($form->isSynchronized()); } public function testSubmitMultipleNonExpandedObjectChoices() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => false, 'choice_list' => new ObjectChoiceList( $this->objectChoices, // label path 'name', array(), null, // value path 'id' ), )); $form->submit(array('2', '3')); $this->assertEquals(array($this->objectChoices[1], $this->objectChoices[2]), $form->getData()); $this->assertEquals(array('2', '3'), $form->getViewData()); } public function testSubmitSingleExpandedRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => true, 'choices' => $this->choices, )); $form->submit('b'); $this->assertSame('b', $form->getData()); $this->assertSame(array( 0 => false, 1 => true, 2 => false, 3 => false, 4 => false, ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertTrue($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertSame('b', $form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedRequiredInvalidChoice() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => true, 'choices' => $this->choices, )); $form->submit('foobar'); $this->assertSame(null, $form->getData()); $this->assertSame('foobar', $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertFalse($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedNonRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => false, 'choices' => $this->choices, )); $form->submit('b'); $this->assertSame('b', $form->getData()); $this->assertSame(array( 0 => false, 1 => true, 2 => false, 3 => false, 4 => false, 'placeholder' => false, ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertFalse($form['placeholder']->getData()); $this->assertFalse($form[0]->getData()); $this->assertTrue($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form['placeholder']->getViewData()); $this->assertNull($form[0]->getViewData()); $this->assertSame('b', $form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedNonRequiredInvalidChoice() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => false, 'choices' => $this->choices, )); $form->submit('foobar'); $this->assertSame(null, $form->getData()); $this->assertSame('foobar', $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertFalse($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedRequiredNull() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => true, 'choices' => $this->choices, )); $form->submit(null); $this->assertNull($form->getData()); $this->assertSame(array( 0 => false, 1 => false, 2 => false, 3 => false, 4 => false, ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedRequiredEmpty() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => true, 'choices' => $this->choices, )); $form->submit(''); $this->assertNull($form->getData()); $this->assertSame(array( 0 => false, 1 => false, 2 => false, 3 => false, 4 => false, ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedRequiredFalse() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => true, 'choices' => $this->choices, )); $form->submit(false); $this->assertNull($form->getData()); $this->assertSame(array( 0 => false, 1 => false, 2 => false, 3 => false, 4 => false, ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedNonRequiredNull() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => false, 'choices' => $this->choices, )); $form->submit(null); $this->assertNull($form->getData()); $this->assertSame(array( 0 => false, 1 => false, 2 => false, 3 => false, 4 => false, 'placeholder' => true, ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertTrue($form['placeholder']->getData()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertSame('', $form['placeholder']->getViewData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedNonRequiredEmpty() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => false, 'choices' => $this->choices, )); $form->submit(''); $this->assertNull($form->getData()); $this->assertSame(array( 0 => false, 1 => false, 2 => false, 3 => false, 4 => false, 'placeholder' => true, ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertTrue($form['placeholder']->getData()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertSame('', $form['placeholder']->getViewData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedNonRequiredFalse() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'required' => false, 'choices' => $this->choices, )); $form->submit(false); $this->assertNull($form->getData()); $this->assertSame(array( 0 => false, 1 => false, 2 => false, 3 => false, 4 => false, 'placeholder' => true, ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertTrue($form['placeholder']->getData()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertSame('', $form['placeholder']->getViewData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedWithEmptyChild() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'choices' => array( '' => 'Empty', 1 => 'Not empty', ), )); $form->submit(''); $this->assertNull($form->getData()); $this->assertTrue($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertSame('', $form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); } public function testSubmitSingleExpandedObjectChoices() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'choice_list' => new ObjectChoiceList( $this->objectChoices, // label path 'name', array(), null, // value path 'id' ), )); $form->submit('2'); $this->assertSame($this->objectChoices[1], $form->getData()); $this->assertFalse($form[0]->getData()); $this->assertTrue($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertSame('2', $form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedNumericChoices() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, 'choices' => $this->numericChoices, )); $form->submit('1'); $this->assertSame(1, $form->getData()); $this->assertFalse($form[0]->getData()); $this->assertTrue($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertSame('1', $form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitMultipleExpanded() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => true, 'choices' => $this->choices, )); $form->submit(array('a', 'c')); $this->assertSame(array('a', 'c'), $form->getData()); $this->assertSame(array( 0 => true, 1 => false, 2 => true, 3 => false, 4 => false, ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertTrue($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertTrue($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertSame('a', $form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertSame('c', $form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitMultipleExpandedInvalidScalarChoice() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => true, 'choices' => $this->choices, )); $form->submit('foobar'); $this->assertNull($form->getData()); $this->assertSame('foobar', $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertFalse($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitMultipleExpandedInvalidArrayChoice() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => true, 'choices' => $this->choices, )); $form->submit(array('a', 'foobar')); $this->assertNull($form->getData()); $this->assertSame(array('a', 'foobar'), $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertFalse($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitMultipleExpandedEmpty() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => true, 'choices' => $this->choices, )); $form->submit(array()); $this->assertSame(array(), $form->getData()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitMultipleExpandedWithEmptyChild() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => true, 'choices' => array( '' => 'Empty', 1 => 'Not Empty', 2 => 'Not Empty 2', ) )); $form->submit(array('', '2')); $this->assertSame(array('', 2), $form->getData()); $this->assertTrue($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertTrue($form[2]->getData()); $this->assertSame('', $form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertSame('2', $form[2]->getViewData()); } public function testSubmitMultipleExpandedObjectChoices() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => true, 'choice_list' => new ObjectChoiceList( $this->objectChoices, // label path 'name', array(), null, // value path 'id' ), )); $form->submit(array('1', '2')); $this->assertSame(array($this->objectChoices[0], $this->objectChoices[1]), $form->getData()); $this->assertTrue($form[0]->getData()); $this->assertTrue($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertSame('1', $form[0]->getViewData()); $this->assertSame('2', $form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } public function testSubmitMultipleExpandedNumericChoices() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => true, 'choices' => $this->numericChoices, )); $form->submit(array('1', '2')); $this->assertSame(array(1, 2), $form->getData()); $this->assertFalse($form[0]->getData()); $this->assertTrue($form[1]->getData()); $this->assertTrue($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); $this->assertNull($form[0]->getViewData()); $this->assertSame('1', $form[1]->getViewData()); $this->assertSame('2', $form[2]->getViewData()); $this->assertNull($form[3]->getViewData()); $this->assertNull($form[4]->getViewData()); } /* * We need this functionality to create choice fields for Boolean types, * e.g. false => 'No', true => 'Yes' */ public function testSetDataSingleNonExpandedAcceptsBoolean() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => false, 'choices' => $this->numericChoices, )); $form->setData(false); $this->assertFalse($form->getData()); $this->assertEquals('0', $form->getViewData()); } public function testSetDataMultipleNonExpandedAcceptsBoolean() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'expanded' => false, 'choices' => $this->numericChoices, )); $form->setData(array(false, true)); $this->assertEquals(array(false, true), $form->getData()); $this->assertEquals(array('0', '1'), $form->getViewData()); } public function testPassRequiredToView() { $form = $this->factory->create('choice', null, array( 'choices' => $this->choices, )); $view = $form->createView(); $this->assertTrue($view->vars['required']); } public function testPassNonRequiredToView() { $form = $this->factory->create('choice', null, array( 'required' => false, 'choices' => $this->choices, )); $view = $form->createView(); $this->assertFalse($view->vars['required']); } public function testPassMultipleToView() { $form = $this->factory->create('choice', null, array( 'multiple' => true, 'choices' => $this->choices, )); $view = $form->createView(); $this->assertTrue($view->vars['multiple']); } public function testPassExpandedToView() { $form = $this->factory->create('choice', null, array( 'expanded' => true, 'choices' => $this->choices, )); $view = $form->createView(); $this->assertTrue($view->vars['expanded']); } public function testEmptyValueIsNullByDefaultIfRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'required' => true, 'choices' => $this->choices, )); $view = $form->createView(); $this->assertNull($view->vars['empty_value']); } public function testEmptyValueIsEmptyStringByDefaultIfNotRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'required' => false, 'choices' => $this->choices, )); $view = $form->createView(); $this->assertSame('', $view->vars['empty_value']); } /** * @dataProvider getOptionsWithEmptyValue */ public function testPassEmptyValueToView($multiple, $expanded, $required, $emptyValue, $viewValue) { $form = $this->factory->create('choice', null, array( 'multiple' => $multiple, 'expanded' => $expanded, 'required' => $required, 'empty_value' => $emptyValue, 'choices' => $this->choices, )); $view = $form->createView(); $this->assertEquals($viewValue, $view->vars['empty_value']); $this->assertFalse($view->vars['empty_value_in_choices']); } /** * @dataProvider getOptionsWithEmptyValue */ public function testDontPassEmptyValueIfContainedInChoices($multiple, $expanded, $required, $emptyValue, $viewValue) { $form = $this->factory->create('choice', null, array( 'multiple' => $multiple, 'expanded' => $expanded, 'required' => $required, 'empty_value' => $emptyValue, 'choices' => array('a' => 'A', '' => 'Empty'), )); $view = $form->createView(); $this->assertNull($view->vars['empty_value']); $this->assertTrue($view->vars['empty_value_in_choices']); } public function getOptionsWithEmptyValue() { return array( // single non-expanded array(false, false, false, 'foobar', 'foobar'), array(false, false, false, '', ''), array(false, false, false, null, null), array(false, false, false, false, null), array(false, false, true, 'foobar', 'foobar'), array(false, false, true, '', ''), array(false, false, true, null, null), array(false, false, true, false, null), // single expanded array(false, true, false, 'foobar', 'foobar'), // radios should never have an empty label array(false, true, false, '', 'None'), array(false, true, false, null, null), array(false, true, false, false, null), array(false, true, true, 'foobar', 'foobar'), // radios should never have an empty label array(false, true, true, '', 'None'), array(false, true, true, null, null), array(false, true, true, false, null), // multiple non-expanded array(true, false, false, 'foobar', null), array(true, false, false, '', null), array(true, false, false, null, null), array(true, false, false, false, null), array(true, false, true, 'foobar', null), array(true, false, true, '', null), array(true, false, true, null, null), array(true, false, true, false, null), // multiple expanded array(true, true, false, 'foobar', null), array(true, true, false, '', null), array(true, true, false, null, null), array(true, true, false, false, null), array(true, true, true, 'foobar', null), array(true, true, true, '', null), array(true, true, true, null, null), array(true, true, true, false, null), ); } public function testPassChoicesToView() { $choices = array('a' => 'A', 'b' => 'B', 'c' => 'C', 'd' => 'D'); $form = $this->factory->create('choice', null, array( 'choices' => $choices, )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView('a', 'a', 'A'), new ChoiceView('b', 'b', 'B'), new ChoiceView('c', 'c', 'C'), new ChoiceView('d', 'd', 'D'), ), $view->vars['choices']); } public function testPassPreferredChoicesToView() { $choices = array('a' => 'A', 'b' => 'B', 'c' => 'C', 'd' => 'D'); $form = $this->factory->create('choice', null, array( 'choices' => $choices, 'preferred_choices' => array('b', 'd'), )); $view = $form->createView(); $this->assertEquals(array( 0 => new ChoiceView('a', 'a', 'A'), 2 => new ChoiceView('c', 'c', 'C'), ), $view->vars['choices']); $this->assertEquals(array( 1 => new ChoiceView('b', 'b', 'B'), 3 => new ChoiceView('d', 'd', 'D'), ), $view->vars['preferred_choices']); } public function testPassHierarchicalChoicesToView() { $form = $this->factory->create('choice', null, array( 'choices' => $this->groupedChoices, 'preferred_choices' => array('b', 'd'), )); $view = $form->createView(); $this->assertEquals(array( 'Symfony' => array( 0 => new ChoiceView('a', 'a', 'Bernhard'), 2 => new ChoiceView('c', 'c', 'Kris'), ), 'Doctrine' => array( 4 => new ChoiceView('e', 'e', 'Roman'), ), ), $view->vars['choices']); $this->assertEquals(array( 'Symfony' => array( 1 => new ChoiceView('b', 'b', 'Fabien'), ), 'Doctrine' => array( 3 => new ChoiceView('d', 'd', 'Jon'), ), ), $view->vars['preferred_choices']); } public function testPassChoiceDataToView() { $obj1 = (object) array('value' => 'a', 'label' => 'A'); $obj2 = (object) array('value' => 'b', 'label' => 'B'); $obj3 = (object) array('value' => 'c', 'label' => 'C'); $obj4 = (object) array('value' => 'd', 'label' => 'D'); $form = $this->factory->create('choice', null, array( 'choice_list' => new ObjectChoiceList(array($obj1, $obj2, $obj3, $obj4), 'label', array(), null, 'value'), )); $view = $form->createView(); $this->assertEquals(array( new ChoiceView($obj1, 'a', 'A'), new ChoiceView($obj2, 'b', 'B'), new ChoiceView($obj3, 'c', 'C'), new ChoiceView($obj4, 'd', 'D'), ), $view->vars['choices']); } public function testAdjustFullNameForMultipleNonExpanded() { $form = $this->factory->createNamed('name', 'choice', null, array( 'multiple' => true, 'expanded' => false, 'choices' => $this->choices, )); $view = $form->createView(); $this->assertSame('name[]', $view->vars['full_name']); } // https://github.com/symfony/symfony/issues/3298 public function testInitializeWithEmptyChoices() { $this->factory->createNamed('name', 'choice', null, array( 'choices' => array(), )); } public function testInitializeWithDefaultObjectChoice() { $obj1 = (object) array('value' => 'a', 'label' => 'A'); $obj2 = (object) array('value' => 'b', 'label' => 'B'); $obj3 = (object) array('value' => 'c', 'label' => 'C'); $obj4 = (object) array('value' => 'd', 'label' => 'D'); $form = $this->factory->create('choice', null, array( 'choice_list' => new ObjectChoiceList(array($obj1, $obj2, $obj3, $obj4), 'label', array(), null, 'value'), // Used to break because "data_class" was inferred, which needs to // remain null in every case (because it refers to the view format) 'data' => $obj3, )); // Trigger data initialization $form->getViewData(); } } Symfony/Component/Form/Tests/Extension/Core/Type/SubmitTypeTest.php000064400000003045152374770060021437 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; /** * @author Bernhard Schussek */ class SubmitTypeTest extends TypeTestCase { public function testCreateSubmitButtonInstances() { $this->assertInstanceOf('Symfony\Component\Form\SubmitButton', $this->factory->create('submit')); } public function testNotClickedByDefault() { $button = $this->factory->create('submit'); $this->assertFalse($button->isClicked()); } public function testNotClickedIfSubmittedWithNull() { $button = $this->factory->create('submit'); $button->submit(null); $this->assertFalse($button->isClicked()); } public function testClickedIfSubmittedWithEmptyString() { $button = $this->factory->create('submit'); $button->submit(''); $this->assertTrue($button->isClicked()); } public function testClickedIfSubmittedWithUnemptyString() { $button = $this->factory->create('submit'); $button->submit('foo'); $this->assertTrue($button->isClicked()); } public function testSubmitCanBeAddedToForm() { $form = $this->factory ->createBuilder('form') ->getForm(); $this->assertSame($form, $form->add('send', 'submit')); } } Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php000064400000036564152374770060021704 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\FormError; use Symfony\Component\Intl\Util\IntlTestHelper; class DateTimeTypeTest extends TypeTestCase { protected function setUp() { IntlTestHelper::requireIntl($this); parent::setUp(); } public function testSubmitDateTime() { $form = $this->factory->create('datetime', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'date_widget' => 'choice', 'time_widget' => 'choice', 'input' => 'datetime', )); $form->submit(array( 'date' => array( 'day' => '2', 'month' => '6', 'year' => '2010', ), 'time' => array( 'hour' => '3', 'minute' => '4', ), )); $dateTime = new \DateTime('2010-06-02 03:04:00 UTC'); $this->assertDateTimeEquals($dateTime, $form->getData()); } public function testSubmitString() { $form = $this->factory->create('datetime', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'string', 'date_widget' => 'choice', 'time_widget' => 'choice', )); $form->submit(array( 'date' => array( 'day' => '2', 'month' => '6', 'year' => '2010', ), 'time' => array( 'hour' => '3', 'minute' => '4', ), )); $this->assertEquals('2010-06-02 03:04:00', $form->getData()); } public function testSubmitTimestamp() { $form = $this->factory->create('datetime', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'timestamp', 'date_widget' => 'choice', 'time_widget' => 'choice', )); $form->submit(array( 'date' => array( 'day' => '2', 'month' => '6', 'year' => '2010', ), 'time' => array( 'hour' => '3', 'minute' => '4', ), )); $dateTime = new \DateTime('2010-06-02 03:04:00 UTC'); $this->assertEquals($dateTime->format('U'), $form->getData()); } public function testSubmitWithoutMinutes() { $form = $this->factory->create('datetime', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'date_widget' => 'choice', 'time_widget' => 'choice', 'input' => 'datetime', 'with_minutes' => false, )); $form->setData(new \DateTime('2010-06-02 03:04:05 UTC')); $input = array( 'date' => array( 'day' => '2', 'month' => '6', 'year' => '2010', ), 'time' => array( 'hour' => '3', ), ); $form->submit($input); $this->assertDateTimeEquals(new \DateTime('2010-06-02 03:00:00 UTC'), $form->getData()); } public function testSubmitWithSeconds() { $form = $this->factory->create('datetime', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'date_widget' => 'choice', 'time_widget' => 'choice', 'input' => 'datetime', 'with_seconds' => true, )); $form->setData(new \DateTime('2010-06-02 03:04:05 UTC')); $input = array( 'date' => array( 'day' => '2', 'month' => '6', 'year' => '2010', ), 'time' => array( 'hour' => '3', 'minute' => '4', 'second' => '5', ), ); $form->submit($input); $this->assertDateTimeEquals(new \DateTime('2010-06-02 03:04:05 UTC'), $form->getData()); } public function testSubmitDifferentTimezones() { $form = $this->factory->create('datetime', null, array( 'model_timezone' => 'America/New_York', 'view_timezone' => 'Pacific/Tahiti', 'date_widget' => 'choice', 'time_widget' => 'choice', 'input' => 'string', 'with_seconds' => true, )); $dateTime = new \DateTime('2010-06-02 03:04:05 Pacific/Tahiti'); $form->submit(array( 'date' => array( 'day' => (int) $dateTime->format('d'), 'month' => (int) $dateTime->format('m'), 'year' => (int) $dateTime->format('Y'), ), 'time' => array( 'hour' => (int) $dateTime->format('H'), 'minute' => (int) $dateTime->format('i'), 'second' => (int) $dateTime->format('s'), ), )); $dateTime->setTimezone(new \DateTimeZone('America/New_York')); $this->assertEquals($dateTime->format('Y-m-d H:i:s'), $form->getData()); } public function testSubmitDifferentTimezonesDateTime() { $form = $this->factory->create('datetime', null, array( 'model_timezone' => 'America/New_York', 'view_timezone' => 'Pacific/Tahiti', 'widget' => 'single_text', 'input' => 'datetime', )); $outputTime = new \DateTime('2010-06-02 03:04:00 Pacific/Tahiti'); $form->submit('2010-06-02T03:04:00-10:00'); $outputTime->setTimezone(new \DateTimeZone('America/New_York')); $this->assertDateTimeEquals($outputTime, $form->getData()); $this->assertEquals('2010-06-02T03:04:00-10:00', $form->getViewData()); } public function testSubmitStringSingleText() { $form = $this->factory->create('datetime', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'string', 'widget' => 'single_text', )); $form->submit('2010-06-02T03:04:00Z'); $this->assertEquals('2010-06-02 03:04:00', $form->getData()); $this->assertEquals('2010-06-02T03:04:00Z', $form->getViewData()); } public function testSubmitStringSingleTextWithSeconds() { $form = $this->factory->create('datetime', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'input' => 'string', 'widget' => 'single_text', 'with_seconds' => true, )); $form->submit('2010-06-02T03:04:05Z'); $this->assertEquals('2010-06-02 03:04:05', $form->getData()); $this->assertEquals('2010-06-02T03:04:05Z', $form->getViewData()); } public function testSubmitDifferentPattern() { $form = $this->factory->create('datetime', null, array( 'date_format' => 'MM*yyyy*dd', 'date_widget' => 'single_text', 'time_widget' => 'single_text', 'input' => 'datetime', )); $dateTime = new \DateTime('2010-06-02 03:04'); $form->submit(array( 'date' => '06*2010*02', 'time' => '03:04', )); $this->assertDateTimeEquals($dateTime, $form->getData()); } // Bug fix public function testInitializeWithDateTime() { // Throws an exception if "data_class" option is not explicitly set // to null in the type $this->factory->create('datetime', new \DateTime()); } public function testSingleTextWidgetShouldUseTheRightInputType() { $form = $this->factory->create('datetime', null, array( 'widget' => 'single_text', )); $view = $form->createView(); $this->assertEquals('datetime', $view->vars['type']); } public function testPassDefaultEmptyValueToViewIfNotRequired() { $form = $this->factory->create('datetime', null, array( 'required' => false, 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('', $view['date']['year']->vars['empty_value']); $this->assertSame('', $view['date']['month']->vars['empty_value']); $this->assertSame('', $view['date']['day']->vars['empty_value']); $this->assertSame('', $view['time']['hour']->vars['empty_value']); $this->assertSame('', $view['time']['minute']->vars['empty_value']); $this->assertSame('', $view['time']['second']->vars['empty_value']); } public function testPassNoEmptyValueToViewIfRequired() { $form = $this->factory->create('datetime', null, array( 'required' => true, 'with_seconds' => true, )); $view = $form->createView(); $this->assertNull($view['date']['year']->vars['empty_value']); $this->assertNull($view['date']['month']->vars['empty_value']); $this->assertNull($view['date']['day']->vars['empty_value']); $this->assertNull($view['time']['hour']->vars['empty_value']); $this->assertNull($view['time']['minute']->vars['empty_value']); $this->assertNull($view['time']['second']->vars['empty_value']); } public function testPassEmptyValueAsString() { $form = $this->factory->create('datetime', null, array( 'empty_value' => 'Empty', 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('Empty', $view['date']['year']->vars['empty_value']); $this->assertSame('Empty', $view['date']['month']->vars['empty_value']); $this->assertSame('Empty', $view['date']['day']->vars['empty_value']); $this->assertSame('Empty', $view['time']['hour']->vars['empty_value']); $this->assertSame('Empty', $view['time']['minute']->vars['empty_value']); $this->assertSame('Empty', $view['time']['second']->vars['empty_value']); } public function testPassEmptyValueAsArray() { $form = $this->factory->create('datetime', null, array( 'empty_value' => array( 'year' => 'Empty year', 'month' => 'Empty month', 'day' => 'Empty day', 'hour' => 'Empty hour', 'minute' => 'Empty minute', 'second' => 'Empty second', ), 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('Empty year', $view['date']['year']->vars['empty_value']); $this->assertSame('Empty month', $view['date']['month']->vars['empty_value']); $this->assertSame('Empty day', $view['date']['day']->vars['empty_value']); $this->assertSame('Empty hour', $view['time']['hour']->vars['empty_value']); $this->assertSame('Empty minute', $view['time']['minute']->vars['empty_value']); $this->assertSame('Empty second', $view['time']['second']->vars['empty_value']); } public function testPassEmptyValueAsPartialArrayAddEmptyIfNotRequired() { $form = $this->factory->create('datetime', null, array( 'required' => false, 'empty_value' => array( 'year' => 'Empty year', 'day' => 'Empty day', 'hour' => 'Empty hour', 'second' => 'Empty second', ), 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('Empty year', $view['date']['year']->vars['empty_value']); $this->assertSame('', $view['date']['month']->vars['empty_value']); $this->assertSame('Empty day', $view['date']['day']->vars['empty_value']); $this->assertSame('Empty hour', $view['time']['hour']->vars['empty_value']); $this->assertSame('', $view['time']['minute']->vars['empty_value']); $this->assertSame('Empty second', $view['time']['second']->vars['empty_value']); } public function testPassEmptyValueAsPartialArrayAddNullIfRequired() { $form = $this->factory->create('datetime', null, array( 'required' => true, 'empty_value' => array( 'year' => 'Empty year', 'day' => 'Empty day', 'hour' => 'Empty hour', 'second' => 'Empty second', ), 'with_seconds' => true, )); $view = $form->createView(); $this->assertSame('Empty year', $view['date']['year']->vars['empty_value']); $this->assertNull($view['date']['month']->vars['empty_value']); $this->assertSame('Empty day', $view['date']['day']->vars['empty_value']); $this->assertSame('Empty hour', $view['time']['hour']->vars['empty_value']); $this->assertNull($view['time']['minute']->vars['empty_value']); $this->assertSame('Empty second', $view['time']['second']->vars['empty_value']); } public function testPassHtml5TypeIfSingleTextAndHtml5Format() { $form = $this->factory->create('datetime', null, array( 'widget' => 'single_text', )); $view = $form->createView(); $this->assertSame('datetime', $view->vars['type']); } public function testDontPassHtml5TypeIfNotHtml5Format() { $form = $this->factory->create('datetime', null, array( 'widget' => 'single_text', 'format' => 'yyyy-MM-dd HH:mm', )); $view = $form->createView(); $this->assertFalse(isset($view->vars['type'])); } public function testDontPassHtml5TypeIfNotSingleText() { $form = $this->factory->create('datetime', null, array( 'widget' => 'text', )); $view = $form->createView(); $this->assertFalse(isset($view->vars['type'])); } public function testDateTypeChoiceErrorsBubbleUp() { $error = new FormError('Invalid!'); $form = $this->factory->create('datetime', null); $form['date']->addError($error); $this->assertSame(array(), $form['date']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } public function testDateTypeSingleTextErrorsBubbleUp() { $error = new FormError('Invalid!'); $form = $this->factory->create('datetime', null, array( 'date_widget' => 'single_text' )); $form['date']->addError($error); $this->assertSame(array(), $form['date']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } public function testTimeTypeChoiceErrorsBubbleUp() { $error = new FormError('Invalid!'); $form = $this->factory->create('datetime', null); $form['time']->addError($error); $this->assertSame(array(), $form['time']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } public function testTimeTypeSingleTextErrorsBubbleUp() { $error = new FormError('Invalid!'); $form = $this->factory->create('datetime', null, array( 'time_widget' => 'single_text' )); $form['time']->addError($error); $this->assertSame(array(), $form['time']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } } Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.php000064400000012264152374770060021730 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; class RepeatedTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { protected $form; protected function setUp() { parent::setUp(); $this->form = $this->factory->create('repeated', null, array( 'type' => 'text', )); $this->form->setData(null); } public function testSetData() { $this->form->setData('foobar'); $this->assertEquals('foobar', $this->form['first']->getData()); $this->assertEquals('foobar', $this->form['second']->getData()); } public function testSetOptions() { $form = $this->factory->create('repeated', null, array( 'type' => 'text', 'options' => array('label' => 'Global'), )); $this->assertEquals('Global', $form['first']->getConfig()->getOption('label')); $this->assertEquals('Global', $form['second']->getConfig()->getOption('label')); $this->assertTrue($form['first']->isRequired()); $this->assertTrue($form['second']->isRequired()); } public function testSetOptionsPerChild() { $form = $this->factory->create('repeated', null, array( // the global required value cannot be overridden 'type' => 'text', 'first_options' => array('label' => 'Test', 'required' => false), 'second_options' => array('label' => 'Test2') )); $this->assertEquals('Test', $form['first']->getConfig()->getOption('label')); $this->assertEquals('Test2', $form['second']->getConfig()->getOption('label')); $this->assertTrue($form['first']->isRequired()); $this->assertTrue($form['second']->isRequired()); } public function testSetRequired() { $form = $this->factory->create('repeated', null, array( 'required' => false, 'type' => 'text', )); $this->assertFalse($form['first']->isRequired()); $this->assertFalse($form['second']->isRequired()); } public function testSetErrorBubblingToTrue() { $form = $this->factory->create('repeated', null, array( 'error_bubbling' => true, )); $this->assertTrue($form->getConfig()->getOption('error_bubbling')); $this->assertTrue($form['first']->getConfig()->getOption('error_bubbling')); $this->assertTrue($form['second']->getConfig()->getOption('error_bubbling')); } public function testSetErrorBubblingToFalse() { $form = $this->factory->create('repeated', null, array( 'error_bubbling' => false, )); $this->assertFalse($form->getConfig()->getOption('error_bubbling')); $this->assertFalse($form['first']->getConfig()->getOption('error_bubbling')); $this->assertFalse($form['second']->getConfig()->getOption('error_bubbling')); } public function testSetErrorBubblingIndividually() { $form = $this->factory->create('repeated', null, array( 'error_bubbling' => true, 'options' => array('error_bubbling' => false), 'second_options' => array('error_bubbling' => true), )); $this->assertTrue($form->getConfig()->getOption('error_bubbling')); $this->assertFalse($form['first']->getConfig()->getOption('error_bubbling')); $this->assertTrue($form['second']->getConfig()->getOption('error_bubbling')); } public function testSetOptionsPerChildAndOverwrite() { $form = $this->factory->create('repeated', null, array( 'type' => 'text', 'options' => array('label' => 'Label'), 'second_options' => array('label' => 'Second label') )); $this->assertEquals('Label', $form['first']->getConfig()->getOption('label')); $this->assertEquals('Second label', $form['second']->getConfig()->getOption('label')); $this->assertTrue($form['first']->isRequired()); $this->assertTrue($form['second']->isRequired()); } public function testSubmitUnequal() { $input = array('first' => 'foo', 'second' => 'bar'); $this->form->submit($input); $this->assertEquals('foo', $this->form['first']->getViewData()); $this->assertEquals('bar', $this->form['second']->getViewData()); $this->assertFalse($this->form->isSynchronized()); $this->assertEquals($input, $this->form->getViewData()); $this->assertNull($this->form->getData()); } public function testSubmitEqual() { $input = array('first' => 'foo', 'second' => 'foo'); $this->form->submit($input); $this->assertEquals('foo', $this->form['first']->getViewData()); $this->assertEquals('foo', $this->form['second']->getViewData()); $this->assertTrue($this->form->isSynchronized()); $this->assertEquals($input, $this->form->getViewData()); $this->assertEquals('foo', $this->form->getData()); } } Symfony/Component/Form/Tests/Extension/Core/Type/UrlTypeTest.php000064400000003300152374770060020730 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; class UrlTypeTest extends TypeTestCase { public function testSubmitAddsDefaultProtocolIfNoneIsIncluded() { $form = $this->factory->create('url', 'name'); $form->submit('www.domain.com'); $this->assertSame('http://www.domain.com', $form->getData()); $this->assertSame('http://www.domain.com', $form->getViewData()); } public function testSubmitAddsNoDefaultProtocolIfAlreadyIncluded() { $form = $this->factory->create('url', null, array( 'default_protocol' => 'http', )); $form->submit('ftp://www.domain.com'); $this->assertSame('ftp://www.domain.com', $form->getData()); $this->assertSame('ftp://www.domain.com', $form->getViewData()); } public function testSubmitAddsNoDefaultProtocolIfEmpty() { $form = $this->factory->create('url', null, array( 'default_protocol' => 'http', )); $form->submit(''); $this->assertNull($form->getData()); $this->assertSame('', $form->getViewData()); } public function testSubmitAddsNoDefaultProtocolIfSetToNull() { $form = $this->factory->create('url', null, array( 'default_protocol' => null, )); $form->submit('www.domain.com'); $this->assertSame('www.domain.com', $form->getData()); $this->assertSame('www.domain.com', $form->getViewData()); } } Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php000064400000001674152374770060023556 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Test\FormPerformanceTestCase; /** * @author Bernhard Schussek */ class ChoiceTypePerformanceTest extends FormPerformanceTestCase { /** * This test case is realistic in collection forms where each * row contains the same choice field. * * @group benchmark */ public function testSameChoiceFieldCreatedMultipleTimes() { $this->setMaxRunningTime(1); $choices = range(1, 300); for ($i = 0; $i < 100; ++$i) { $this->factory->create('choice', rand(1, 400), array( 'choices' => $choices, )); } } } Symfony/Component/Form/Tests/Extension/Core/Type/TypeTestCase.php000064400000001072152374770060021045 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Test\TypeTestCase as BaseTypeTestCase; /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use Symfony\Component\Form\Test\TypeTestCase instead. */ abstract class TypeTestCase extends BaseTypeTestCase { } Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.php000064400000002060152374770060021762 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Intl\Util\IntlTestHelper; class CurrencyTypeTest extends TypeTestCase { protected function setUp() { IntlTestHelper::requireIntl($this); parent::setUp(); } public function testCurrenciesAreSelectable() { $form = $this->factory->create('currency'); $view = $form->createView(); $choices = $view->vars['choices']; $this->assertContains(new ChoiceView('EUR', 'EUR', 'Euro'), $choices, '', false, false); $this->assertContains(new ChoiceView('USD', 'USD', 'US Dollar'), $choices, '', false, false); $this->assertContains(new ChoiceView('SIT', 'SIT', 'Slovenian Tolar'), $choices, '', false, false); } } Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php000064400000003100152374770060021707 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Intl\Util\IntlTestHelper; class LanguageTypeTest extends TypeTestCase { protected function setUp() { IntlTestHelper::requireIntl($this); parent::setUp(); } public function testCountriesAreSelectable() { $form = $this->factory->create('language'); $view = $form->createView(); $choices = $view->vars['choices']; $this->assertContains(new ChoiceView('en', 'en', 'English'), $choices, '', false, false); $this->assertContains(new ChoiceView('en_GB', 'en_GB', 'British English'), $choices, '', false, false); $this->assertContains(new ChoiceView('en_US', 'en_US', 'U.S. English'), $choices, '', false, false); $this->assertContains(new ChoiceView('fr', 'fr', 'French'), $choices, '', false, false); $this->assertContains(new ChoiceView('my', 'my', 'Burmese'), $choices, '', false, false); } public function testMultipleLanguagesIsNotIncluded() { $form = $this->factory->create('language', 'language'); $view = $form->createView(); $choices = $view->vars['choices']; $this->assertNotContains(new ChoiceView('mul', 'mul', 'Mehrsprachig'), $choices, '', false, false); } } Symfony/Component/Form/Tests/Extension/Core/Type/NumberTypeTest.php000064400000003364152374770060021430 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Intl\Util\IntlTestHelper; class NumberTypeTest extends TypeTestCase { protected function setUp() { parent::setUp(); // we test against "de_DE", so we need the full implementation IntlTestHelper::requireFullIntl($this); \Locale::setDefault('de_DE'); } public function testDefaultFormatting() { $form = $this->factory->create('number'); $form->setData('12345.67890'); $view = $form->createView(); $this->assertSame('12345,679', $view->vars['value']); } public function testDefaultFormattingWithGrouping() { $form = $this->factory->create('number', null, array('grouping' => true)); $form->setData('12345.67890'); $view = $form->createView(); $this->assertSame('12.345,679', $view->vars['value']); } public function testDefaultFormattingWithPrecision() { $form = $this->factory->create('number', null, array('precision' => 2)); $form->setData('12345.67890'); $view = $form->createView(); $this->assertSame('12345,68', $view->vars['value']); } public function testDefaultFormattingWithRounding() { $form = $this->factory->create('number', null, array('precision' => 0, 'rounding_mode' => \NumberFormatter::ROUND_UP)); $form->setData('12345.54321'); $view = $form->createView(); $this->assertSame('12346', $view->vars['value']); } } Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.php000064400000003324152374770060021263 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Intl\Util\IntlTestHelper; class MoneyTypeTest extends TypeTestCase { protected function setUp() { // we test against different locales, so we need the full // implementation IntlTestHelper::requireFullIntl($this); parent::setUp(); } public function testPassMoneyPatternToView() { \Locale::setDefault('de_DE'); $form = $this->factory->create('money'); $view = $form->createView(); $this->assertSame('{{ widget }} €', $view->vars['money_pattern']); } public function testMoneyPatternWorksForYen() { \Locale::setDefault('en_US'); $form = $this->factory->create('money', null, array('currency' => 'JPY')); $view = $form->createView(); $this->assertTrue((Boolean) strstr($view->vars['money_pattern'], 'Â¥')); } // https://github.com/symfony/symfony/issues/5458 public function testPassDifferentPatternsForDifferentCurrencies() { \Locale::setDefault('de_DE'); $form1 = $this->factory->create('money', null, array('currency' => 'GBP')); $form2 = $this->factory->create('money', null, array('currency' => 'EUR')); $view1 = $form1->createView(); $view2 = $form2->createView(); $this->assertSame('{{ widget }} £', $view1->vars['money_pattern']); $this->assertSame('{{ widget }} €', $view2->vars['money_pattern']); } } Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.php000064400000001201152374770060021437 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; /** * @author Bernhard Schussek */ class ButtonTypeTest extends BaseTypeTest { public function testCreateButtonInstances() { $this->assertInstanceOf('Symfony\Component\Form\Button', $this->factory->create('button')); } protected function getTestedType() { return 'button'; } } Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php000064400000001765152374770060021775 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; class TimezoneTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { public function testTimezonesAreSelectable() { $form = $this->factory->create('timezone'); $view = $form->createView(); $choices = $view->vars['choices']; $this->assertArrayHasKey('Africa', $choices); $this->assertContains(new ChoiceView('Africa/Kinshasa', 'Africa/Kinshasa', 'Kinshasa'), $choices['Africa'], '', false, false); $this->assertArrayHasKey('America', $choices); $this->assertContains(new ChoiceView('America/New_York', 'America/New_York', 'New York'), $choices['America'], '', false, false); } } Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php000064400000045147152374770060021110 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Form\Form; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Tests\Fixtures\Author; use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; use Symfony\Component\Form\FormError; class FormTest_AuthorWithoutRefSetter { protected $reference; protected $referenceCopy; public function __construct($reference) { $this->reference = $reference; $this->referenceCopy = $reference; } // The returned object should be modified by reference without having // to provide a setReference() method public function getReference() { return $this->reference; } // The returned object is a copy, so setReferenceCopy() must be used // to update it public function getReferenceCopy() { return is_object($this->referenceCopy) ? clone $this->referenceCopy : $this->referenceCopy; } public function setReferenceCopy($reference) { $this->referenceCopy = $reference; } } class FormTypeTest extends BaseTypeTest { public function testCreateFormInstances() { $this->assertInstanceOf('Symfony\Component\Form\Form', $this->factory->create('form')); } public function testPassRequiredAsOption() { $form = $this->factory->create('form', null, array('required' => false)); $this->assertFalse($form->isRequired()); $form = $this->factory->create('form', null, array('required' => true)); $this->assertTrue($form->isRequired()); } public function testSubmittedDataIsTrimmedBeforeTransforming() { $form = $this->factory->createBuilder('form') ->addViewTransformer(new FixedDataTransformer(array( null => '', 'reverse[a]' => 'a', ))) ->setCompound(false) ->getForm(); $form->submit(' a '); $this->assertEquals('a', $form->getViewData()); $this->assertEquals('reverse[a]', $form->getData()); } public function testSubmittedDataIsNotTrimmedBeforeTransformingIfNoTrimming() { $form = $this->factory->createBuilder('form', null, array('trim' => false)) ->addViewTransformer(new FixedDataTransformer(array( null => '', 'reverse[ a ]' => ' a ', ))) ->setCompound(false) ->getForm(); $form->submit(' a '); $this->assertEquals(' a ', $form->getViewData()); $this->assertEquals('reverse[ a ]', $form->getData()); } public function testNonReadOnlyFormWithReadOnlyParentIsReadOnly() { $view = $this->factory->createNamedBuilder('parent', 'form', null, array('read_only' => true)) ->add('child', 'form') ->getForm() ->createView(); $this->assertTrue($view['child']->vars['read_only']); } public function testReadOnlyFormWithNonReadOnlyParentIsReadOnly() { $view = $this->factory->createNamedBuilder('parent', 'form') ->add('child', 'form', array('read_only' => true)) ->getForm() ->createView(); $this->assertTrue($view['child']->vars['read_only']); } public function testNonReadOnlyFormWithNonReadOnlyParentIsNotReadOnly() { $view = $this->factory->createNamedBuilder('parent', 'form') ->add('child', 'form') ->getForm() ->createView(); $this->assertFalse($view['child']->vars['read_only']); } public function testPassMaxLengthToView() { $form = $this->factory->create('form', null, array('max_length' => 10)); $view = $form->createView(); $this->assertSame(10, $view->vars['max_length']); } public function testSubmitWithEmptyDataCreatesObjectIfClassAvailable() { $builder = $this->factory->createBuilder('form', null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', 'required' => false, )); $builder->add('firstName', 'text'); $builder->add('lastName', 'text'); $form = $builder->getForm(); $form->setData(null); // partially empty, still an object is created $form->submit(array('firstName' => 'Bernhard', 'lastName' => '')); $author = new Author(); $author->firstName = 'Bernhard'; $author->setLastName(''); $this->assertEquals($author, $form->getData()); } public function testSubmitWithEmptyDataCreatesObjectIfInitiallySubmittedWithObject() { $builder = $this->factory->createBuilder('form', null, array( // data class is inferred from the passed object 'data' => new Author(), 'required' => false, )); $builder->add('firstName', 'text'); $builder->add('lastName', 'text'); $form = $builder->getForm(); $form->setData(null); // partially empty, still an object is created $form->submit(array('firstName' => 'Bernhard', 'lastName' => '')); $author = new Author(); $author->firstName = 'Bernhard'; $author->setLastName(''); $this->assertEquals($author, $form->getData()); } public function testSubmitWithEmptyDataCreatesArrayIfDataClassIsNull() { $builder = $this->factory->createBuilder('form', null, array( 'data_class' => null, 'required' => false, )); $builder->add('firstName', 'text'); $form = $builder->getForm(); $form->setData(null); $form->submit(array('firstName' => 'Bernhard')); $this->assertSame(array('firstName' => 'Bernhard'), $form->getData()); } public function testSubmitEmptyWithEmptyDataCreatesNoObjectIfNotRequired() { $builder = $this->factory->createBuilder('form', null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', 'required' => false, )); $builder->add('firstName', 'text'); $builder->add('lastName', 'text'); $form = $builder->getForm(); $form->setData(null); $form->submit(array('firstName' => '', 'lastName' => '')); $this->assertNull($form->getData()); } public function testSubmitEmptyWithEmptyDataCreatesObjectIfRequired() { $builder = $this->factory->createBuilder('form', null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', 'required' => true, )); $builder->add('firstName', 'text'); $builder->add('lastName', 'text'); $form = $builder->getForm(); $form->setData(null); $form->submit(array('firstName' => '', 'lastName' => '')); $this->assertEquals(new Author(), $form->getData()); } /* * We need something to write the field values into */ public function testSubmitWithEmptyDataStoresArrayIfNoClassAvailable() { $form = $this->factory->createBuilder('form') ->add('firstName', 'text') ->getForm(); $form->setData(null); $form->submit(array('firstName' => 'Bernhard')); $this->assertSame(array('firstName' => 'Bernhard'), $form->getData()); } public function testSubmitWithEmptyDataPassesEmptyStringToTransformerIfNotCompound() { $form = $this->factory->createBuilder('form') ->addViewTransformer(new FixedDataTransformer(array( // required for the initial, internal setData(null) null => 'null', // required to test that submit(null) is converted to '' 'empty' => '', ))) ->setCompound(false) ->getForm(); $form->submit(null); $this->assertSame('empty', $form->getData()); } public function testSubmitWithEmptyDataUsesEmptyDataOption() { $author = new Author(); $builder = $this->factory->createBuilder('form', null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', 'empty_data' => $author, )); $builder->add('firstName', 'text'); $form = $builder->getForm(); $form->submit(array('firstName' => 'Bernhard')); $this->assertSame($author, $form->getData()); $this->assertEquals('Bernhard', $author->firstName); } public function provideZeros() { return array( array(0, '0'), array('0', '0'), array('00000', '00000'), ); } /** * @dataProvider provideZeros * @see https://github.com/symfony/symfony/issues/1986 */ public function testSetDataThroughParamsWithZero($data, $dataAsString) { $form = $this->factory->create('form', null, array( 'data' => $data, 'compound' => false, )); $view = $form->createView(); $this->assertFalse($form->isEmpty()); $this->assertSame($dataAsString, $view->vars['value']); $this->assertSame($dataAsString, $form->getData()); } /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testAttributesException() { $this->factory->create('form', null, array('attr' => '')); } public function testNameCanBeEmptyString() { $form = $this->factory->createNamed('', 'form'); $this->assertEquals('', $form->getName()); } public function testSubformDoesntCallSetters() { $author = new FormTest_AuthorWithoutRefSetter(new Author()); $builder = $this->factory->createBuilder('form', $author); $builder->add('reference', 'form', array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', )); $builder->get('reference')->add('firstName', 'text'); $form = $builder->getForm(); $form->submit(array( // reference has a getter, but not setter 'reference' => array( 'firstName' => 'Foo', ) )); $this->assertEquals('Foo', $author->getReference()->firstName); } public function testSubformCallsSettersIfTheObjectChanged() { // no reference $author = new FormTest_AuthorWithoutRefSetter(null); $newReference = new Author(); $builder = $this->factory->createBuilder('form', $author); $builder->add('referenceCopy', 'form', array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', )); $builder->get('referenceCopy')->add('firstName', 'text'); $form = $builder->getForm(); $form['referenceCopy']->setData($newReference); // new author object $form->submit(array( // referenceCopy has a getter that returns a copy 'referenceCopy' => array( 'firstName' => 'Foo', ) )); $this->assertEquals('Foo', $author->getReferenceCopy()->firstName); } public function testSubformCallsSettersIfByReferenceIsFalse() { $author = new FormTest_AuthorWithoutRefSetter(new Author()); $builder = $this->factory->createBuilder('form', $author); $builder->add('referenceCopy', 'form', array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', 'by_reference' => false )); $builder->get('referenceCopy')->add('firstName', 'text'); $form = $builder->getForm(); $form->submit(array( // referenceCopy has a getter that returns a copy 'referenceCopy' => array( 'firstName' => 'Foo', ) )); // firstName can only be updated if setReferenceCopy() was called $this->assertEquals('Foo', $author->getReferenceCopy()->firstName); } public function testSubformCallsSettersIfReferenceIsScalar() { $author = new FormTest_AuthorWithoutRefSetter('scalar'); $builder = $this->factory->createBuilder('form', $author); $builder->add('referenceCopy', 'form'); $builder->get('referenceCopy')->addViewTransformer(new CallbackTransformer( function () {}, function ($value) { // reverseTransform return 'foobar'; } )); $form = $builder->getForm(); $form->submit(array( 'referenceCopy' => array(), // doesn't matter actually )); // firstName can only be updated if setReferenceCopy() was called $this->assertEquals('foobar', $author->getReferenceCopy()); } public function testSubformAlwaysInsertsIntoArrays() { $ref1 = new Author(); $ref2 = new Author(); $author = array('referenceCopy' => $ref1); $builder = $this->factory->createBuilder('form'); $builder->setData($author); $builder->add('referenceCopy', 'form'); $builder->get('referenceCopy')->addViewTransformer(new CallbackTransformer( function () {}, function ($value) use ($ref2) { // reverseTransform return $ref2; } )); $form = $builder->getForm(); $form->submit(array( 'referenceCopy' => array('a' => 'b'), // doesn't matter actually )); // the new reference was inserted into the array $author = $form->getData(); $this->assertSame($ref2, $author['referenceCopy']); } public function testPassMultipartTrueIfAnyChildIsMultipartToView() { $view = $this->factory->createBuilder('form') ->add('foo', 'text') ->add('bar', 'file') ->getForm() ->createView(); $this->assertTrue($view->vars['multipart']); } public function testViewIsNotRenderedByDefault() { $view = $this->factory->createBuilder('form') ->add('foo', 'form') ->getForm() ->createView(); $this->assertFalse($view->isRendered()); } public function testErrorBubblingIfCompound() { $form = $this->factory->create('form', null, array( 'compound' => true, )); $this->assertTrue($form->getConfig()->getErrorBubbling()); } public function testNoErrorBubblingIfNotCompound() { $form = $this->factory->create('form', null, array( 'compound' => false, )); $this->assertFalse($form->getConfig()->getErrorBubbling()); } public function testOverrideErrorBubbling() { $form = $this->factory->create('form', null, array( 'compound' => false, 'error_bubbling' => true, )); $this->assertTrue($form->getConfig()->getErrorBubbling()); } public function testPropertyPath() { $form = $this->factory->create('form', null, array( 'property_path' => 'foo', )); $this->assertEquals(new PropertyPath('foo'), $form->getPropertyPath()); $this->assertTrue($form->getConfig()->getMapped()); } public function testPropertyPathNullImpliesDefault() { $form = $this->factory->createNamed('name', 'form', null, array( 'property_path' => null, )); $this->assertEquals(new PropertyPath('name'), $form->getPropertyPath()); $this->assertTrue($form->getConfig()->getMapped()); } public function testNotMapped() { $form = $this->factory->create('form', null, array( 'property_path' => 'foo', 'mapped' => false, )); $this->assertEquals(new PropertyPath('foo'), $form->getPropertyPath()); $this->assertFalse($form->getConfig()->getMapped()); } public function testViewValidNotSubmitted() { $form = $this->factory->create('form'); $view = $form->createView(); $this->assertTrue($view->vars['valid']); } public function testViewNotValidSubmitted() { $form = $this->factory->create('form'); $form->submit(array()); $form->addError(new FormError('An error')); $view = $form->createView(); $this->assertFalse($view->vars['valid']); } public function testViewSubmittedNotSubmitted() { $form = $this->factory->create('form'); $view = $form->createView(); $this->assertFalse($view->vars['submitted']); } public function testViewSubmittedSubmitted() { $form = $this->factory->create('form'); $form->submit(array()); $view = $form->createView(); $this->assertTrue($view->vars['submitted']); } public function testDataOptionSupersedesSetDataCalls() { $form = $this->factory->create('form', null, array( 'data' => 'default', 'compound' => false, )); $form->setData('foobar'); $this->assertSame('default', $form->getData()); } public function testDataOptionSupersedesSetDataCallsIfNull() { $form = $this->factory->create('form', null, array( 'data' => null, 'compound' => false, )); $form->setData('foobar'); $this->assertNull($form->getData()); } public function testNormDataIsPassedToView() { $view = $this->factory->createBuilder('form') ->addViewTransformer(new FixedDataTransformer(array( 'foo' => 'bar', ))) ->setData('foo') ->getForm() ->createView(); $this->assertSame('foo', $view->vars['data']); $this->assertSame('bar', $view->vars['value']); } // https://github.com/symfony/symfony/issues/6862 public function testPassZeroLabelToView() { $view = $this->factory->create('form', null, array( 'label' => '0' )) ->createView(); $this->assertSame('0', $view->vars['label']); } public function testCanGetErrorsWhenButtonInForm() { $builder = $this->factory->createBuilder('form', null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', 'required' => false, )); $builder->add('foo', 'text'); $builder->add('submit', 'submit'); $form = $builder->getForm(); //This method should not throw a Fatal Error Exception. $form->getErrorsAsString(); } protected function getTestedType() { return 'form'; } } Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.php000064400000011275152374770060021726 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\CallbackTransformer; class CheckboxTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { public function testDataIsFalseByDefault() { $form = $this->factory->create('checkbox'); $this->assertFalse($form->getData()); $this->assertFalse($form->getNormData()); $this->assertNull($form->getViewData()); } public function testPassValueToView() { $form = $this->factory->create('checkbox', null, array('value' => 'foobar')); $view = $form->createView(); $this->assertEquals('foobar', $view->vars['value']); } public function testCheckedIfDataTrue() { $form = $this->factory->create('checkbox'); $form->setData(true); $view = $form->createView(); $this->assertTrue($view->vars['checked']); } public function testCheckedIfDataTrueWithEmptyValue() { $form = $this->factory->create('checkbox', null, array('value' => '')); $form->setData(true); $view = $form->createView(); $this->assertTrue($view->vars['checked']); } public function testNotCheckedIfDataFalse() { $form = $this->factory->create('checkbox'); $form->setData(false); $view = $form->createView(); $this->assertFalse($view->vars['checked']); } public function testSubmitWithValueChecked() { $form = $this->factory->create('checkbox', null, array( 'value' => 'foobar', )); $form->submit('foobar'); $this->assertTrue($form->getData()); $this->assertEquals('foobar', $form->getViewData()); } public function testSubmitWithRandomValueChecked() { $form = $this->factory->create('checkbox', null, array( 'value' => 'foobar', )); $form->submit('krixikraxi'); $this->assertTrue($form->getData()); $this->assertEquals('foobar', $form->getViewData()); } public function testSubmitWithValueUnchecked() { $form = $this->factory->create('checkbox', null, array( 'value' => 'foobar', )); $form->submit(null); $this->assertFalse($form->getData()); $this->assertNull($form->getViewData()); } public function testSubmitWithEmptyValueChecked() { $form = $this->factory->create('checkbox', null, array( 'value' => '', )); $form->submit(''); $this->assertTrue($form->getData()); $this->assertSame('', $form->getViewData()); } public function testSubmitWithEmptyValueUnchecked() { $form = $this->factory->create('checkbox', null, array( 'value' => '', )); $form->submit(null); $this->assertFalse($form->getData()); $this->assertNull($form->getViewData()); } public function testSubmitWithEmptyValueAndFalseUnchecked() { $form = $this->factory->create('checkbox', null, array( 'value' => '', )); $form->submit(false); $this->assertFalse($form->getData()); $this->assertNull($form->getViewData()); } public function testSubmitWithEmptyValueAndTrueChecked() { $form = $this->factory->create('checkbox', null, array( 'value' => '', )); $form->submit(true); $this->assertTrue($form->getData()); $this->assertSame('', $form->getViewData()); } /** * @dataProvider provideCustomModelTransformerData */ public function testCustomModelTransformer($data, $checked) { // present a binary status field as a checkbox $transformer = new CallbackTransformer( function ($value) { return 'checked' == $value; }, function ($value) { return $value ? 'checked' : 'unchecked'; } ); $form = $this->factory->createBuilder('checkbox') ->addModelTransformer($transformer) ->getForm(); $form->setData($data); $view = $form->createView(); $this->assertSame($data, $form->getData()); $this->assertSame($checked, $form->getNormData()); $this->assertEquals($checked, $view->vars['checked']); } public function provideCustomModelTransformerData() { return array( array('checked', true), array('unchecked', false), ); } } Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php000064400000015114152374770060022267 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Form; class CollectionTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { public function testContainsNoChildByDefault() { $form = $this->factory->create('collection', null, array( 'type' => 'text', )); $this->assertCount(0, $form); } public function testSetDataAdjustsSize() { $form = $this->factory->create('collection', null, array( 'type' => 'text', 'options' => array( 'max_length' => 20, ), )); $form->setData(array('foo@foo.com', 'foo@bar.com')); $this->assertInstanceOf('Symfony\Component\Form\Form', $form[0]); $this->assertInstanceOf('Symfony\Component\Form\Form', $form[1]); $this->assertCount(2, $form); $this->assertEquals('foo@foo.com', $form[0]->getData()); $this->assertEquals('foo@bar.com', $form[1]->getData()); $this->assertEquals(20, $form[0]->getConfig()->getOption('max_length')); $this->assertEquals(20, $form[1]->getConfig()->getOption('max_length')); $form->setData(array('foo@baz.com')); $this->assertInstanceOf('Symfony\Component\Form\Form', $form[0]); $this->assertFalse(isset($form[1])); $this->assertCount(1, $form); $this->assertEquals('foo@baz.com', $form[0]->getData()); $this->assertEquals(20, $form[0]->getConfig()->getOption('max_length')); } public function testThrowsExceptionIfObjectIsNotTraversable() { $form = $this->factory->create('collection', null, array( 'type' => 'text', )); $this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException'); $form->setData(new \stdClass()); } public function testNotResizedIfSubmittedWithMissingData() { $form = $this->factory->create('collection', null, array( 'type' => 'text', )); $form->setData(array('foo@foo.com', 'bar@bar.com')); $form->submit(array('foo@bar.com')); $this->assertTrue($form->has('0')); $this->assertTrue($form->has('1')); $this->assertEquals('foo@bar.com', $form[0]->getData()); $this->assertEquals('', $form[1]->getData()); } public function testResizedDownIfSubmittedWithMissingDataAndAllowDelete() { $form = $this->factory->create('collection', null, array( 'type' => 'text', 'allow_delete' => true, )); $form->setData(array('foo@foo.com', 'bar@bar.com')); $form->submit(array('foo@foo.com')); $this->assertTrue($form->has('0')); $this->assertFalse($form->has('1')); $this->assertEquals('foo@foo.com', $form[0]->getData()); $this->assertEquals(array('foo@foo.com'), $form->getData()); } public function testNotResizedIfSubmittedWithExtraData() { $form = $this->factory->create('collection', null, array( 'type' => 'text', )); $form->setData(array('foo@bar.com')); $form->submit(array('foo@foo.com', 'bar@bar.com')); $this->assertTrue($form->has('0')); $this->assertFalse($form->has('1')); $this->assertEquals('foo@foo.com', $form[0]->getData()); } public function testResizedUpIfSubmittedWithExtraDataAndAllowAdd() { $form = $this->factory->create('collection', null, array( 'type' => 'text', 'allow_add' => true, )); $form->setData(array('foo@bar.com')); $form->submit(array('foo@bar.com', 'bar@bar.com')); $this->assertTrue($form->has('0')); $this->assertTrue($form->has('1')); $this->assertEquals('foo@bar.com', $form[0]->getData()); $this->assertEquals('bar@bar.com', $form[1]->getData()); $this->assertEquals(array('foo@bar.com', 'bar@bar.com'), $form->getData()); } public function testAllowAddButNoPrototype() { $form = $this->factory->create('collection', null, array( 'type' => 'form', 'allow_add' => true, 'prototype' => false, )); $this->assertFalse($form->has('__name__')); } public function testPrototypeMultipartPropagation() { $form = $this->factory ->create('collection', null, array( 'type' => 'file', 'allow_add' => true, 'prototype' => true, )) ; $this->assertTrue($form->createView()->vars['multipart']); } public function testGetDataDoesNotContainsPrototypeNameBeforeDataAreSet() { $form = $this->factory->create('collection', array(), array( 'type' => 'file', 'prototype' => true, 'allow_add' => true, )); $data = $form->getData(); $this->assertFalse(isset($data['__name__'])); } public function testGetDataDoesNotContainsPrototypeNameAfterDataAreSet() { $form = $this->factory->create('collection', array(), array( 'type' => 'file', 'allow_add' => true, 'prototype' => true, )); $form->setData(array('foobar.png')); $data = $form->getData(); $this->assertFalse(isset($data['__name__'])); } public function testPrototypeNameOption() { $form = $this->factory->create('collection', null, array( 'type' => 'form', 'prototype' => true, 'allow_add' => true, )); $this->assertSame('__name__', $form->getConfig()->getAttribute('prototype')->getName(), '__name__ is the default'); $form = $this->factory->create('collection', null, array( 'type' => 'form', 'prototype' => true, 'allow_add' => true, 'prototype_name' => '__test__', )); $this->assertSame('__test__', $form->getConfig()->getAttribute('prototype')->getName()); } public function testPrototypeDefaultLabel() { $form = $this->factory->create('collection', array(), array( 'type' => 'file', 'allow_add' => true, 'prototype' => true, 'prototype_name' => '__test__', )); $this->assertSame('__test__label__', $form->createView()->vars['prototype']->vars['label']); } } Symfony/Component/Form/Tests/Extension/Core/Type/PasswordTypeTest.php000064400000002537152374770060022003 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\Type; class PasswordTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { public function testEmptyIfNotSubmitted() { $form = $this->factory->create('password'); $form->setData('pAs5w0rd'); $view = $form->createView(); $this->assertSame('', $view->vars['value']); } public function testEmptyIfSubmitted() { $form = $this->factory->create('password'); $form->submit('pAs5w0rd'); $view = $form->createView(); $this->assertSame('', $view->vars['value']); } public function testNotEmptyIfSubmittedAndNotAlwaysEmpty() { $form = $this->factory->create('password', null, array('always_empty' => false)); $form->submit('pAs5w0rd'); $view = $form->createView(); $this->assertSame('pAs5w0rd', $view->vars['value']); } public function testNotTrimmed() { $form = $this->factory->create('password', null); $form->submit(' pAs5w0rd '); $data = $form->getData(); $this->assertSame(' pAs5w0rd ', $data); } } Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php000064400000067556152374770060030443 0ustar00Symfony * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer; use Symfony\Component\Intl\Util\IntlTestHelper; class NumberToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase { protected function setUp() { parent::setUp(); // Since we test against "de_AT", we need the full implementation IntlTestHelper::requireFullIntl($this); \Locale::setDefault('de_AT'); } public function provideTransformations() { return array( array(null, '', 'de_AT'), array(1, '1', 'de_AT'), array(1.5, '1,5', 'de_AT'), array(1234.5, '1234,5', 'de_AT'), array(12345.912, '12345,912', 'de_AT'), array(1234.5, '1234,5', 'ru'), array(1234.5, '1234,5', 'fi'), ); } /** * @dataProvider provideTransformations */ public function testTransform($from, $to, $locale) { \Locale::setDefault($locale); $transformer = new NumberToLocalizedStringTransformer(); $this->assertSame($to, $transformer->transform($from)); } public function provideTransformationsWithGrouping() { return array( array(1234.5, '1.234,5', 'de_AT'), array(12345.912, '12.345,912', 'de_AT'), array(1234.5, '1 234,5', 'fr'), array(1234.5, '1 234,5', 'ru'), array(1234.5, '1 234,5', 'fi'), ); } /** * @dataProvider provideTransformationsWithGrouping */ public function testTransformWithGrouping($from, $to, $locale) { \Locale::setDefault($locale); $transformer = new NumberToLocalizedStringTransformer(null, true); $this->assertSame($to, $transformer->transform($from)); } public function testTransformWithPrecision() { $transformer = new NumberToLocalizedStringTransformer(2); $this->assertEquals('1234,50', $transformer->transform(1234.5)); $this->assertEquals('678,92', $transformer->transform(678.916)); } public function transformWithRoundingProvider() { return array( // towards positive infinity (1.6 -> 2, -1.6 -> -1) array(0, 1234.5, '1235', NumberToLocalizedStringTransformer::ROUND_CEILING), array(0, 1234.4, '1235', NumberToLocalizedStringTransformer::ROUND_CEILING), array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_CEILING), array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_CEILING), array(1, 123.45, '123,5', NumberToLocalizedStringTransformer::ROUND_CEILING), array(1, 123.44, '123,5', NumberToLocalizedStringTransformer::ROUND_CEILING), array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_CEILING), array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_CEILING), // towards negative infinity (1.6 -> 1, -1.6 -> -2) array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_FLOOR), array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_FLOOR), array(0, -1234.5, '-1235', NumberToLocalizedStringTransformer::ROUND_FLOOR), array(0, -1234.4, '-1235', NumberToLocalizedStringTransformer::ROUND_FLOOR), array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_FLOOR), array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_FLOOR), array(1, -123.45, '-123,5', NumberToLocalizedStringTransformer::ROUND_FLOOR), array(1, -123.44, '-123,5', NumberToLocalizedStringTransformer::ROUND_FLOOR), // away from zero (1.6 -> 2, -1.6 -> 2) array(0, 1234.5, '1235', NumberToLocalizedStringTransformer::ROUND_UP), array(0, 1234.4, '1235', NumberToLocalizedStringTransformer::ROUND_UP), array(0, -1234.5, '-1235', NumberToLocalizedStringTransformer::ROUND_UP), array(0, -1234.4, '-1235', NumberToLocalizedStringTransformer::ROUND_UP), array(1, 123.45, '123,5', NumberToLocalizedStringTransformer::ROUND_UP), array(1, 123.44, '123,5', NumberToLocalizedStringTransformer::ROUND_UP), array(1, -123.45, '-123,5', NumberToLocalizedStringTransformer::ROUND_UP), array(1, -123.44, '-123,5', NumberToLocalizedStringTransformer::ROUND_UP), // towards zero (1.6 -> 1, -1.6 -> -1) array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_DOWN), array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_DOWN), array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_DOWN), array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_DOWN), array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_DOWN), array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_DOWN), array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_DOWN), array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_DOWN), // round halves (.5) to the next even number array(0, 1234.6, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, 1233.5, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, 1232.5, '1232', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, -1234.6, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, -1233.5, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, -1232.5, '-1232', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, 123.46, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, 123.35, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, 123.25, '123,2', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, -123.46, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, -123.35, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, -123.25, '-123,2', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), // round halves (.5) away from zero array(0, 1234.6, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, 1234.5, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, -1234.6, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, -1234.5, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, 123.46, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, 123.45, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, -123.46, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, -123.45, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_UP), // round halves (.5) towards zero array(0, 1234.6, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, -1234.6, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, 123.46, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, -123.46, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), ); } /** * @dataProvider transformWithRoundingProvider */ public function testTransformWithRounding($precision, $input, $output, $roundingMode) { $transformer = new NumberToLocalizedStringTransformer($precision, null, $roundingMode); $this->assertEquals($output, $transformer->transform($input)); } public function testTransformDoesNotRoundIfNoPrecision() { $transformer = new NumberToLocalizedStringTransformer(null, null, NumberToLocalizedStringTransformer::ROUND_DOWN); $this->assertEquals('1234,547', $transformer->transform(1234.547)); } /** * @dataProvider provideTransformations */ public function testReverseTransform($to, $from, $locale) { \Locale::setDefault($locale); $transformer = new NumberToLocalizedStringTransformer(); $this->assertEquals($to, $transformer->reverseTransform($from)); } /** * @dataProvider provideTransformationsWithGrouping */ public function testReverseTransformWithGrouping($to, $from, $locale) { \Locale::setDefault($locale); $transformer = new NumberToLocalizedStringTransformer(null, true); $this->assertEquals($to, $transformer->reverseTransform($from)); } // https://github.com/symfony/symfony/issues/7609 public function testReverseTransformWithGroupingAndFixedSpaces() { if (!extension_loaded('mbstring')) { $this->markTestSkipped('The "mbstring" extension is required for this test.'); } \Locale::setDefault('ru'); $transformer = new NumberToLocalizedStringTransformer(null, true); $this->assertEquals(1234.5, $transformer->reverseTransform("1\xc2\xa0234,5")); } public function testReverseTransformWithGroupingButWithoutGroupSeparator() { $transformer = new NumberToLocalizedStringTransformer(null, true); // omit group separator $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); $this->assertEquals(12345.912, $transformer->reverseTransform('12345,912')); } public function reverseTransformWithRoundingProvider() { return array( // towards positive infinity (1.6 -> 2, -1.6 -> -1) array(0, '1234,5', 1235, NumberToLocalizedStringTransformer::ROUND_CEILING), array(0, '1234,4', 1235, NumberToLocalizedStringTransformer::ROUND_CEILING), array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_CEILING), array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_CEILING), array(1, '123,45', 123.5, NumberToLocalizedStringTransformer::ROUND_CEILING), array(1, '123,44', 123.5, NumberToLocalizedStringTransformer::ROUND_CEILING), array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_CEILING), array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_CEILING), // towards negative infinity (1.6 -> 1, -1.6 -> -2) array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_FLOOR), array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_FLOOR), array(0, '-1234,5', -1235, NumberToLocalizedStringTransformer::ROUND_FLOOR), array(0, '-1234,4', -1235, NumberToLocalizedStringTransformer::ROUND_FLOOR), array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_FLOOR), array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_FLOOR), array(1, '-123,45', -123.5, NumberToLocalizedStringTransformer::ROUND_FLOOR), array(1, '-123,44', -123.5, NumberToLocalizedStringTransformer::ROUND_FLOOR), // away from zero (1.6 -> 2, -1.6 -> 2) array(0, '1234,5', 1235, NumberToLocalizedStringTransformer::ROUND_UP), array(0, '1234,4', 1235, NumberToLocalizedStringTransformer::ROUND_UP), array(0, '-1234,5', -1235, NumberToLocalizedStringTransformer::ROUND_UP), array(0, '-1234,4', -1235, NumberToLocalizedStringTransformer::ROUND_UP), array(1, '123,45', 123.5, NumberToLocalizedStringTransformer::ROUND_UP), array(1, '123,44', 123.5, NumberToLocalizedStringTransformer::ROUND_UP), array(1, '-123,45', -123.5, NumberToLocalizedStringTransformer::ROUND_UP), array(1, '-123,44', -123.5, NumberToLocalizedStringTransformer::ROUND_UP), // towards zero (1.6 -> 1, -1.6 -> -1) array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_DOWN), array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_DOWN), array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_DOWN), array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_DOWN), array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_DOWN), array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_DOWN), array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_DOWN), array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_DOWN), // round halves (.5) to the next even number array(0, '1234,6', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, '1233,5', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, '1232,5', 1232, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, '-1234,6', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, '-1233,5', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(0, '-1232,5', -1232, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '123,46', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '123,35', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '123,25', 123.2, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '-123,46', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '-123,35', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1, '-123,25', -123.2, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), // round halves (.5) away from zero array(0, '1234,6', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, '1234,5', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, '-1234,6', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, '-1234,5', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, '123,46', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, '123,45', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, '-123,46', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, '-123,45', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP), array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_UP), // round halves (.5) towards zero array(0, '1234,6', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, '-1234,6', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, '123,46', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, '-123,46', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), ); } /** * @dataProvider reverseTransformWithRoundingProvider */ public function testReverseTransformWithRounding($precision, $input, $output, $roundingMode) { $transformer = new NumberToLocalizedStringTransformer($precision, null, $roundingMode); $this->assertEquals($output, $transformer->reverseTransform($input)); } public function testReverseTransformDoesNotRoundIfNoPrecision() { $transformer = new NumberToLocalizedStringTransformer(null, null, NumberToLocalizedStringTransformer::ROUND_DOWN); $this->assertEquals(1234.547, $transformer->reverseTransform('1234,547')); } public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsNotDot() { \Locale::setDefault('fr'); $transformer = new NumberToLocalizedStringTransformer(null, true); // completely valid format $this->assertEquals(1234.5, $transformer->reverseTransform('1 234,5')); // accept dots $this->assertEquals(1234.5, $transformer->reverseTransform('1 234.5')); // omit group separator $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDot() { $transformer = new NumberToLocalizedStringTransformer(null, true); $transformer->reverseTransform('1.234.5'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDotWithNoGroupSep() { $transformer = new NumberToLocalizedStringTransformer(null, true); $transformer->reverseTransform('1234.5'); } public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsDotButNoGroupingUsed() { \Locale::setDefault('fr'); $transformer = new NumberToLocalizedStringTransformer(); $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); } public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsNotComma() { \Locale::setDefault('bg'); $transformer = new NumberToLocalizedStringTransformer(null, true); // completely valid format $this->assertEquals(1234.5, $transformer->reverseTransform('1 234.5')); // accept commas $this->assertEquals(1234.5, $transformer->reverseTransform('1 234,5')); // omit group separator $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsComma() { \Locale::setDefault('en'); $transformer = new NumberToLocalizedStringTransformer(null, true); $transformer->reverseTransform('1,234,5'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsCommaWithNoGroupSep() { \Locale::setDefault('en'); $transformer = new NumberToLocalizedStringTransformer(null, true); $transformer->reverseTransform('1234,5'); } public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsCommaButNoGroupingUsed() { \Locale::setDefault('en'); $transformer = new NumberToLocalizedStringTransformer(); $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testTransformExpectsNumeric() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->transform('foo'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformExpectsString() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform(1); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformExpectsValidNumber() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform('foo'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException * @link https://github.com/symfony/symfony/issues/3161 */ public function testReverseTransformDisallowsNaN() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform('NaN'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsNaN2() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform('nan'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsInfinity() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform('∞'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsInfinity2() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform('∞,123'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsNegativeInfinity() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform('-∞'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsLeadingExtraCharacters() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform('foo123'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException * @expectedExceptionMessage The number contains unrecognized characters: "foo3" */ public function testReverseTransformDisallowsCenteredExtraCharacters() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform('12foo3'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException * @expectedExceptionMessage The number contains unrecognized characters: "foo8" */ public function testReverseTransformDisallowsCenteredExtraCharactersMultibyte() { if (!extension_loaded('mbstring')) { $this->markTestSkipped('The "mbstring" extension is required for this test.'); } \Locale::setDefault('ru'); $transformer = new NumberToLocalizedStringTransformer(null, true); $transformer->reverseTransform("12\xc2\xa0345,67foo8"); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException * @expectedExceptionMessage The number contains unrecognized characters: "foo8" */ public function testReverseTransformIgnoresTrailingSpacesInExceptionMessage() { if (!extension_loaded('mbstring')) { $this->markTestSkipped('The "mbstring" extension is required for this test.'); } \Locale::setDefault('ru'); $transformer = new NumberToLocalizedStringTransformer(null, true); $transformer->reverseTransform("12\xc2\xa0345,67foo8 \xc2\xa0\t"); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException * @expectedExceptionMessage The number contains unrecognized characters: "foo" */ public function testReverseTransformDisallowsTrailingExtraCharacters() { $transformer = new NumberToLocalizedStringTransformer(); $transformer->reverseTransform('123foo'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException * @expectedExceptionMessage The number contains unrecognized characters: "foo" */ public function testReverseTransformDisallowsTrailingExtraCharactersMultibyte() { if (!extension_loaded('mbstring')) { $this->markTestSkipped('The "mbstring" extension is required for this test.'); } \Locale::setDefault('ru'); $transformer = new NumberToLocalizedStringTransformer(null, true); $transformer->reverseTransform("12\xc2\xa0345,678foo"); } } Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeTestCase.php000064400000001054152374770060023773 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; abstract class DateTimeTestCase extends \PHPUnit_Framework_TestCase { public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual) { self::assertEquals($expected->format('c'), $actual->format('c')); } } Component/Form/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php000064400000027172152374770060030576 0ustar00Symfony * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\IntegerToLocalizedStringTransformer; use Symfony\Component\Intl\Util\IntlTestHelper; class IntegerToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase { protected function setUp() { parent::setUp(); // Since we test against "de_AT", we need the full implementation IntlTestHelper::requireFullIntl($this); \Locale::setDefault('de_AT'); } public function transformWithRoundingProvider() { return array( // towards positive infinity (1.6 -> 2, -1.6 -> -1) array(1234.5, '1235', IntegerToLocalizedStringTransformer::ROUND_CEILING), array(1234.4, '1235', IntegerToLocalizedStringTransformer::ROUND_CEILING), array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_CEILING), array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_CEILING), // towards negative infinity (1.6 -> 1, -1.6 -> -2) array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_FLOOR), array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_FLOOR), array(-1234.5, '-1235', IntegerToLocalizedStringTransformer::ROUND_FLOOR), array(-1234.4, '-1235', IntegerToLocalizedStringTransformer::ROUND_FLOOR), // away from zero (1.6 -> 2, -1.6 -> 2) array(1234.5, '1235', IntegerToLocalizedStringTransformer::ROUND_UP), array(1234.4, '1235', IntegerToLocalizedStringTransformer::ROUND_UP), array(-1234.5, '-1235', IntegerToLocalizedStringTransformer::ROUND_UP), array(-1234.4, '-1235', IntegerToLocalizedStringTransformer::ROUND_UP), // towards zero (1.6 -> 1, -1.6 -> -1) array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_DOWN), array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_DOWN), array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_DOWN), array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_DOWN), // round halves (.5) to the next even number array(1234.6, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1233.5, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array(1232.5, '1232', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array(-1234.6, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array(-1233.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array(-1232.5, '-1232', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), // round halves (.5) away from zero array(1234.6, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array(1234.5, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array(-1234.6, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array(-1234.5, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_UP), // round halves (.5) towards zero array(1234.6, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array(-1234.6, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), ); } /** * @dataProvider transformWithRoundingProvider */ public function testTransformWithRounding($input, $output, $roundingMode) { $transformer = new IntegerToLocalizedStringTransformer(null, null, $roundingMode); $this->assertEquals($output, $transformer->transform($input)); } public function testReverseTransform() { $transformer = new IntegerToLocalizedStringTransformer(); $this->assertEquals(1, $transformer->reverseTransform('1')); $this->assertEquals(1, $transformer->reverseTransform('1,5')); $this->assertEquals(1234, $transformer->reverseTransform('1234,5')); $this->assertEquals(12345, $transformer->reverseTransform('12345,912')); } public function testReverseTransformEmpty() { $transformer = new IntegerToLocalizedStringTransformer(); $this->assertNull($transformer->reverseTransform('')); } public function testReverseTransformWithGrouping() { $transformer = new IntegerToLocalizedStringTransformer(null, true); $this->assertEquals(1234, $transformer->reverseTransform('1.234,5')); $this->assertEquals(12345, $transformer->reverseTransform('12.345,912')); $this->assertEquals(1234, $transformer->reverseTransform('1234,5')); $this->assertEquals(12345, $transformer->reverseTransform('12345,912')); } public function reverseTransformWithRoundingProvider() { return array( // towards positive infinity (1.6 -> 2, -1.6 -> -1) array('1234,5', 1235, IntegerToLocalizedStringTransformer::ROUND_CEILING), array('1234,4', 1235, IntegerToLocalizedStringTransformer::ROUND_CEILING), array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_CEILING), array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_CEILING), // towards negative infinity (1.6 -> 1, -1.6 -> -2) array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_FLOOR), array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_FLOOR), array('-1234,5', -1235, IntegerToLocalizedStringTransformer::ROUND_FLOOR), array('-1234,4', -1235, IntegerToLocalizedStringTransformer::ROUND_FLOOR), // away from zero (1.6 -> 2, -1.6 -> 2) array('1234,5', 1235, IntegerToLocalizedStringTransformer::ROUND_UP), array('1234,4', 1235, IntegerToLocalizedStringTransformer::ROUND_UP), array('-1234,5', -1235, IntegerToLocalizedStringTransformer::ROUND_UP), array('-1234,4', -1235, IntegerToLocalizedStringTransformer::ROUND_UP), // towards zero (1.6 -> 1, -1.6 -> -1) array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_DOWN), array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_DOWN), array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_DOWN), array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_DOWN), // round halves (.5) to the next even number array('1234,6', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array('1233,5', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array('1232,5', 1232, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array('-1234,6', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array('-1233,5', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), array('-1232,5', -1232, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), // round halves (.5) away from zero array('1234,6', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array('1234,5', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array('-1234,6', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array('-1234,5', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP), array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_UP), // round halves (.5) towards zero array('1234,6', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array('-1234,6', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), ); } /** * @dataProvider reverseTransformWithRoundingProvider */ public function testReverseTransformWithRounding($input, $output, $roundingMode) { $transformer = new IntegerToLocalizedStringTransformer(null, null, $roundingMode); $this->assertEquals($output, $transformer->reverseTransform($input)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformExpectsString() { $transformer = new IntegerToLocalizedStringTransformer(); $transformer->reverseTransform(1); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformExpectsValidNumber() { $transformer = new IntegerToLocalizedStringTransformer(); $transformer->reverseTransform('foo'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsNaN() { $transformer = new IntegerToLocalizedStringTransformer(); $transformer->reverseTransform('NaN'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsNaN2() { $transformer = new IntegerToLocalizedStringTransformer(); $transformer->reverseTransform('nan'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsInfinity() { $transformer = new IntegerToLocalizedStringTransformer(); $transformer->reverseTransform('∞'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsNegativeInfinity() { $transformer = new IntegerToLocalizedStringTransformer(); $transformer->reverseTransform('-∞'); } } Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php000064400000025025152374770060030670 0ustar00Symfony * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer; use Symfony\Component\Intl\Util\IntlTestHelper; class DateTimeToLocalizedStringTransformerTest extends DateTimeTestCase { protected $dateTime; protected $dateTimeWithoutSeconds; protected function setUp() { parent::setUp(); // Since we test against "de_AT", we need the full implementation IntlTestHelper::requireFullIntl($this); \Locale::setDefault('de_AT'); $this->dateTime = new \DateTime('2010-02-03 04:05:06 UTC'); $this->dateTimeWithoutSeconds = new \DateTime('2010-02-03 04:05:00 UTC'); } protected function tearDown() { $this->dateTime = null; $this->dateTimeWithoutSeconds = null; } public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) { if ($expected instanceof \DateTime && $actual instanceof \DateTime) { $expected = $expected->format('c'); $actual = $actual->format('c'); } parent::assertEquals($expected, $actual, $message, $delta, $maxDepth, $canonicalize, $ignoreCase); } public function dataProvider() { return array( array(\IntlDateFormatter::SHORT, null, null, '03.02.10 04:05', '2010-02-03 04:05:00 UTC'), array(\IntlDateFormatter::MEDIUM, null, null, '03.02.2010 04:05', '2010-02-03 04:05:00 UTC'), array(\IntlDateFormatter::LONG, null, null, '03. Februar 2010 04:05', '2010-02-03 04:05:00 UTC'), array(\IntlDateFormatter::FULL, null, null, 'Mittwoch, 03. Februar 2010 04:05', '2010-02-03 04:05:00 UTC'), array(\IntlDateFormatter::SHORT, \IntlDateFormatter::NONE, null, '03.02.10', '2010-02-03 00:00:00 UTC'), array(\IntlDateFormatter::MEDIUM, \IntlDateFormatter::NONE, null, '03.02.2010', '2010-02-03 00:00:00 UTC'), array(\IntlDateFormatter::LONG, \IntlDateFormatter::NONE, null, '03. Februar 2010', '2010-02-03 00:00:00 UTC'), array(\IntlDateFormatter::FULL, \IntlDateFormatter::NONE, null, 'Mittwoch, 03. Februar 2010', '2010-02-03 00:00:00 UTC'), array(null, \IntlDateFormatter::SHORT, null, '03.02.2010 04:05', '2010-02-03 04:05:00 UTC'), array(null, \IntlDateFormatter::MEDIUM, null, '03.02.2010 04:05:06', '2010-02-03 04:05:06 UTC'), array(null, \IntlDateFormatter::LONG, null, '03.02.2010 04:05:06 GMT', '2010-02-03 04:05:06 UTC'), // see below for extra test case for time format FULL array(\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT, null, '04:05', '1970-01-01 04:05:00 UTC'), array(\IntlDateFormatter::NONE, \IntlDateFormatter::MEDIUM, null, '04:05:06', '1970-01-01 04:05:06 UTC'), array(\IntlDateFormatter::NONE, \IntlDateFormatter::LONG, null, '04:05:06 GMT', '1970-01-01 04:05:06 UTC'), array(null, null, 'yyyy-MM-dd HH:mm:00', '2010-02-03 04:05:00', '2010-02-03 04:05:00 UTC'), array(null, null, 'yyyy-MM-dd HH:mm', '2010-02-03 04:05', '2010-02-03 04:05:00 UTC'), array(null, null, 'yyyy-MM-dd HH', '2010-02-03 04', '2010-02-03 04:00:00 UTC'), array(null, null, 'yyyy-MM-dd', '2010-02-03', '2010-02-03 00:00:00 UTC'), array(null, null, 'yyyy-MM', '2010-02', '2010-02-01 00:00:00 UTC'), array(null, null, 'yyyy', '2010', '2010-01-01 00:00:00 UTC'), array(null, null, 'dd-MM-yyyy', '03-02-2010', '2010-02-03 00:00:00 UTC'), array(null, null, 'HH:mm:ss', '04:05:06', '1970-01-01 04:05:06 UTC'), array(null, null, 'HH:mm:00', '04:05:00', '1970-01-01 04:05:00 UTC'), array(null, null, 'HH:mm', '04:05', '1970-01-01 04:05:00 UTC'), array(null, null, 'HH', '04', '1970-01-01 04:00:00 UTC'), ); } /** * @dataProvider dataProvider */ public function testTransform($dateFormat, $timeFormat, $pattern, $output, $input) { $transformer = new DateTimeToLocalizedStringTransformer( 'UTC', 'UTC', $dateFormat, $timeFormat, \IntlDateFormatter::GREGORIAN, $pattern ); $input = new \DateTime($input); $this->assertEquals($output, $transformer->transform($input)); } public function testTransformFullTime() { $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::FULL); $this->assertEquals('03.02.2010 04:05:06 GMT', $transformer->transform($this->dateTime)); } public function testTransformToDifferentLocale() { \Locale::setDefault('en_US'); $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC'); $this->assertEquals('Feb 3, 2010, 4:05 AM', $transformer->transform($this->dateTime)); } public function testTransformEmpty() { $transformer = new DateTimeToLocalizedStringTransformer(); $this->assertSame('', $transformer->transform(null)); } public function testTransformWithDifferentTimezones() { $transformer = new DateTimeToLocalizedStringTransformer('America/New_York', 'Asia/Hong_Kong'); $input = new \DateTime('2010-02-03 04:05:06 America/New_York'); $dateTime = clone $input; $dateTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); $this->assertEquals($dateTime->format('d.m.Y H:i'), $transformer->transform($input)); } public function testTransformWithDifferentPatterns() { $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'MM*yyyy*dd HH|mm|ss'); $this->assertEquals('02*2010*03 04|05|06', $transformer->transform($this->dateTime)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testTransformRequiresValidDateTime() { $transformer = new DateTimeToLocalizedStringTransformer(); $transformer->transform('2010-01-01'); } public function testTransformWrapsIntlErrors() { $transformer = new DateTimeToLocalizedStringTransformer(); // HOW TO REPRODUCE? //$this->setExpectedException('Symfony\Component\Form\Extension\Core\DataTransformer\Transdate_formationFailedException'); //$transformer->transform(1.5); } /** * @dataProvider dataProvider */ public function testReverseTransform($dateFormat, $timeFormat, $pattern, $input, $output) { $transformer = new DateTimeToLocalizedStringTransformer( 'UTC', 'UTC', $dateFormat, $timeFormat, \IntlDateFormatter::GREGORIAN, $pattern ); $output = new \DateTime($output); $this->assertEquals($output, $transformer->reverseTransform($input)); } public function testReverseTransformFullTime() { $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::FULL); $this->assertDateTimeEquals($this->dateTime, $transformer->reverseTransform('03.02.2010 04:05:06 GMT+00:00')); } public function testReverseTransformFromDifferentLocale() { \Locale::setDefault('en_US'); $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC'); $this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('Feb 3, 2010, 04:05 AM')); } public function testReverseTransformWithDifferentTimezones() { $transformer = new DateTimeToLocalizedStringTransformer('America/New_York', 'Asia/Hong_Kong'); $dateTime = new \DateTime('2010-02-03 04:05:00 Asia/Hong_Kong'); $dateTime->setTimezone(new \DateTimeZone('America/New_York')); $this->assertDateTimeEquals($dateTime, $transformer->reverseTransform('03.02.2010 04:05')); } public function testReverseTransformWithDifferentPatterns() { $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'MM*yyyy*dd HH|mm|ss'); $this->assertDateTimeEquals($this->dateTime, $transformer->reverseTransform('02*2010*03 04|05|06')); } public function testReverseTransformEmpty() { $transformer = new DateTimeToLocalizedStringTransformer(); $this->assertNull($transformer->reverseTransform('')); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformRequiresString() { $transformer = new DateTimeToLocalizedStringTransformer(); $transformer->reverseTransform(12345); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWrapsIntlErrors() { $transformer = new DateTimeToLocalizedStringTransformer(); $transformer->reverseTransform('12345'); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testValidateDateFormatOption() { new DateTimeToLocalizedStringTransformer(null, null, 'foobar'); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testValidateTimeFormatOption() { new DateTimeToLocalizedStringTransformer(null, null, null, 'foobar'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNonExistingDate() { $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::SHORT); $this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('31.04.10 04:05')); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformOutOfTimestampRange() { $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC'); $transformer->reverseTransform('1789-07-14'); } } Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ArrayToPartsTransformerTest.php000064400000007001152374770060026317 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\ArrayToPartsTransformer; class ArrayToPartsTransformerTest extends \PHPUnit_Framework_TestCase { private $transformer; protected function setUp() { $this->transformer = new ArrayToPartsTransformer(array( 'first' => array('a', 'b', 'c'), 'second' => array('d', 'e', 'f'), )); } protected function tearDown() { $this->transformer = null; } public function testTransform() { $input = array( 'a' => '1', 'b' => '2', 'c' => '3', 'd' => '4', 'e' => '5', 'f' => '6', ); $output = array( 'first' => array( 'a' => '1', 'b' => '2', 'c' => '3', ), 'second' => array( 'd' => '4', 'e' => '5', 'f' => '6', ), ); $this->assertSame($output, $this->transformer->transform($input)); } public function testTransformEmpty() { $output = array( 'first' => null, 'second' => null, ); $this->assertSame($output, $this->transformer->transform(null)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testTransformRequiresArray() { $this->transformer->transform('12345'); } public function testReverseTransform() { $input = array( 'first' => array( 'a' => '1', 'b' => '2', 'c' => '3', ), 'second' => array( 'd' => '4', 'e' => '5', 'f' => '6', ), ); $output = array( 'a' => '1', 'b' => '2', 'c' => '3', 'd' => '4', 'e' => '5', 'f' => '6', ); $this->assertSame($output, $this->transformer->reverseTransform($input)); } public function testReverseTransformCompletelyEmpty() { $input = array( 'first' => '', 'second' => '', ); $this->assertNull($this->transformer->reverseTransform($input)); } public function testReverseTransformCompletelyNull() { $input = array( 'first' => null, 'second' => null, ); $this->assertNull($this->transformer->reverseTransform($input)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformPartiallyNull() { $input = array( 'first' => array( 'a' => '1', 'b' => '2', 'c' => '3', ), 'second' => null, ); $this->transformer->reverseTransform($input); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformRequiresArray() { $this->transformer->reverseTransform('12345'); } } Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php000064400000010614152374770060026704 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToRfc3339Transformer; class DateTimeToRfc3339TransformerTest extends DateTimeTestCase { protected $dateTime; protected $dateTimeWithoutSeconds; protected function setUp() { parent::setUp(); $this->dateTime = new \DateTime('2010-02-03 04:05:06 UTC'); $this->dateTimeWithoutSeconds = new \DateTime('2010-02-03 04:05:00 UTC'); } protected function tearDown() { $this->dateTime = null; $this->dateTimeWithoutSeconds = null; } public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE) { if ($expected instanceof \DateTime && $actual instanceof \DateTime) { $expected = $expected->format('c'); $actual = $actual->format('c'); } parent::assertEquals($expected, $actual, $message, $delta, $maxDepth, $canonicalize, $ignoreCase); } public function allProvider() { return array( array('UTC', 'UTC', '2010-02-03 04:05:06 UTC', '2010-02-03T04:05:06Z'), array('UTC', 'UTC', null, ''), array('America/New_York', 'Asia/Hong_Kong', '2010-02-03 04:05:06 America/New_York', '2010-02-03T17:05:06+08:00'), array('America/New_York', 'Asia/Hong_Kong', null, ''), array('UTC', 'Asia/Hong_Kong', '2010-02-03 04:05:06 UTC', '2010-02-03T12:05:06+08:00'), array('America/New_York', 'UTC', '2010-02-03 04:05:06 America/New_York', '2010-02-03T09:05:06Z'), ); } public function transformProvider() { return $this->allProvider(); } public function reverseTransformProvider() { return array_merge($this->allProvider(), array( // format without seconds, as appears in some browsers array('UTC', 'UTC', '2010-02-03 04:05:00 UTC', '2010-02-03T04:05Z'), array('America/New_York', 'Asia/Hong_Kong', '2010-02-03 04:05:00 America/New_York', '2010-02-03T17:05+08:00'), array('Europe/Amsterdam', 'Europe/Amsterdam', '2013-08-21 10:30:00 Europe/Amsterdam', '2013-08-21T08:30:00Z') )); } /** * @dataProvider transformProvider */ public function testTransform($fromTz, $toTz, $from, $to) { $transformer = new DateTimeToRfc3339Transformer($fromTz, $toTz); $this->assertSame($to, $transformer->transform(null !== $from ? new \DateTime($from) : null)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testTransformRequiresValidDateTime() { $transformer = new DateTimeToRfc3339Transformer(); $transformer->transform('2010-01-01'); } /** * @dataProvider reverseTransformProvider */ public function testReverseTransform($toTz, $fromTz, $to, $from) { $transformer = new DateTimeToRfc3339Transformer($toTz, $fromTz); if (null !== $to) { $this->assertDateTimeEquals(new \DateTime($to), $transformer->reverseTransform($from)); } else { $this->assertSame($to, $transformer->reverseTransform($from)); } } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformRequiresString() { $transformer = new DateTimeToRfc3339Transformer(); $transformer->reverseTransform(12345); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNonExistingDate() { $transformer = new DateTimeToRfc3339Transformer('UTC', 'UTC'); $transformer->reverseTransform('2010-04-31T04:05Z'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformExpectsValidDateString() { $transformer = new DateTimeToRfc3339Transformer('UTC', 'UTC'); $transformer->reverseTransform('2010-2010-2010'); } } Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BaseDateTimeTransformerTest.php000064400000002410152374770060026212 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; class BaseDateTimeTransformerTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException * @expectedExceptionMessage this_timezone_does_not_exist */ public function testConstructFailsIfInputTimezoneIsInvalid() { $this->getMock( 'Symfony\Component\Form\Extension\Core\DataTransformer\BaseDateTimeTransformer', array(), array('this_timezone_does_not_exist') ); } /** * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException * @expectedExceptionMessage that_timezone_does_not_exist */ public function testConstructFailsIfOutputTimezoneIsInvalid() { $this->getMock( 'Symfony\Component\Form\Extension\Core\DataTransformer\BaseDateTimeTransformer', array(), array(null, 'that_timezone_does_not_exist') ); } } Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php000064400000004152152374770060030261 0ustar00Symfony * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\MoneyToLocalizedStringTransformer; use Symfony\Component\Intl\Util\IntlTestHelper; class MoneyToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase { protected function setUp() { parent::setUp(); // Since we test against "de_AT", we need the full implementation IntlTestHelper::requireFullIntl($this); \Locale::setDefault('de_AT'); } public function testTransform() { $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100); $this->assertEquals('1,23', $transformer->transform(123)); } public function testTransformExpectsNumeric() { $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $transformer->transform('abcd'); } public function testTransformEmpty() { $transformer = new MoneyToLocalizedStringTransformer(); $this->assertSame('', $transformer->transform(null)); } public function testReverseTransform() { $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100); $this->assertEquals(123, $transformer->reverseTransform('1,23')); } public function testReverseTransformExpectsString() { $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $transformer->reverseTransform(12345); } public function testReverseTransformEmpty() { $transformer = new MoneyToLocalizedStringTransformer(); $this->assertNull($transformer->reverseTransform('')); } } Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.php000064400000006441152374770060027616 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; class DateTimeToTimestampTransformerTest extends DateTimeTestCase { public function testTransform() { $transformer = new DateTimeToTimestampTransformer('UTC', 'UTC'); $input = new \DateTime('2010-02-03 04:05:06 UTC'); $output = $input->format('U'); $this->assertEquals($output, $transformer->transform($input)); } public function testTransformEmpty() { $transformer = new DateTimeToTimestampTransformer(); $this->assertNull($transformer->transform(null)); } public function testTransformWithDifferentTimezones() { $transformer = new DateTimeToTimestampTransformer('Asia/Hong_Kong', 'America/New_York'); $input = new \DateTime('2010-02-03 04:05:06 America/New_York'); $output = $input->format('U'); $input->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); $this->assertEquals($output, $transformer->transform($input)); } public function testTransformFromDifferentTimezone() { $transformer = new DateTimeToTimestampTransformer('Asia/Hong_Kong', 'UTC'); $input = new \DateTime('2010-02-03 04:05:06 Asia/Hong_Kong'); $dateTime = clone $input; $dateTime->setTimezone(new \DateTimeZone('UTC')); $output = $dateTime->format('U'); $this->assertEquals($output, $transformer->transform($input)); } public function testTransformExpectsDateTime() { $transformer = new DateTimeToTimestampTransformer(); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $transformer->transform('1234'); } public function testReverseTransform() { $reverseTransformer = new DateTimeToTimestampTransformer('UTC', 'UTC'); $output = new \DateTime('2010-02-03 04:05:06 UTC'); $input = $output->format('U'); $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input)); } public function testReverseTransformEmpty() { $reverseTransformer = new DateTimeToTimestampTransformer(); $this->assertNull($reverseTransformer->reverseTransform(null)); } public function testReverseTransformWithDifferentTimezones() { $reverseTransformer = new DateTimeToTimestampTransformer('Asia/Hong_Kong', 'America/New_York'); $output = new \DateTime('2010-02-03 04:05:06 America/New_York'); $input = $output->format('U'); $output->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input)); } public function testReverseTransformExpectsValidTimestamp() { $reverseTransformer = new DateTimeToTimestampTransformer(); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $reverseTransformer->reverseTransform('2010-2010-2010'); } } Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php000064400000014757152374770060027132 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; class DateTimeToStringTransformerTest extends DateTimeTestCase { public function dataProvider() { $data = array( array('Y-m-d H:i:s', '2010-02-03 16:05:06', '2010-02-03 16:05:06 UTC'), array('Y-m-d H:i:00', '2010-02-03 16:05:00', '2010-02-03 16:05:00 UTC'), array('Y-m-d H:i', '2010-02-03 16:05', '2010-02-03 16:05:00 UTC'), array('Y-m-d H', '2010-02-03 16', '2010-02-03 16:00:00 UTC'), array('Y-m-d', '2010-02-03', '2010-02-03 00:00:00 UTC'), array('Y-m', '2010-12', '2010-12-01 00:00:00 UTC'), array('Y', '2010', '2010-01-01 00:00:00 UTC'), array('d-m-Y', '03-02-2010', '2010-02-03 00:00:00 UTC'), array('H:i:s', '16:05:06', '1970-01-01 16:05:06 UTC'), array('H:i:00', '16:05:00', '1970-01-01 16:05:00 UTC'), array('H:i', '16:05', '1970-01-01 16:05:00 UTC'), array('H', '16', '1970-01-01 16:00:00 UTC'), // different day representations array('Y-m-j', '2010-02-3', '2010-02-03 00:00:00 UTC'), array('z', '33', '1970-02-03 00:00:00 UTC'), // not bijective // this will not work as PHP will use actual date to replace missing info // and after change of date will lookup for closest Wednesday // i.e. value: 2010-02, PHP value: 2010-02-(today i.e. 20), parsed date: 2010-02-24 //array('Y-m-D', '2010-02-Wed', '2010-02-03 00:00:00 UTC'), //array('Y-m-l', '2010-02-Wednesday', '2010-02-03 00:00:00 UTC'), // different month representations array('Y-n-d', '2010-2-03', '2010-02-03 00:00:00 UTC'), array('Y-M-d', '2010-Feb-03', '2010-02-03 00:00:00 UTC'), array('Y-F-d', '2010-February-03', '2010-02-03 00:00:00 UTC'), // different year representations array('y-m-d', '10-02-03', '2010-02-03 00:00:00 UTC'), // different time representations array('G:i:s', '16:05:06', '1970-01-01 16:05:06 UTC'), array('g:i:s a', '4:05:06 pm', '1970-01-01 16:05:06 UTC'), array('h:i:s a', '04:05:06 pm', '1970-01-01 16:05:06 UTC'), // seconds since Unix array('U', '1265213106', '2010-02-03 16:05:06 UTC'), ); // This test will fail < 5.3.9 - see https://bugs.php.net/51994 if (version_compare(phpversion(), '5.3.9', '>=')) { $data[] = array('Y-z', '2010-33', '2010-02-03 00:00:00 UTC'); } return $data; } /** * @dataProvider dataProvider */ public function testTransform($format, $output, $input) { $transformer = new DateTimeToStringTransformer('UTC', 'UTC', $format); $input = new \DateTime($input); $this->assertEquals($output, $transformer->transform($input)); } public function testTransformEmpty() { $transformer = new DateTimeToStringTransformer(); $this->assertSame('', $transformer->transform(null)); } public function testTransformWithDifferentTimezones() { $transformer = new DateTimeToStringTransformer('Asia/Hong_Kong', 'America/New_York', 'Y-m-d H:i:s'); $input = new \DateTime('2010-02-03 12:05:06 America/New_York'); $output = $input->format('Y-m-d H:i:s'); $input->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); $this->assertEquals($output, $transformer->transform($input)); } public function testTransformExpectsDateTime() { $transformer = new DateTimeToStringTransformer(); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $transformer->transform('1234'); } /** * @dataProvider dataProvider */ public function testReverseTransformUsingPipe($format, $input, $output) { if (version_compare(phpversion(), '5.3.7', '<')) { $this->markTestSkipped('Pipe usage requires PHP 5.3.7 or newer.'); } $reverseTransformer = new DateTimeToStringTransformer('UTC', 'UTC', $format, true); $output = new \DateTime($output); $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input)); } /** * @dataProvider dataProvider */ public function testReverseTransformWithoutUsingPipe($format, $input, $output) { $reverseTransformer = new DateTimeToStringTransformer('UTC', 'UTC', $format, false); $output = new \DateTime($output); $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input)); } public function testReverseTransformEmpty() { $reverseTransformer = new DateTimeToStringTransformer(); $this->assertNull($reverseTransformer->reverseTransform('')); } public function testReverseTransformWithDifferentTimezones() { $reverseTransformer = new DateTimeToStringTransformer('America/New_York', 'Asia/Hong_Kong', 'Y-m-d H:i:s'); $output = new \DateTime('2010-02-03 16:05:06 Asia/Hong_Kong'); $input = $output->format('Y-m-d H:i:s'); $output->setTimeZone(new \DateTimeZone('America/New_York')); $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input)); } public function testReverseTransformExpectsString() { $reverseTransformer = new DateTimeToStringTransformer(); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $reverseTransformer->reverseTransform(1234); } public function testReverseTransformExpectsValidDateString() { $reverseTransformer = new DateTimeToStringTransformer(); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $reverseTransformer->reverseTransform('2010-2010-2010'); } public function testReverseTransformWithNonExistingDate() { $reverseTransformer = new DateTimeToStringTransformer(); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $reverseTransformer->reverseTransform('2010-04-31'); } } Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php000064400000037503152374770060026734 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; class DateTimeToArrayTransformerTest extends DateTimeTestCase { public function testTransform() { $transformer = new DateTimeToArrayTransformer('UTC', 'UTC'); $input = new \DateTime('2010-02-03 04:05:06 UTC'); $output = array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '6', ); $this->assertSame($output, $transformer->transform($input)); } public function testTransformEmpty() { $transformer = new DateTimeToArrayTransformer(); $output = array( 'year' => '', 'month' => '', 'day' => '', 'hour' => '', 'minute' => '', 'second' => '', ); $this->assertSame($output, $transformer->transform(null)); } public function testTransformEmptyWithFields() { $transformer = new DateTimeToArrayTransformer(null, null, array('year', 'minute', 'second')); $output = array( 'year' => '', 'minute' => '', 'second' => '', ); $this->assertSame($output, $transformer->transform(null)); } public function testTransformWithFields() { $transformer = new DateTimeToArrayTransformer('UTC', 'UTC', array('year', 'month', 'minute', 'second')); $input = new \DateTime('2010-02-03 04:05:06 UTC'); $output = array( 'year' => '2010', 'month' => '2', 'minute' => '5', 'second' => '6', ); $this->assertSame($output, $transformer->transform($input)); } public function testTransformWithPadding() { $transformer = new DateTimeToArrayTransformer('UTC', 'UTC', null, true); $input = new \DateTime('2010-02-03 04:05:06 UTC'); $output = array( 'year' => '2010', 'month' => '02', 'day' => '03', 'hour' => '04', 'minute' => '05', 'second' => '06', ); $this->assertSame($output, $transformer->transform($input)); } public function testTransformDifferentTimezones() { $transformer = new DateTimeToArrayTransformer('America/New_York', 'Asia/Hong_Kong'); $input = new \DateTime('2010-02-03 04:05:06 America/New_York'); $dateTime = new \DateTime('2010-02-03 04:05:06 America/New_York'); $dateTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); $output = array( 'year' => (string) (int) $dateTime->format('Y'), 'month' => (string) (int) $dateTime->format('m'), 'day' => (string) (int) $dateTime->format('d'), 'hour' => (string) (int) $dateTime->format('H'), 'minute' => (string) (int) $dateTime->format('i'), 'second' => (string) (int) $dateTime->format('s'), ); $this->assertSame($output, $transformer->transform($input)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testTransformRequiresDateTime() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform('12345'); } public function testReverseTransform() { $transformer = new DateTimeToArrayTransformer('UTC', 'UTC'); $input = array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '6', ); $output = new \DateTime('2010-02-03 04:05:06 UTC'); $this->assertDateTimeEquals($output, $transformer->reverseTransform($input)); } public function testReverseTransformWithSomeZero() { $transformer = new DateTimeToArrayTransformer('UTC', 'UTC'); $input = array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '0', 'second' => '0', ); $output = new \DateTime('2010-02-03 04:00:00 UTC'); $this->assertDateTimeEquals($output, $transformer->reverseTransform($input)); } public function testReverseTransformCompletelyEmpty() { $transformer = new DateTimeToArrayTransformer(); $input = array( 'year' => '', 'month' => '', 'day' => '', 'hour' => '', 'minute' => '', 'second' => '', ); $this->assertNull($transformer->reverseTransform($input)); } public function testReverseTransformCompletelyEmptySubsetOfFields() { $transformer = new DateTimeToArrayTransformer(null, null, array('year', 'month', 'day')); $input = array( 'year' => '', 'month' => '', 'day' => '', ); $this->assertNull($transformer->reverseTransform($input)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformPartiallyEmptyYear() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformPartiallyEmptyMonth() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformPartiallyEmptyDay() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformPartiallyEmptyHour() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '3', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformPartiallyEmptyMinute() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '4', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformPartiallyEmptySecond() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5', )); } public function testReverseTransformNull() { $transformer = new DateTimeToArrayTransformer(); $this->assertNull($transformer->reverseTransform(null)); } public function testReverseTransformDifferentTimezones() { $transformer = new DateTimeToArrayTransformer('America/New_York', 'Asia/Hong_Kong'); $input = array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '6', ); $output = new \DateTime('2010-02-03 04:05:06 Asia/Hong_Kong'); $output->setTimezone(new \DateTimeZone('America/New_York')); $this->assertDateTimeEquals($output, $transformer->reverseTransform($input)); } public function testReverseTransformToDifferentTimezone() { $transformer = new DateTimeToArrayTransformer('Asia/Hong_Kong', 'UTC'); $input = array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '6', ); $output = new \DateTime('2010-02-03 04:05:06 UTC'); $output->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); $this->assertDateTimeEquals($output, $transformer->reverseTransform($input)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformRequiresArray() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform('12345'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNegativeYear() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '-1', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNegativeMonth() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '-1', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNegativeDay() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '-1', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNegativeHour() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '-1', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNegativeMinute() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '-1', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNegativeSecond() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '-1', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithInvalidMonth() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '13', 'day' => '3', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithInvalidDay() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '31', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithStringDay() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => 'bazinga', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithStringMonth() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => 'bazinga', 'day' => '31', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithStringYear() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => 'bazinga', 'month' => '2', 'day' => '31', 'hour' => '4', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithEmptyStringHour() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '31', 'hour' => '', 'minute' => '5', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithEmptyStringMinute() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '31', 'hour' => '4', 'minute' => '', 'second' => '6', )); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithEmptyStringSecond() { $transformer = new DateTimeToArrayTransformer(); $transformer->reverseTransform(array( 'year' => '2010', 'month' => '2', 'day' => '31', 'hour' => '4', 'minute' => '5', 'second' => '', )); } } Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php000064400000007237152374770060030601 0ustar00Symfony * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\PercentToLocalizedStringTransformer; use Symfony\Component\Intl\Util\IntlTestHelper; class PercentToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase { protected function setUp() { parent::setUp(); // Since we test against "de_AT", we need the full implementation IntlTestHelper::requireFullIntl($this); \Locale::setDefault('de_AT'); } public function testTransform() { $transformer = new PercentToLocalizedStringTransformer(); $this->assertEquals('10', $transformer->transform(0.1)); $this->assertEquals('15', $transformer->transform(0.15)); $this->assertEquals('12', $transformer->transform(0.1234)); $this->assertEquals('200', $transformer->transform(2)); } public function testTransformEmpty() { $transformer = new PercentToLocalizedStringTransformer(); $this->assertEquals('', $transformer->transform(null)); } public function testTransformWithInteger() { $transformer = new PercentToLocalizedStringTransformer(null, 'integer'); $this->assertEquals('0', $transformer->transform(0.1)); $this->assertEquals('1', $transformer->transform(1)); $this->assertEquals('15', $transformer->transform(15)); $this->assertEquals('16', $transformer->transform(15.9)); } public function testTransformWithPrecision() { $transformer = new PercentToLocalizedStringTransformer(2); $this->assertEquals('12,34', $transformer->transform(0.1234)); } public function testReverseTransform() { $transformer = new PercentToLocalizedStringTransformer(); $this->assertEquals(0.1, $transformer->reverseTransform('10')); $this->assertEquals(0.15, $transformer->reverseTransform('15')); $this->assertEquals(0.12, $transformer->reverseTransform('12')); $this->assertEquals(2, $transformer->reverseTransform('200')); } public function testReverseTransformEmpty() { $transformer = new PercentToLocalizedStringTransformer(); $this->assertNull($transformer->reverseTransform('')); } public function testReverseTransformWithInteger() { $transformer = new PercentToLocalizedStringTransformer(null, 'integer'); $this->assertEquals(10, $transformer->reverseTransform('10')); $this->assertEquals(15, $transformer->reverseTransform('15')); $this->assertEquals(12, $transformer->reverseTransform('12')); $this->assertEquals(200, $transformer->reverseTransform('200')); } public function testReverseTransformWithPrecision() { $transformer = new PercentToLocalizedStringTransformer(2); $this->assertEquals(0.1234, $transformer->reverseTransform('12,34')); } public function testTransformExpectsNumeric() { $transformer = new PercentToLocalizedStringTransformer(); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $transformer->transform('foo'); } public function testReverseTransformExpectsString() { $transformer = new PercentToLocalizedStringTransformer(); $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); $transformer->reverseTransform(1); } } Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.php000064400000003663152374770060026430 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer; class ChoiceToValueTransformerTest extends \PHPUnit_Framework_TestCase { protected $transformer; protected function setUp() { $list = new SimpleChoiceList(array('' => 'A', 0 => 'B', 1 => 'C')); $this->transformer = new ChoiceToValueTransformer($list); } protected function tearDown() { $this->transformer = null; } public function transformProvider() { return array( // more extensive test set can be found in FormUtilTest array(0, '0'), array(false, '0'), array('', ''), ); } /** * @dataProvider transformProvider */ public function testTransform($in, $out) { $this->assertSame($out, $this->transformer->transform($in)); } public function reverseTransformProvider() { return array( // values are expected to be valid choice keys already and stay // the same array('0', 0), array('', null), array(null, null), ); } /** * @dataProvider reverseTransformProvider */ public function testReverseTransform($in, $out) { $this->assertSame($out, $this->transformer->reverseTransform($in)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformExpectsScalar() { $this->transformer->reverseTransform(array()); } } Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php000064400000005474152374770060027335 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\ValueToDuplicatesTransformer; class ValueToDuplicatesTransformerTest extends \PHPUnit_Framework_TestCase { private $transformer; protected function setUp() { $this->transformer = new ValueToDuplicatesTransformer(array('a', 'b', 'c')); } protected function tearDown() { $this->transformer = null; } public function testTransform() { $output = array( 'a' => 'Foo', 'b' => 'Foo', 'c' => 'Foo', ); $this->assertSame($output, $this->transformer->transform('Foo')); } public function testTransformEmpty() { $output = array( 'a' => null, 'b' => null, 'c' => null, ); $this->assertSame($output, $this->transformer->transform(null)); } public function testReverseTransform() { $input = array( 'a' => 'Foo', 'b' => 'Foo', 'c' => 'Foo', ); $this->assertSame('Foo', $this->transformer->reverseTransform($input)); } public function testReverseTransformCompletelyEmpty() { $input = array( 'a' => '', 'b' => '', 'c' => '', ); $this->assertNull($this->transformer->reverseTransform($input)); } public function testReverseTransformCompletelyNull() { $input = array( 'a' => null, 'b' => null, 'c' => null, ); $this->assertNull($this->transformer->reverseTransform($input)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformPartiallyNull() { $input = array( 'a' => 'Foo', 'b' => 'Foo', 'c' => null, ); $this->transformer->reverseTransform($input); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDifferences() { $input = array( 'a' => 'Foo', 'b' => 'Bar', 'c' => 'Foo', ); $this->transformer->reverseTransform($input); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformRequiresArray() { $this->transformer->reverseTransform('12345'); } } Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php000064400000003647152374770060027011 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\BooleanToStringTransformer; class BooleanToStringTransformerTest extends \PHPUnit_Framework_TestCase { const TRUE_VALUE = '1'; /** * @var BooleanToStringTransformer */ protected $transformer; protected function setUp() { $this->transformer = new BooleanToStringTransformer(self::TRUE_VALUE); } protected function tearDown() { $this->transformer = null; } public function testTransform() { $this->assertEquals(self::TRUE_VALUE, $this->transformer->transform(true)); $this->assertNull($this->transformer->transform(false)); } // https://github.com/symfony/symfony/issues/8989 public function testTransformAcceptsNull() { $this->assertNull($this->transformer->transform(null)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testTransformFailsIfString() { $this->transformer->transform('1'); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformFailsIfInteger() { $this->transformer->reverseTransform(1); } public function testReverseTransform() { $this->assertTrue($this->transformer->reverseTransform(self::TRUE_VALUE)); $this->assertTrue($this->transformer->reverseTransform('foobar')); $this->assertTrue($this->transformer->reverseTransform('')); $this->assertFalse($this->transformer->reverseTransform(null)); } } Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DataTransformerChainTest.php000064400000004207152374770060025545 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DataTransformerChain; class DataTransformerChainTest extends \PHPUnit_Framework_TestCase { public function testTransform() { $transformer1 = $this->getMock('Symfony\Component\Form\DataTransformerInterface'); $transformer1->expects($this->once()) ->method('transform') ->with($this->identicalTo('foo')) ->will($this->returnValue('bar')); $transformer2 = $this->getMock('Symfony\Component\Form\DataTransformerInterface'); $transformer2->expects($this->once()) ->method('transform') ->with($this->identicalTo('bar')) ->will($this->returnValue('baz')); $chain = new DataTransformerChain(array($transformer1, $transformer2)); $this->assertEquals('baz', $chain->transform('foo')); } public function testReverseTransform() { $transformer2 = $this->getMock('Symfony\Component\Form\DataTransformerInterface'); $transformer2->expects($this->once()) ->method('reverseTransform') ->with($this->identicalTo('foo')) ->will($this->returnValue('bar')); $transformer1 = $this->getMock('Symfony\Component\Form\DataTransformerInterface'); $transformer1->expects($this->once()) ->method('reverseTransform') ->with($this->identicalTo('bar')) ->will($this->returnValue('baz')); $chain = new DataTransformerChain(array($transformer1, $transformer2)); $this->assertEquals('baz', $chain->reverseTransform('foo')); } } Symfony/Component/Form/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.php000064400000004051152374770060026766 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToValuesTransformer; class ChoicesToValuesTransformerTest extends \PHPUnit_Framework_TestCase { protected $transformer; protected function setUp() { $list = new SimpleChoiceList(array(0 => 'A', 1 => 'B', 2 => 'C')); $this->transformer = new ChoicesToValuesTransformer($list); } protected function tearDown() { $this->transformer = null; } public function testTransform() { // Value strategy in SimpleChoiceList is to copy and convert to string $in = array(0, 1, 2); $out = array('0', '1', '2'); $this->assertSame($out, $this->transformer->transform($in)); } public function testTransformNull() { $this->assertSame(array(), $this->transformer->transform(null)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testTransformExpectsArray() { $this->transformer->transform('foobar'); } public function testReverseTransform() { // values are expected to be valid choices and stay the same $in = array('0', '1', '2'); $out = array(0, 1, 2); $this->assertSame($out, $this->transformer->reverseTransform($in)); } public function testReverseTransformNull() { $this->assertSame(array(), $this->transformer->reverseTransform(null)); } /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformExpectsArray() { $this->transformer->reverseTransform('foobar'); } } Symfony/Component/Form/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php000064400000005645152374770060023335 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; use Symfony\Component\Form\Extension\Core\ChoiceList\LazyChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; class LazyChoiceListTest extends \PHPUnit_Framework_TestCase { private $list; protected function setUp() { parent::setUp(); $this->list = new LazyChoiceListTest_Impl(new SimpleChoiceList(array( 'a' => 'A', 'b' => 'B', 'c' => 'C', ), array('b'))); } protected function tearDown() { parent::tearDown(); $this->list = null; } public function testGetChoices() { $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c'), $this->list->getChoices()); } public function testGetValues() { $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c'), $this->list->getValues()); } public function testGetPreferredViews() { $this->assertEquals(array(1 => new ChoiceView('b', 'b', 'B')), $this->list->getPreferredViews()); } public function testGetRemainingViews() { $this->assertEquals(array(0 => new ChoiceView('a', 'a', 'A'), 2 => new ChoiceView('c', 'c', 'C')), $this->list->getRemainingViews()); } public function testGetIndicesForChoices() { $choices = array('b', 'c'); $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); } public function testGetIndicesForValues() { $values = array('b', 'c'); $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); } public function testGetChoicesForValues() { $values = array('b', 'c'); $this->assertSame(array('b', 'c'), $this->list->getChoicesForValues($values)); } public function testGetValuesForChoices() { $choices = array('b', 'c'); $this->assertSame(array('b', 'c'), $this->list->getValuesForChoices($choices)); } /** * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException */ public function testLoadChoiceListShouldReturnChoiceList() { $list = new LazyChoiceListTest_InvalidImpl(); $list->getChoices(); } } class LazyChoiceListTest_Impl extends LazyChoiceList { private $choiceList; public function __construct($choiceList) { $this->choiceList = $choiceList; } protected function loadChoiceList() { return $this->choiceList; } } class LazyChoiceListTest_InvalidImpl extends LazyChoiceList { protected function loadChoiceList() { return new \stdClass(); } } Symfony/Component/Form/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php000064400000017327152374770060024161 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; /** * @author Bernhard Schussek */ abstract class AbstractChoiceListTest extends \PHPUnit_Framework_TestCase { /** * @var \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected $list; /** * @var array */ protected $choices; /** * @var array */ protected $values; /** * @var array */ protected $indices; /** * @var array */ protected $labels; /** * @var mixed */ protected $choice1; /** * @var mixed */ protected $choice2; /** * @var mixed */ protected $choice3; /** * @var mixed */ protected $choice4; /** * @var string */ protected $value1; /** * @var string */ protected $value2; /** * @var string */ protected $value3; /** * @var string */ protected $value4; /** * @var int|string */ protected $index1; /** * @var int|string */ protected $index2; /** * @var int|string */ protected $index3; /** * @var int|string */ protected $index4; /** * @var string */ protected $label1; /** * @var string */ protected $label2; /** * @var string */ protected $label3; /** * @var string */ protected $label4; protected function setUp() { parent::setUp(); $this->list = $this->createChoiceList(); $this->choices = $this->getChoices(); $this->indices = $this->getIndices(); $this->values = $this->getValues(); $this->labels = $this->getLabels(); // allow access to the individual entries without relying on their indices reset($this->choices); reset($this->indices); reset($this->values); reset($this->labels); for ($i = 1; $i <= 4; ++$i) { $this->{'choice'.$i} = current($this->choices); $this->{'index'.$i} = current($this->indices); $this->{'value'.$i} = current($this->values); $this->{'label'.$i} = current($this->labels); next($this->choices); next($this->indices); next($this->values); next($this->labels); } } public function testGetChoices() { $this->assertSame($this->choices, $this->list->getChoices()); } public function testGetValues() { $this->assertSame($this->values, $this->list->getValues()); } public function testGetIndicesForChoices() { $choices = array($this->choice1, $this->choice2); $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); } public function testGetIndicesForChoicesPreservesKeys() { $choices = array(5 => $this->choice1, 8 => $this->choice2); $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForChoices($choices)); } public function testGetIndicesForChoicesPreservesOrder() { $choices = array($this->choice2, $this->choice1); $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForChoices($choices)); } public function testGetIndicesForChoicesIgnoresNonExistingChoices() { $choices = array($this->choice1, $this->choice2, 'foobar'); $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); } public function testGetIndicesForChoicesEmpty() { $this->assertSame(array(), $this->list->getIndicesForChoices(array())); } public function testGetIndicesForValues() { // values and indices are always the same $values = array($this->value1, $this->value2); $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForValues($values)); } public function testGetIndicesForValuesPreservesKeys() { // values and indices are always the same $values = array(5 => $this->value1, 8 => $this->value2); $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForValues($values)); } public function testGetIndicesForValuesPreservesOrder() { $values = array($this->value2, $this->value1); $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForValues($values)); } public function testGetIndicesForValuesIgnoresNonExistingValues() { $values = array($this->value1, $this->value2, 'foobar'); $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForValues($values)); } public function testGetIndicesForValuesEmpty() { $this->assertSame(array(), $this->list->getIndicesForValues(array())); } public function testGetChoicesForValues() { $values = array($this->value1, $this->value2); $this->assertSame(array($this->choice1, $this->choice2), $this->list->getChoicesForValues($values)); } public function testGetChoicesForValuesPreservesKeys() { $values = array(5 => $this->value1, 8 => $this->value2); $this->assertSame(array(5 => $this->choice1, 8 => $this->choice2), $this->list->getChoicesForValues($values)); } public function testGetChoicesForValuesPreservesOrder() { $values = array($this->value2, $this->value1); $this->assertSame(array($this->choice2, $this->choice1), $this->list->getChoicesForValues($values)); } public function testGetChoicesForValuesIgnoresNonExistingValues() { $values = array($this->value1, $this->value2, 'foobar'); $this->assertSame(array($this->choice1, $this->choice2), $this->list->getChoicesForValues($values)); } // https://github.com/symfony/symfony/issues/3446 public function testGetChoicesForValuesEmpty() { $this->assertSame(array(), $this->list->getChoicesForValues(array())); } public function testGetValuesForChoices() { $choices = array($this->choice1, $this->choice2); $this->assertSame(array($this->value1, $this->value2), $this->list->getValuesForChoices($choices)); } public function testGetValuesForChoicesPreservesKeys() { $choices = array(5 => $this->choice1, 8 => $this->choice2); $this->assertSame(array(5 => $this->value1, 8 => $this->value2), $this->list->getValuesForChoices($choices)); } public function testGetValuesForChoicesPreservesOrder() { $choices = array($this->choice2, $this->choice1); $this->assertSame(array($this->value2, $this->value1), $this->list->getValuesForChoices($choices)); } public function testGetValuesForChoicesIgnoresNonExistingChoices() { $choices = array($this->choice1, $this->choice2, 'foobar'); $this->assertSame(array($this->value1, $this->value2), $this->list->getValuesForChoices($choices)); } public function testGetValuesForChoicesEmpty() { $this->assertSame(array(), $this->list->getValuesForChoices(array())); } /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ abstract protected function createChoiceList(); abstract protected function getChoices(); abstract protected function getLabels(); abstract protected function getValues(); abstract protected function getIndices(); } Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php000064400000004266152374770060025170 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; class SimpleNumericChoiceListTest extends AbstractChoiceListTest { public function testGetIndicesForChoicesDealsWithNumericChoices() { // Pass choices as strings although they are integers $choices = array('0', '1'); $this->assertSame(array(0, 1), $this->list->getIndicesForChoices($choices)); } public function testGetIndicesForValuesDealsWithNumericValues() { // Pass values as strings although they are integers $values = array('0', '1'); $this->assertSame(array(0, 1), $this->list->getIndicesForValues($values)); } public function testGetChoicesForValuesDealsWithNumericValues() { // Pass values as strings although they are integers $values = array('0', '1'); $this->assertSame(array(0, 1), $this->list->getChoicesForValues($values)); } public function testGetValuesForChoicesDealsWithNumericValues() { // Pass values as strings although they are integers $values = array('0', '1'); $this->assertSame(array('0', '1'), $this->list->getValuesForChoices($values)); } /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected function createChoiceList() { return new SimpleChoiceList(array( 'Group 1' => array(0 => 'A', 1 => 'B'), 'Group 2' => array(2 => 'C', 3 => 'D'), ), array(1, 2)); } protected function getChoices() { return array(0 => 0, 1 => 1, 2 => 2, 3 => 3); } protected function getLabels() { return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); } protected function getValues() { return array(0 => '0', 1 => '1', 2 => '2', 3 => '3'); } protected function getIndices() { return array(0, 1, 2, 3); } } Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php000064400000020374152374770060023620 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; class ObjectChoiceListTest_EntityWithToString { private $property; public function __construct($property) { $this->property = $property; } public function __toString() { return $this->property; } } class ObjectChoiceListTest extends AbstractChoiceListTest { private $obj1; private $obj2; private $obj3; private $obj4; protected function setUp() { $this->obj1 = (object) array('name' => 'A'); $this->obj2 = (object) array('name' => 'B'); $this->obj3 = (object) array('name' => 'C'); $this->obj4 = (object) array('name' => 'D'); parent::setUp(); } public function testInitArray() { $this->list = new ObjectChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4), 'name', array($this->obj2) ); $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices()); $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues()); $this->assertEquals(array(1 => new ChoiceView($this->obj2, '1', 'B')), $this->list->getPreferredViews()); $this->assertEquals(array(0 => new ChoiceView($this->obj1, '0', 'A'), 2 => new ChoiceView($this->obj3, '2', 'C'), 3 => new ChoiceView($this->obj4, '3', 'D')), $this->list->getRemainingViews()); } public function testInitNestedArray() { $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices()); $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues()); $this->assertEquals(array( 'Group 1' => array(1 => new ChoiceView($this->obj2, '1', 'B')), 'Group 2' => array(2 => new ChoiceView($this->obj3, '2', 'C')) ), $this->list->getPreferredViews()); $this->assertEquals(array( 'Group 1' => array(0 => new ChoiceView($this->obj1, '0', 'A')), 'Group 2' => array(3 => new ChoiceView($this->obj4, '3', 'D')) ), $this->list->getRemainingViews()); } public function testInitArrayWithGroupPath() { $this->obj1 = (object) array('name' => 'A', 'category' => 'Group 1'); $this->obj2 = (object) array('name' => 'B', 'category' => 'Group 1'); $this->obj3 = (object) array('name' => 'C', 'category' => 'Group 2'); $this->obj4 = (object) array('name' => 'D', 'category' => 'Group 2'); // Objects with NULL groups are not grouped $obj5 = (object) array('name' => 'E', 'category' => null); // Objects without the group property are not grouped either // see https://github.com/symfony/symfony/commit/d9b7abb7c7a0f28e0ce970afc5e305dce5dccddf $obj6 = (object) array('name' => 'F'); $this->list = new ObjectChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4, $obj5, $obj6), 'name', array($this->obj2, $this->obj3), 'category' ); $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4, $obj5, $obj6), $this->list->getChoices()); $this->assertSame(array('0', '1', '2', '3', '4', '5'), $this->list->getValues()); $this->assertEquals(array( 'Group 1' => array(1 => new ChoiceView($this->obj2, '1', 'B')), 'Group 2' => array(2 => new ChoiceView($this->obj3, '2', 'C')) ), $this->list->getPreferredViews()); $this->assertEquals(array( 'Group 1' => array(0 => new ChoiceView($this->obj1, '0', 'A')), 'Group 2' => array(3 => new ChoiceView($this->obj4, '3', 'D')), 4 => new ChoiceView($obj5, '4', 'E'), 5 => new ChoiceView($obj6, '5', 'F'), ), $this->list->getRemainingViews()); } /** * @expectedException \InvalidArgumentException */ public function testInitArrayWithGroupPathThrowsExceptionIfNestedArray() { $this->obj1 = (object) array('name' => 'A', 'category' => 'Group 1'); $this->obj2 = (object) array('name' => 'B', 'category' => 'Group 1'); $this->obj3 = (object) array('name' => 'C', 'category' => 'Group 2'); $this->obj4 = (object) array('name' => 'D', 'category' => 'Group 2'); new ObjectChoiceList( array( 'Group 1' => array($this->obj1, $this->obj2), 'Group 2' => array($this->obj3, $this->obj4), ), 'name', array($this->obj2, $this->obj3), 'category' ); } public function testInitArrayWithValuePath() { $this->obj1 = (object) array('name' => 'A', 'id' => 10); $this->obj2 = (object) array('name' => 'B', 'id' => 20); $this->obj3 = (object) array('name' => 'C', 'id' => 30); $this->obj4 = (object) array('name' => 'D', 'id' => 40); $this->list = new ObjectChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4), 'name', array($this->obj2, $this->obj3), null, 'id' ); $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices()); $this->assertSame(array('10', '20', '30', '40'), $this->list->getValues()); $this->assertEquals(array(1 => new ChoiceView($this->obj2, '20', 'B'), 2 => new ChoiceView($this->obj3, '30', 'C')), $this->list->getPreferredViews()); $this->assertEquals(array(0 => new ChoiceView($this->obj1, '10', 'A'), 3 => new ChoiceView($this->obj4, '40', 'D')), $this->list->getRemainingViews()); } public function testInitArrayUsesToString() { $this->obj1 = new ObjectChoiceListTest_EntityWithToString('A'); $this->obj2 = new ObjectChoiceListTest_EntityWithToString('B'); $this->obj3 = new ObjectChoiceListTest_EntityWithToString('C'); $this->obj4 = new ObjectChoiceListTest_EntityWithToString('D'); $this->list = new ObjectChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4) ); $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices()); $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues()); $this->assertEquals(array(0 => new ChoiceView($this->obj1, '0', 'A'), 1 => new ChoiceView($this->obj2, '1', 'B'), 2 => new ChoiceView($this->obj3, '2', 'C'), 3 => new ChoiceView($this->obj4, '3', 'D')), $this->list->getRemainingViews()); } /** * @expectedException \Symfony\Component\Form\Exception\StringCastException */ public function testInitArrayThrowsExceptionIfToStringNotFound() { $this->obj1 = new ObjectChoiceListTest_EntityWithToString('A'); $this->obj2 = new ObjectChoiceListTest_EntityWithToString('B'); $this->obj3 = (object) array('name' => 'C'); $this->obj4 = new ObjectChoiceListTest_EntityWithToString('D'); new ObjectChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4) ); } /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected function createChoiceList() { return new ObjectChoiceList( array( 'Group 1' => array($this->obj1, $this->obj2), 'Group 2' => array($this->obj3, $this->obj4), ), 'name', array($this->obj2, $this->obj3) ); } protected function getChoices() { return array(0 => $this->obj1, 1 => $this->obj2, 2 => $this->obj3, 3 => $this->obj4); } protected function getLabels() { return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); } protected function getValues() { return array(0 => '0', 1 => '1', 2 => '2', 3 => '3'); } protected function getIndices() { return array(0, 1, 2, 3); } } Symfony/Component/Form/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php000064400000006602152374770060023641 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; class SimpleChoiceListTest extends AbstractChoiceListTest { public function testInitArray() { $choices = array('a' => 'A', 'b' => 'B', 'c' => 'C'); $this->list = new SimpleChoiceList($choices, array('b')); $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c'), $this->list->getChoices()); $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c'), $this->list->getValues()); $this->assertEquals(array(1 => new ChoiceView('b', 'b', 'B')), $this->list->getPreferredViews()); $this->assertEquals(array(0 => new ChoiceView('a', 'a', 'A'), 2 => new ChoiceView('c', 'c', 'C')), $this->list->getRemainingViews()); } public function testInitNestedArray() { $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'), $this->list->getChoices()); $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'), $this->list->getValues()); $this->assertEquals(array( 'Group 1' => array(1 => new ChoiceView('b', 'b', 'B')), 'Group 2' => array(2 => new ChoiceView('c', 'c', 'C')) ), $this->list->getPreferredViews()); $this->assertEquals(array( 'Group 1' => array(0 => new ChoiceView('a', 'a', 'A')), 'Group 2' => array(3 => new ChoiceView('d', 'd', 'D')) ), $this->list->getRemainingViews()); } /** * @dataProvider dirtyValuesProvider */ public function testGetValuesForChoicesDealsWithDirtyValues($choice, $value) { $choices = array( '0' => 'Zero', '1' => 'One', '' => 'Empty', '1.23' => 'Float', 'foo' => 'Foo', 'foo10' => 'Foo 10', ); $this->list = new SimpleChoiceList($choices, array()); $this->assertSame(array($value), $this->list->getValuesForChoices(array($choice))); } public function dirtyValuesProvider() { return array( array(0, '0'), array('0', '0'), array('1', '1'), array(false, '0'), array(true, '1'), array('', ''), array(null, ''), array('1.23', '1.23'), array('foo', 'foo'), array('foo10', 'foo10'), ); } /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected function createChoiceList() { return new SimpleChoiceList(array( 'Group 1' => array('a' => 'A', 'b' => 'B'), 'Group 2' => array('c' => 'C', 'd' => 'D'), ), array('b', 'c')); } protected function getChoices() { return array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'); } protected function getLabels() { return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); } protected function getValues() { return array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'); } protected function getIndices() { return array(0, 1, 2, 3); } } Symfony/Component/Form/Tests/Extension/Core/ChoiceList/ChoiceListTest.php000064400000012051152374770060022462 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; class ChoiceListTest extends AbstractChoiceListTest { private $obj1; private $obj2; private $obj3; private $obj4; protected function setUp() { $this->obj1 = new \stdClass(); $this->obj2 = new \stdClass(); $this->obj3 = new \stdClass(); $this->obj4 = new \stdClass(); parent::setUp(); } public function testInitArray() { $this->list = new ChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4), array('A', 'B', 'C', 'D'), array($this->obj2) ); $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices()); $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues()); $this->assertEquals(array(1 => new ChoiceView($this->obj2, '1', 'B')), $this->list->getPreferredViews()); $this->assertEquals(array(0 => new ChoiceView($this->obj1, '0', 'A'), 2 => new ChoiceView($this->obj3, '2', 'C'), 3 => new ChoiceView($this->obj4, '3', 'D')), $this->list->getRemainingViews()); } /** * Necessary for interoperability with MongoDB cursors or ORM relations as * choices parameter. A choice itself that is an object implementing \Traversable * is not treated as hierarchical structure, but as-is. */ public function testInitNestedTraversable() { $traversableChoice = new \ArrayIterator(array($this->obj3, $this->obj4)); $this->list = new ChoiceList( new \ArrayIterator(array( 'Group' => array($this->obj1, $this->obj2), 'Not a Group' => $traversableChoice )), array( 'Group' => array('A', 'B'), 'Not a Group' => 'C', ), array($this->obj2) ); $this->assertSame(array($this->obj1, $this->obj2, $traversableChoice), $this->list->getChoices()); $this->assertSame(array('0', '1', '2'), $this->list->getValues()); $this->assertEquals(array( 'Group' => array(1 => new ChoiceView($this->obj2, '1', 'B')) ), $this->list->getPreferredViews()); $this->assertEquals(array( 'Group' => array(0 => new ChoiceView($this->obj1, '0', 'A')), 2 => new ChoiceView($traversableChoice, '2', 'C') ), $this->list->getRemainingViews()); } public function testInitNestedArray() { $this->assertSame(array($this->obj1, $this->obj2, $this->obj3, $this->obj4), $this->list->getChoices()); $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues()); $this->assertEquals(array( 'Group 1' => array(1 => new ChoiceView($this->obj2, '1', 'B')), 'Group 2' => array(2 => new ChoiceView($this->obj3, '2', 'C')) ), $this->list->getPreferredViews()); $this->assertEquals(array( 'Group 1' => array(0 => new ChoiceView($this->obj1, '0', 'A')), 'Group 2' => array(3 => new ChoiceView($this->obj4, '3', 'D')) ), $this->list->getRemainingViews()); } /** * @expectedException \InvalidArgumentException */ public function testInitWithInsufficientLabels() { $this->list = new ChoiceList( array($this->obj1, $this->obj2), array('A') ); } public function testInitWithLabelsContainingNull() { $this->list = new ChoiceList( array($this->obj1, $this->obj2), array('A', null) ); $this->assertEquals( array(0 => new ChoiceView($this->obj1, '0', 'A'), 1 => new ChoiceView($this->obj2, '1', null)), $this->list->getRemainingViews() ); } /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ protected function createChoiceList() { return new ChoiceList( array( 'Group 1' => array($this->obj1, $this->obj2), 'Group 2' => array($this->obj3, $this->obj4), ), array( 'Group 1' => array('A', 'B'), 'Group 2' => array('C', 'D'), ), array($this->obj2, $this->obj3) ); } protected function getChoices() { return array(0 => $this->obj1, 1 => $this->obj2, 2 => $this->obj3, 3 => $this->obj4); } protected function getLabels() { return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); } protected function getValues() { return array(0 => '0', 1 => '1', 2 => '2', 3 => '3'); } protected function getIndices() { return array(0, 1, 2, 3); } } Symfony/Component/Form/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php000064400000006052152374770060025434 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Core\EventListener\FixRadioInputListener; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; class FixRadioInputListenerTest extends \PHPUnit_Framework_TestCase { private $choiceList; protected function setUp() { parent::setUp(); $this->choiceList = new SimpleChoiceList(array('' => 'Empty', 0 => 'A', 1 => 'B')); } protected function tearDown() { parent::tearDown(); $listener = null; } public function testFixRadio() { $data = '1'; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $listener = new FixRadioInputListener($this->choiceList, true); $listener->preSubmit($event); // Indices in SimpleChoiceList are zero-based generated integers $this->assertEquals(array(2 => '1'), $event->getData()); } public function testFixZero() { $data = '0'; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $listener = new FixRadioInputListener($this->choiceList, true); $listener->preSubmit($event); // Indices in SimpleChoiceList are zero-based generated integers $this->assertEquals(array(1 => '0'), $event->getData()); } public function testFixEmptyString() { $data = ''; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $listener = new FixRadioInputListener($this->choiceList, true); $listener->preSubmit($event); // Indices in SimpleChoiceList are zero-based generated integers $this->assertEquals(array(0 => ''), $event->getData()); } public function testConvertEmptyStringToPlaceholderIfNotFound() { $list = new SimpleChoiceList(array(0 => 'A', 1 => 'B')); $data = ''; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $listener = new FixRadioInputListener($list, true); $listener->preSubmit($event); $this->assertEquals(array('placeholder' => ''), $event->getData()); } public function testDontConvertEmptyStringToPlaceholderIfNoPlaceholderUsed() { $list = new SimpleChoiceList(array(0 => 'A', 1 => 'B')); $data = ''; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $listener = new FixRadioInputListener($list, false); $listener->preSubmit($event); $this->assertEquals(array(), $event->getData()); } } Symfony/Component/Form/Tests/Extension/Core/EventListener/TrimListenerTest.php000064400000004463152374770060023626 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Core\EventListener\TrimListener; class TrimListenerTest extends \PHPUnit_Framework_TestCase { public function testTrim() { $data = " Foo! "; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $filter = new TrimListener(); $filter->preSubmit($event); $this->assertEquals('Foo!', $event->getData()); } public function testTrimSkipNonStrings() { $data = 1234; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $filter = new TrimListener(); $filter->preSubmit($event); $this->assertSame(1234, $event->getData()); } /** * @dataProvider codePointProvider */ public function testTrimUtf8($chars) { if (!function_exists('mb_check_encoding')) { $this->markTestSkipped('The "mb_check_encoding" function is not available'); } $data = mb_convert_encoding(pack('H*', implode('', $chars)), 'UTF-8', 'UCS-2BE'); $data = $data."ab\ncd".$data; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $filter = new TrimListener(); $filter->preSubmit($event); $this->assertSame("ab\ncd", $event->getData(), 'TrimListener should trim character(s): '.implode(', ', $chars)); } public function codePointProvider() { return array( 'General category: Separator' => array(array('0020', '00A0', '1680', '180E', '2000', '2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '200A', '2028', '2029', '202F', '205F', '3000')), 'General category: Other, control' => array(array('0009', '000A', '000B', '000C', '000D', '0085')), //'General category: Other, format. ZERO WIDTH SPACE' => array(array('200B')), ); } } Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php000064400000022350152374770060024773 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Doctrine\Common\Collections\ArrayCollection; use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormEvent; class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase { private $dispatcher; private $factory; private $form; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->form = $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); } protected function tearDown() { $this->dispatcher = null; $this->factory = null; $this->form = null; } protected function getBuilder($name = 'name') { return new FormBuilder($name, null, $this->dispatcher, $this->factory); } protected function getForm($name = 'name') { return $this->getBuilder($name)->getForm(); } /** * @return \PHPUnit_Framework_MockObject_MockObject */ private function getDataMapper() { return $this->getMock('Symfony\Component\Form\DataMapperInterface'); } protected function getMockForm() { return $this->getMock('Symfony\Component\Form\Test\FormInterface'); } public function testPreSetDataResizesForm() { $this->form->add($this->getForm('0')); $this->form->add($this->getForm('1')); $this->factory->expects($this->at(0)) ->method('createNamed') ->with(1, 'text', null, array('property_path' => '[1]', 'max_length' => 10, 'auto_initialize' => false)) ->will($this->returnValue($this->getForm('1'))); $this->factory->expects($this->at(1)) ->method('createNamed') ->with(2, 'text', null, array('property_path' => '[2]', 'max_length' => 10, 'auto_initialize' => false)) ->will($this->returnValue($this->getForm('2'))); $data = array(1 => 'string', 2 => 'string'); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array('max_length' => '10'), false, false); $listener->preSetData($event); $this->assertFalse($this->form->has('0')); $this->assertTrue($this->form->has('1')); $this->assertTrue($this->form->has('2')); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testPreSetDataRequiresArrayOrTraversable() { $data = 'no array or traversable'; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->preSetData($event); } public function testPreSetDataDealsWithNullData() { $this->factory->expects($this->never())->method('createNamed'); $data = null; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->preSetData($event); } public function testPreSubmitResizesUpIfAllowAdd() { $this->form->add($this->getForm('0')); $this->factory->expects($this->once()) ->method('createNamed') ->with(1, 'text', null, array('property_path' => '[1]', 'max_length' => 10, 'auto_initialize' => false)) ->will($this->returnValue($this->getForm('1'))); $data = array(0 => 'string', 1 => 'string'); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array('max_length' => 10), true, false); $listener->preSubmit($event); $this->assertTrue($this->form->has('0')); $this->assertTrue($this->form->has('1')); } public function testPreSubmitResizesDownIfAllowDelete() { $this->form->add($this->getForm('0')); $this->form->add($this->getForm('1')); $data = array(0 => 'string'); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->preSubmit($event); $this->assertTrue($this->form->has('0')); $this->assertFalse($this->form->has('1')); } // fix for https://github.com/symfony/symfony/pull/493 public function testPreSubmitRemovesZeroKeys() { $this->form->add($this->getForm('0')); $data = array(); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->preSubmit($event); $this->assertFalse($this->form->has('0')); } public function testPreSubmitDoesNothingIfNotAllowAddNorAllowDelete() { $this->form->add($this->getForm('0')); $this->form->add($this->getForm('1')); $data = array(0 => 'string', 2 => 'string'); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->preSubmit($event); $this->assertTrue($this->form->has('0')); $this->assertTrue($this->form->has('1')); $this->assertFalse($this->form->has('2')); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testPreSubmitRequiresArrayOrTraversable() { $data = 'no array or traversable'; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->preSubmit($event); } public function testPreSubmitDealsWithNullData() { $this->form->add($this->getForm('1')); $data = null; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->preSubmit($event); $this->assertFalse($this->form->has('1')); } // fixes https://github.com/symfony/symfony/pull/40 public function testPreSubmitDealsWithEmptyData() { $this->form->add($this->getForm('1')); $data = ''; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->preSubmit($event); $this->assertFalse($this->form->has('1')); } public function testOnSubmitNormDataRemovesEntriesMissingInTheFormIfAllowDelete() { $this->form->add($this->getForm('1')); $data = array(0 => 'first', 1 => 'second', 2 => 'third'); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->onSubmit($event); $this->assertEquals(array(1 => 'second'), $event->getData()); } public function testOnSubmitNormDataDoesNothingIfNotAllowDelete() { $this->form->add($this->getForm('1')); $data = array(0 => 'first', 1 => 'second', 2 => 'third'); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->onSubmit($event); $this->assertEquals($data, $event->getData()); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testOnSubmitNormDataRequiresArrayOrTraversable() { $data = 'no array or traversable'; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->onSubmit($event); } public function testOnSubmitNormDataDealsWithNullData() { $this->form->add($this->getForm('1')); $data = null; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->onSubmit($event); $this->assertEquals(array(), $event->getData()); } public function testOnSubmitDealsWithObjectBackedIteratorAggregate() { $this->form->add($this->getForm('1')); $data = new \ArrayObject(array(0 => 'first', 1 => 'second', 2 => 'third')); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->onSubmit($event); $this->assertArrayNotHasKey(0, $event->getData()); $this->assertArrayNotHasKey(2, $event->getData()); } public function testOnSubmitDealsWithArrayBackedIteratorAggregate() { $this->form->add($this->getForm('1')); $data = new ArrayCollection(array(0 => 'first', 1 => 'second', 2 => 'third')); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->onSubmit($event); $this->assertArrayNotHasKey(0, $event->getData()); $this->assertArrayNotHasKey(2, $event->getData()); } } Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerCustomArrayObjectTest.php000064400000001436152374770060031225 0ustar00Symfony * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Symfony\Component\Form\Tests\Fixtures\CustomArrayObject; use Symfony\Component\Form\FormBuilder; class MergeCollectionListenerCustomArrayObjectTest extends MergeCollectionListenerTest { protected function getData(array $data) { return new CustomArrayObject($data); } protected function getBuilder($name = 'name') { return new FormBuilder($name, 'Symfony\Component\Form\Tests\Fixtures\CustomArrayObject', $this->dispatcher, $this->factory); } } Symfony/Component/Form/Tests/Extension/Core/EventListener/Fixtures/randomhash000064400000000043152374770060023502 0ustar00GIF87a€ÿÿÿÿÿÿ,D;Symfony/Component/Form/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php000064400000003147152374770060025644 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener; class FixUrlProtocolListenerTest extends \PHPUnit_Framework_TestCase { public function testFixHttpUrl() { $data = "www.symfony.com"; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); $filter->onSubmit($event); $this->assertEquals('http://www.symfony.com', $event->getData()); } public function testSkipKnownUrl() { $data = "http://www.symfony.com"; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); $filter->onSubmit($event); $this->assertEquals('http://www.symfony.com', $event->getData()); } public function testSkipOtherProtocol() { $data = "ftp://www.symfony.com"; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); $filter->onSubmit($event); $this->assertEquals('ftp://www.symfony.com', $event->getData()); } } Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayTest.php000064400000001211152374770060026751 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Symfony\Component\Form\FormBuilder; class MergeCollectionListenerArrayTest extends MergeCollectionListenerTest { protected function getData(array $data) { return $data; } protected function getBuilder($name = 'name') { return new FormBuilder($name, null, $this->dispatcher, $this->factory); } } Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php000064400000017033152374770060025763 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener; abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase { protected $dispatcher; protected $factory; protected $form; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->form = $this->getForm('axes'); } protected function tearDown() { $this->dispatcher = null; $this->factory = null; $this->form = null; } abstract protected function getBuilder($name = 'name'); protected function getForm($name = 'name', $propertyPath = null) { $propertyPath = $propertyPath ?: $name; return $this->getBuilder($name)->setAttribute('property_path', $propertyPath)->getForm(); } protected function getMockForm() { return $this->getMock('Symfony\Component\Form\Test\FormInterface'); } public function getBooleanMatrix1() { return array( array(true), array(false), ); } public function getBooleanMatrix2() { return array( array(true, true), array(true, false), array(false, true), array(false, false), ); } abstract protected function getData(array $data); /** * @dataProvider getBooleanMatrix1 */ public function testAddExtraEntriesIfAllowAdd($allowDelete) { $originalData = $this->getData(array(1 => 'second')); $newData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third')); $listener = new MergeCollectionListener(true, $allowDelete); $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); $listener->onSubmit($event); // The original object was modified if (is_object($originalData)) { $this->assertSame($originalData, $event->getData()); } // The original object matches the new object $this->assertEquals($newData, $event->getData()); } /** * @dataProvider getBooleanMatrix1 */ public function testAddExtraEntriesIfAllowAddDontOverwriteExistingIndices($allowDelete) { $originalData = $this->getData(array(1 => 'first')); $newData = $this->getData(array(0 => 'first', 1 => 'second')); $listener = new MergeCollectionListener(true, $allowDelete); $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); $listener->onSubmit($event); // The original object was modified if (is_object($originalData)) { $this->assertSame($originalData, $event->getData()); } // The original object matches the new object $this->assertEquals($this->getData(array(1 => 'first', 2 => 'second')), $event->getData()); } /** * @dataProvider getBooleanMatrix1 */ public function testDoNothingIfNotAllowAdd($allowDelete) { $originalDataArray = array(1 => 'second'); $originalData = $this->getData($originalDataArray); $newData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third')); $listener = new MergeCollectionListener(false, $allowDelete); $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); $listener->onSubmit($event); // We still have the original object if (is_object($originalData)) { $this->assertSame($originalData, $event->getData()); } // Nothing was removed $this->assertEquals($this->getData($originalDataArray), $event->getData()); } /** * @dataProvider getBooleanMatrix1 */ public function testRemoveMissingEntriesIfAllowDelete($allowAdd) { $originalData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third')); $newData = $this->getData(array(1 => 'second')); $listener = new MergeCollectionListener($allowAdd, true); $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); $listener->onSubmit($event); // The original object was modified if (is_object($originalData)) { $this->assertSame($originalData, $event->getData()); } // The original object matches the new object $this->assertEquals($newData, $event->getData()); } /** * @dataProvider getBooleanMatrix1 */ public function testDoNothingIfNotAllowDelete($allowAdd) { $originalDataArray = array(0 => 'first', 1 => 'second', 2 => 'third'); $originalData = $this->getData($originalDataArray); $newData = $this->getData(array(1 => 'second')); $listener = new MergeCollectionListener($allowAdd, false); $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); $listener->onSubmit($event); // We still have the original object if (is_object($originalData)) { $this->assertSame($originalData, $event->getData()); } // Nothing was removed $this->assertEquals($this->getData($originalDataArray), $event->getData()); } /** * @dataProvider getBooleanMatrix2 * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testRequireArrayOrTraversable($allowAdd, $allowDelete) { $newData = 'no array or traversable'; $event = new FormEvent($this->form, $newData); $listener = new MergeCollectionListener($allowAdd, $allowDelete); $listener->onSubmit($event); } public function testDealWithNullData() { $originalData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third')); $newData = null; $listener = new MergeCollectionListener(false, false); $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); $listener->onSubmit($event); $this->assertSame($originalData, $event->getData()); } /** * @dataProvider getBooleanMatrix1 */ public function testDealWithNullOriginalDataIfAllowAdd($allowDelete) { $originalData = null; $newData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third')); $listener = new MergeCollectionListener(true, $allowDelete); $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); $listener->onSubmit($event); $this->assertSame($newData, $event->getData()); } /** * @dataProvider getBooleanMatrix1 */ public function testDontDealWithNullOriginalDataIfNotAllowAdd($allowDelete) { $originalData = null; $newData = $this->getData(array(0 => 'first', 1 => 'second', 2 => 'third')); $listener = new MergeCollectionListener(false, $allowDelete); $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); $listener->onSubmit($event); $this->assertNull($event->getData()); } } Symfony/Component/Form/Tests/Extension/Core/EventListener/MergeCollectionListenerArrayObjectTest.php000064400000001253152374770060030106 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Symfony\Component\Form\FormBuilder; class MergeCollectionListenerArrayObjectTest extends MergeCollectionListenerTest { protected function getData(array $data) { return new \ArrayObject($data); } protected function getBuilder($name = 'name') { return new FormBuilder($name, '\ArrayObject', $this->dispatcher, $this->factory); } } Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php000064400000061107152374770060024531 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\Constraints; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\Extension\Validator\Constraints\FormValidator; use Symfony\Component\Form\SubmitButtonBuilder; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\NotBlank; /** * @author Bernhard Schussek */ class FormValidatorTest extends \PHPUnit_Framework_TestCase { /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dispatcher; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $factory; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $serverParams; /** * @var FormValidator */ private $validator; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->serverParams = $this->getMock( 'Symfony\Component\Form\Extension\Validator\Util\ServerParams', array('getNormalizedIniPostMaxSize', 'getContentLength') ); $this->validator = new FormValidator($this->serverParams); } public function testValidate() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => array('group1', 'group2')); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); $context->expects($this->at(0)) ->method('validate') ->with($object, 'data', 'group1', true); $context->expects($this->at(1)) ->method('validate') ->with($object, 'data', 'group2', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testValidateConstraints() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = new NotNull(array('groups' => array('group1', 'group2'))); $constraint2 = new NotBlank(array('groups' => 'group2')); $options = array( 'validation_groups' => array('group1', 'group2'), 'constraints' => array($constraint1, $constraint2), ); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); // First default constraints $context->expects($this->at(0)) ->method('validate') ->with($object, 'data', 'group1', true); $context->expects($this->at(1)) ->method('validate') ->with($object, 'data', 'group2', true); // Then custom constraints $context->expects($this->at(2)) ->method('validateValue') ->with($object, $constraint1, 'data', 'group1'); $context->expects($this->at(3)) ->method('validateValue') ->with($object, $constraint2, 'data', 'group2'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testDontValidateIfParentWithoutCascadeValidation() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parent = $this->getBuilder('parent', null, array('cascade_validation' => false)) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $options = array('validation_groups' => array('group1', 'group2')); $form = $this->getBuilder('name', '\stdClass', $options)->getForm(); $parent->add($form); $form->setData($object); $context->expects($this->never()) ->method('validate'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testValidateConstraintsEvenIfNoCascadeValidation() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = new NotNull(array('groups' => array('group1', 'group2'))); $constraint2 = new NotBlank(array('groups' => 'group2')); $parent = $this->getBuilder('parent', null, array('cascade_validation' => false)) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $options = array( 'validation_groups' => array('group1', 'group2'), 'constraints' => array($constraint1, $constraint2), ); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); $parent->add($form); $context->expects($this->at(0)) ->method('validateValue') ->with($object, $constraint1, 'data', 'group1'); $context->expects($this->at(1)) ->method('validateValue') ->with($object, $constraint2, 'data', 'group2'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testDontValidateIfNoValidationGroups() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass', array( 'validation_groups' => array(), )) ->setData($object) ->getForm(); $form->setData($object); $context->expects($this->never()) ->method('validate'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testDontValidateConstraintsIfNoValidationGroups() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = $this->getMock('Symfony\Component\Validator\Constraint'); $constraint2 = $this->getMock('Symfony\Component\Validator\Constraint'); $options = array( 'validation_groups' => array(), 'constraints' => array($constraint1, $constraint2), ); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); // Launch transformer $form->submit(array()); $context->expects($this->never()) ->method('validate'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testDontValidateIfNotSynchronized() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass', array( 'invalid_message' => 'invalid_message_key', // Invalid message parameters must be supported, because the // invalid message can be a translation key // see https://github.com/symfony/symfony/issues/5144 'invalid_message_parameters' => array('{{ foo }}' => 'bar'), )) ->setData($object) ->addViewTransformer(new CallbackTransformer( function ($data) { return $data; }, function () { throw new TransformationFailedException(); } )) ->getForm(); // Launch transformer $form->submit('foo'); $context->expects($this->never()) ->method('validate'); $context->expects($this->once()) ->method('addViolation') ->with( 'invalid_message_key', array('{{ value }}' => 'foo', '{{ foo }}' => 'bar'), 'foo' ); $context->expects($this->never()) ->method('addViolationAt'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testAddInvalidErrorEvenIfNoValidationGroups() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass', array( 'invalid_message' => 'invalid_message_key', // Invalid message parameters must be supported, because the // invalid message can be a translation key // see https://github.com/symfony/symfony/issues/5144 'invalid_message_parameters' => array('{{ foo }}' => 'bar'), 'validation_groups' => array(), )) ->setData($object) ->addViewTransformer(new CallbackTransformer( function ($data) { return $data; }, function () { throw new TransformationFailedException(); } )) ->getForm(); // Launch transformer $form->submit('foo'); $context->expects($this->never()) ->method('validate'); $context->expects($this->once()) ->method('addViolation') ->with( 'invalid_message_key', array('{{ value }}' => 'foo', '{{ foo }}' => 'bar'), 'foo' ); $context->expects($this->never()) ->method('addViolationAt'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testDontValidateConstraintsIfNotSynchronized() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = $this->getMock('Symfony\Component\Validator\Constraint'); $constraint2 = $this->getMock('Symfony\Component\Validator\Constraint'); $options = array( 'validation_groups' => array('group1', 'group2'), 'constraints' => array($constraint1, $constraint2), ); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->addViewTransformer(new CallbackTransformer( function ($data) { return $data; }, function () { throw new TransformationFailedException(); } )) ->getForm(); // Launch transformer $form->submit(array()); $context->expects($this->never()) ->method('validate'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } // https://github.com/symfony/symfony/issues/4359 public function testDontMarkInvalidIfAnyChildIsNotSynchronized() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $failingTransformer = new CallbackTransformer( function ($data) { return $data; }, function () { throw new TransformationFailedException(); } ); $form = $this->getBuilder('name', '\stdClass') ->setData($object) ->addViewTransformer($failingTransformer) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->add( $this->getBuilder('child') ->addViewTransformer($failingTransformer) ) ->getForm(); // Launch transformer $form->submit(array('child' => 'foo')); $context->expects($this->never()) ->method('addViolation'); $context->expects($this->never()) ->method('addViolationAt'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testHandleCallbackValidationGroups() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => array($this, 'getValidationGroups')); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); $context->expects($this->at(0)) ->method('validate') ->with($object, 'data', 'group1', true); $context->expects($this->at(1)) ->method('validate') ->with($object, 'data', 'group2', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testDontExecuteFunctionNames() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => 'header'); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); $context->expects($this->once()) ->method('validate') ->with($object, 'data', 'header', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testHandleClosureValidationGroups() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => function (FormInterface $form) { return array('group1', 'group2'); }); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); $context->expects($this->at(0)) ->method('validate') ->with($object, 'data', 'group1', true); $context->expects($this->at(1)) ->method('validate') ->with($object, 'data', 'group2', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testUseValidationGroupOfClickedButton() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parent = $this->getBuilder('parent', null, array('cascade_validation' => true)) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $form = $this->getForm('name', '\stdClass', array( 'validation_groups' => 'form_group', )); $parent->add($form); $parent->add($this->getSubmitButton('submit', array( 'validation_groups' => 'button_group', ))); $parent->submit(array('name' => $object, 'submit' => '')); $context->expects($this->once()) ->method('validate') ->with($object, 'data', 'button_group', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testDontUseValidationGroupOfUnclickedButton() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parent = $this->getBuilder('parent', null, array('cascade_validation' => true)) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $form = $this->getForm('name', '\stdClass', array( 'validation_groups' => 'form_group', )); $parent->add($form); $parent->add($this->getSubmitButton('submit', array( 'validation_groups' => 'button_group', ))); $form->setData($object); $context->expects($this->once()) ->method('validate') ->with($object, 'data', 'form_group', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testUseInheritedValidationGroup() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parentOptions = array( 'validation_groups' => 'group', 'cascade_validation' => true, ); $parent = $this->getBuilder('parent', null, $parentOptions) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $form = $this->getBuilder('name', '\stdClass')->getForm(); $parent->add($form); $form->setData($object); $context->expects($this->once()) ->method('validate') ->with($object, 'data', 'group', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testUseInheritedCallbackValidationGroup() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parentOptions = array( 'validation_groups' => array($this, 'getValidationGroups'), 'cascade_validation' => true, ); $parent = $this->getBuilder('parent', null, $parentOptions) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $form = $this->getBuilder('name', '\stdClass')->getForm(); $parent->add($form); $form->setData($object); $context->expects($this->at(0)) ->method('validate') ->with($object, 'data', 'group1', true); $context->expects($this->at(1)) ->method('validate') ->with($object, 'data', 'group2', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testUseInheritedClosureValidationGroup() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parentOptions = array( 'validation_groups' => function (FormInterface $form) { return array('group1', 'group2'); }, 'cascade_validation' => true, ); $parent = $this->getBuilder('parent', null, $parentOptions) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $form = $this->getBuilder('name', '\stdClass')->getForm(); $parent->add($form); $form->setData($object); $context->expects($this->at(0)) ->method('validate') ->with($object, 'data', 'group1', true); $context->expects($this->at(1)) ->method('validate') ->with($object, 'data', 'group2', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testAppendPropertyPath() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass') ->setData($object) ->getForm(); $context->expects($this->once()) ->method('validate') ->with($object, 'data', 'Default', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testDontWalkScalars() { $context = $this->getMockExecutionContext(); $form = $this->getBuilder() ->setData('scalar') ->getForm(); $context->expects($this->never()) ->method('validate'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function testViolationIfExtraData() { $context = $this->getMockExecutionContext(); $form = $this->getBuilder('parent', null, array('extra_fields_message' => 'Extra!')) ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->add($this->getBuilder('child')) ->getForm(); $form->submit(array('foo' => 'bar')); $context->expects($this->once()) ->method('addViolation') ->with( 'Extra!', array('{{ extra_fields }}' => 'foo'), array('foo' => 'bar') ); $context->expects($this->never()) ->method('addViolationAt'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } /** * @dataProvider getPostMaxSizeFixtures */ public function testPostMaxSizeViolation($contentLength, $iniMax, $nbViolation, array $params = array()) { $this->serverParams->expects($this->once()) ->method('getContentLength') ->will($this->returnValue($contentLength)); $this->serverParams->expects($this->any()) ->method('getNormalizedIniPostMaxSize') ->will($this->returnValue($iniMax)); $context = $this->getMockExecutionContext(); $options = array('post_max_size_message' => 'Max {{ max }}!'); $form = $this->getBuilder('name', null, $options)->getForm(); for ($i = 0; $i < $nbViolation; ++$i) { if (0 === $i && count($params) > 0) { $context->expects($this->at($i)) ->method('addViolation') ->with($options['post_max_size_message'], $params); } else { $context->expects($this->at($i)) ->method('addViolation'); } } $context->expects($this->never()) ->method('addViolationAt'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } public function getPostMaxSizeFixtures() { return array( array(pow(1024, 3) + 1, '1G', 1, array('{{ max }}' => '1G')), array(pow(1024, 3), '1G', 0), array(pow(1024, 2) + 1, '1M', 1, array('{{ max }}' => '1M')), array(pow(1024, 2), '1M', 0), array(1024 + 1, '1K', 1, array('{{ max }}' => '1K')), array(1024, '1K', 0), array(null, '1K', 0), array(1024, '', 0), array(1024, 0, 0), ); } public function testNoViolationIfNotRoot() { $this->serverParams->expects($this->once()) ->method('getContentLength') ->will($this->returnValue(1025)); $this->serverParams->expects($this->never()) ->method('getNormalizedIniPostMaxSize'); $context = $this->getMockExecutionContext(); $parent = $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) ->getForm(); $form = $this->getForm(); $parent->add($form); $context->expects($this->never()) ->method('addViolation'); $context->expects($this->never()) ->method('addViolationAt'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); } /** * Access has to be public, as this method is called via callback array * in {@link testValidateFormDataCanHandleCallbackValidationGroups()} * and {@link testValidateFormDataUsesInheritedCallbackValidationGroup()} */ public function getValidationGroups(FormInterface $form) { return array('group1', 'group2'); } private function getMockExecutionContext() { return $this->getMock('Symfony\Component\Validator\ExecutionContextInterface'); } /** * @param string $name * @param string $dataClass * @param array $options * * @return FormBuilder */ private function getBuilder($name = 'name', $dataClass = null, array $options = array()) { $options = array_replace(array( 'constraints' => array(), 'invalid_message_parameters' => array(), ), $options); return new FormBuilder($name, $dataClass, $this->dispatcher, $this->factory, $options); } private function getForm($name = 'name', $dataClass = null, array $options = array()) { return $this->getBuilder($name, $dataClass, $options)->getForm(); } private function getSubmitButton($name = 'name', array $options = array()) { $builder = new SubmitButtonBuilder($name, $options); return $builder->getForm(); } /** * @return \PHPUnit_Framework_MockObject_MockObject */ private function getDataMapper() { return $this->getMock('Symfony\Component\Form\DataMapperInterface'); } } Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php000064400000002431152374770060026706 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\Constraints; use Symfony\Component\Form\Extension\Validator\ValidatorExtension; use Symfony\Component\Form\Test\FormPerformanceTestCase; use Symfony\Component\Validator\Validation; /** * @author Bernhard Schussek */ class FormValidatorPerformanceTest extends FormPerformanceTestCase { protected function getExtensions() { return array( new ValidatorExtension(Validation::createValidator()), ); } /** * findClickedButton() used to have an exponential number of calls * * @group benchmark */ public function testValidationPerformance() { $this->setMaxRunningTime(1); $builder = $this->factory->createBuilder('form'); for ($i = 0; $i < 40; ++$i) { $builder->add($i, 'form'); $builder->get($i) ->add('a') ->add('b') ->add('c'); } $form = $builder->getForm(); $form->submit(null); } } Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php000064400000002211152374770060025671 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; use Symfony\Component\Validator\ConstraintViolationList; class FormTypeValidatorExtensionTest extends BaseValidatorExtensionTest { public function testSubmitValidatesData() { $builder = $this->factory->createBuilder( 'form', null, array( 'validation_groups' => 'group', ) ); $builder->add('firstName', 'form'); $form = $builder->getForm(); $this->validator->expects($this->once()) ->method('validate') ->with($this->equalTo($form)) ->will($this->returnValue(new ConstraintViolationList())); // specific data is irrelevant $form->submit(array()); } protected function createForm(array $options = array()) { return $this->factory->create('form', null, $options); } } Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php000064400000002665152374770060022113 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; use Symfony\Component\Form\Test\TypeTestCase as BaseTypeTestCase; use Symfony\Component\Form\Extension\Validator\ValidatorExtension; abstract class TypeTestCase extends BaseTypeTestCase { protected $validator; protected function setUp() { $this->validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); $metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); $this->validator->expects($this->once())->method('getMetadataFactory')->will($this->returnValue($metadataFactory)); $metadata = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); $metadataFactory->expects($this->once())->method('getMetadataFor')->will($this->returnValue($metadata)); parent::setUp(); } protected function tearDown() { $this->validator = null; parent::tearDown(); } protected function getExtensions() { return array_merge(parent::getExtensions(), array( new ValidatorExtension($this->validator), )); } } Symfony/Component/Form/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php000064400000004170152374770060025004 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; use Symfony\Component\Form\Test\FormInterface; /** * @author Bernhard Schussek */ abstract class BaseValidatorExtensionTest extends TypeTestCase { public function testValidationGroupNullByDefault() { $form = $this->createForm(); $this->assertNull($form->getConfig()->getOption('validation_groups')); } public function testValidationGroupsTransformedToArray() { $form = $this->createForm(array( 'validation_groups' => 'group', )); $this->assertEquals(array('group'), $form->getConfig()->getOption('validation_groups')); } public function testValidationGroupsCanBeSetToArray() { $form = $this->createForm(array( 'validation_groups' => array('group1', 'group2'), )); $this->assertEquals(array('group1', 'group2'), $form->getConfig()->getOption('validation_groups')); } public function testValidationGroupsCanBeSetToFalse() { $form = $this->createForm(array( 'validation_groups' => false, )); $this->assertEquals(array(), $form->getConfig()->getOption('validation_groups')); } public function testValidationGroupsCanBeSetToCallback() { $form = $this->createForm(array( 'validation_groups' => array($this, 'testValidationGroupsCanBeSetToCallback'), )); $this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups'))); } public function testValidationGroupsCanBeSetToClosure() { $form = $this->createForm(array( 'validation_groups' => function (FormInterface $form) { return null; }, )); $this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups'))); } abstract protected function createForm(array $options = array()); } Symfony/Component/Form/Tests/Extension/Validator/Type/SubmitTypeValidatorExtensionTest.php000064400000001007152374770060026233 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; class SubmitTypeValidatorExtensionTest extends BaseValidatorExtensionTest { protected function createForm(array $options = array()) { return $this->factory->create('submit', null, $options); } } Symfony/Component/Form/Tests/Extension/Validator/Util/ServerParamsTest.php000064400000002665152374770060023004 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\Util; class ServerParamsTest extends \PHPUnit_Framework_TestCase { /** @dataProvider getGetPostMaxSizeTestData */ public function testGetPostMaxSize($size, $bytes) { $serverParams = $this->getMock('Symfony\Component\Form\Extension\Validator\Util\ServerParams', array('getNormalizedIniPostMaxSize')); $serverParams ->expects($this->any()) ->method('getNormalizedIniPostMaxSize') ->will($this->returnValue(strtoupper($size))); $this->assertEquals($bytes, $serverParams->getPostMaxSize()); } public function getGetPostMaxSizeTestData() { return array( array('2k', 2048), array('2 k', 2048), array('8m', 8 * 1024 * 1024), array('+2 k', 2048), array('+2???k', 2048), array('0x10', 16), array('0xf', 15), array('010', 8), array('+0x10 k', 16 * 1024), array('1g', 1024 * 1024 * 1024), array('-1', -1), array('0', 0), array('2mk', 2048), // the unit must be the last char, so in this case 'k', not 'm' ); } } Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.php000064400000004621152374770060023574 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator; use Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser; use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\Type; /** * @author franek */ class ValidatorTypeGuesserTest extends \PHPUnit_Framework_TestCase { private $typeGuesser; public function setUp() { if (!class_exists('Symfony\Component\Validator\Constraint')) { $this->markTestSkipped('The "Validator" component is not available'); } $metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); $this->typeGuesser = new ValidatorTypeGuesser($metadataFactory); } public function testGuessMaxLengthForConstraintWithMaxValue() { $constraint = new Length(array('max' => '2')); $result = $this->typeGuesser->guessMaxLengthForConstraint($constraint); $this->assertInstanceOf('Symfony\Component\Form\Guess\ValueGuess', $result); $this->assertEquals(2, $result->getValue()); $this->assertEquals(Guess::HIGH_CONFIDENCE, $result->getConfidence()); } public function testGuessMaxLengthForConstraintWithMinValue() { $constraint = new Length(array('min' => '2')); $result = $this->typeGuesser->guessMaxLengthForConstraint($constraint); $this->assertNull($result); } /** * @dataProvider dataProviderTestGuessMaxLengthForConstraintWithType */ public function testGuessMaxLengthForConstraintWithType($type) { $constraint = new Type($type); $result = $this->typeGuesser->guessMaxLengthForConstraint($constraint); $this->assertInstanceOf('Symfony\Component\Form\Guess\ValueGuess', $result); $this->assertEquals(null, $result->getValue()); $this->assertEquals(Guess::MEDIUM_CONFIDENCE, $result->getConfidence()); } public static function dataProviderTestGuessMaxLengthForConstraintWithType() { return array ( array('double'), array('float'), array('numeric'), array('real') ); } } Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.php000064400000011741152374770060026037 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\EventListener; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Validator\ConstraintViolation; use Symfony\Component\Validator\ConstraintViolationList; class ValidationListenerTest extends \PHPUnit_Framework_TestCase { /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dispatcher; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $factory; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $validator; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $violationMapper; /** * @var ValidationListener */ private $listener; private $message; private $messageTemplate; private $params; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); $this->violationMapper = $this->getMock('Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapperInterface'); $this->listener = new ValidationListener($this->validator, $this->violationMapper); $this->message = 'Message'; $this->messageTemplate = 'Message template'; $this->params = array('foo' => 'bar'); } private function getConstraintViolation($code = null) { return new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, 'prop.path', null, null, $code); } private function getBuilder($name = 'name', $propertyPath = null, $dataClass = null) { $builder = new FormBuilder($name, $dataClass, $this->dispatcher, $this->factory); $builder->setPropertyPath(new PropertyPath($propertyPath ?: $name)); $builder->setAttribute('error_mapping', array()); $builder->setErrorBubbling(false); $builder->setMapped(true); return $builder; } private function getForm($name = 'name', $propertyPath = null, $dataClass = null) { return $this->getBuilder($name, $propertyPath, $dataClass)->getForm(); } private function getMockForm() { return $this->getMock('Symfony\Component\Form\Test\FormInterface'); } // More specific mapping tests can be found in ViolationMapperTest public function testMapViolation() { $violation = $this->getConstraintViolation(); $form = $this->getForm('street'); $this->validator->expects($this->once()) ->method('validate') ->will($this->returnValue(array($violation))); $this->violationMapper->expects($this->once()) ->method('mapViolation') ->with($violation, $form, false); $this->listener->validateForm(new FormEvent($form, null)); } public function testMapViolationAllowsNonSyncIfInvalid() { $violation = $this->getConstraintViolation(Form::ERR_INVALID); $form = $this->getForm('street'); $this->validator->expects($this->once()) ->method('validate') ->will($this->returnValue(array($violation))); $this->violationMapper->expects($this->once()) ->method('mapViolation') // pass true now ->with($violation, $form, true); $this->listener->validateForm(new FormEvent($form, null)); } public function testValidateIgnoresNonRoot() { $form = $this->getMockForm(); $form->expects($this->once()) ->method('isRoot') ->will($this->returnValue(false)); $this->validator->expects($this->never()) ->method('validate'); $this->violationMapper->expects($this->never()) ->method('mapViolation'); $this->listener->validateForm(new FormEvent($form, null)); } public function testValidateWithEmptyViolationList() { $form = $this->getMockForm(); $form->expects($this->once()) ->method('isRoot') ->will($this->returnValue(true)); $this->validator ->expects($this->once()) ->method('validate') ->will($this->returnValue(new ConstraintViolationList())); $this->violationMapper ->expects($this->never()) ->method('mapViolation'); $this->listener->validateForm(new FormEvent($form, null)); } } Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php000064400000426241152374770060025677 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\ViolationMapper; use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Form; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\FormError; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Validator\ConstraintViolation; /** * @author Bernhard Schussek */ class ViolationMapperTest extends \PHPUnit_Framework_TestCase { const LEVEL_0 = 0; const LEVEL_1 = 1; const LEVEL_1B = 2; const LEVEL_2 = 3; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dispatcher; /** * @var ViolationMapper */ private $mapper; /** * @var string */ private $message; /** * @var string */ private $messageTemplate; /** * @var array */ private $params; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->mapper = new ViolationMapper(); $this->message = 'Message'; $this->messageTemplate = 'Message template'; $this->params = array('foo' => 'bar'); } protected function getForm($name = 'name', $propertyPath = null, $dataClass = null, $errorMapping = array(), $inheritData = false, $synchronized = true) { $config = new FormConfigBuilder($name, $dataClass, $this->dispatcher, array( 'error_mapping' => $errorMapping, )); $config->setMapped(true); $config->setInheritData($inheritData); $config->setPropertyPath($propertyPath); $config->setCompound(true); $config->setDataMapper($this->getDataMapper()); if (!$synchronized) { $config->addViewTransformer(new CallbackTransformer( function ($normData) { return $normData; }, function () { throw new TransformationFailedException(); } )); } return new Form($config); } /** * @return \PHPUnit_Framework_MockObject_MockObject */ private function getDataMapper() { return $this->getMock('Symfony\Component\Form\DataMapperInterface'); } /** * @param $propertyPath * * @return ConstraintViolation */ protected function getConstraintViolation($propertyPath) { return new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, $propertyPath, null); } /** * @return FormError */ protected function getFormError() { return new FormError($this->message, $this->messageTemplate, $this->params); } public function testMapToFormInheritingParentDataIfDataDoesNotMatch() { $violation = $this->getConstraintViolation('children[address].data.foo'); $parent = $this->getForm('parent'); $child = $this->getForm('address', 'address', null, array(), true); $grandChild = $this->getForm('street'); $parent->add($child); $child->add($grandChild); $this->mapper->mapViolation($violation, $parent); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $child->getErrors(), $child->getName().' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); } public function testFollowDotRules() { $violation = $this->getConstraintViolation('data.foo'); $parent = $this->getForm('parent', null, null, array( 'foo' => 'address', )); $child = $this->getForm('address', null, null, array( '.' => 'street', )); $grandChild = $this->getForm('street', null, null, array( '.' => 'name', )); $grandGrandChild = $this->getForm('name'); $parent->add($child); $child->add($grandChild); $grandChild->add($grandGrandChild); $this->mapper->mapViolation($violation, $parent); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $grandGrandChild->getErrors(), $grandGrandChild->getName().' should have an error, but has none'); } public function testAbortMappingIfNotSynchronized() { $violation = $this->getConstraintViolation('children[address].data.street'); $parent = $this->getForm('parent'); $child = $this->getForm('address', 'address', null, array(), false, false); // even though "street" is synchronized, it should not have any errors // due to its parent not being synchronized $grandChild = $this->getForm('street' , 'street'); $parent->add($child); $child->add($grandChild); // submit to invoke the transformer and mark the form unsynchronized $parent->submit(array()); $this->mapper->mapViolation($violation, $parent); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); } public function testAbortDotRuleMappingIfNotSynchronized() { $violation = $this->getConstraintViolation('data.address'); $parent = $this->getForm('parent'); $child = $this->getForm('address', 'address', null, array( '.' => 'street', ), false, false); // even though "street" is synchronized, it should not have any errors // due to its parent not being synchronized $grandChild = $this->getForm('street'); $parent->add($child); $child->add($grandChild); // submit to invoke the transformer and mark the form unsynchronized $parent->submit(array()); $this->mapper->mapViolation($violation, $parent); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); } public function provideDefaultTests() { // The mapping must be deterministic! If a child has the property path "[street]", // "data[street]" should be mapped, but "data.street" should not! return array( // mapping target, child name, its property path, grand child name, its property path, violation path array(self::LEVEL_0, 'address', 'address', 'street', 'street', ''), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street].prop'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.address.street'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.address.street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'data.address[street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'data.address[street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street]'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street].prop'), array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address].data'), array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address].data.street.prop'), array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address].data[street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'data.address.street'), array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'data.address.street.prop'), array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'data.address[street]'), array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'data.address[street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address].street'), array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address].street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address][street]'), array(self::LEVEL_0, 'address', 'address', 'street', '[street]', 'data[address][street].prop'), array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address].data'), array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address].data.street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address].data[street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address.street'), array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address.street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address[street]'), array(self::LEVEL_0, 'address', '[address]', 'street', 'street', 'data.address[street].prop'), array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'data[address].street'), array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'data[address].street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'data[address][street]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'data[address][street].prop'), array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address].data'), array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address].data.street.prop'), array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address].data[street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address.street'), array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address.street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address[street]'), array(self::LEVEL_0, 'address', '[address]', 'street', '[street]', 'data.address[street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'data[address].street'), array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'data[address].street.prop'), array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'data[address][street]'), array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'data[address][street].prop'), array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'children[address].data'), array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'children[address].data.street.prop'), array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'children[address].data[street].prop'), array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'data.person.address.street'), array(self::LEVEL_2, 'address', 'person.address', 'street', 'street', 'data.person.address.street.prop'), array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'data.person.address[street]'), array(self::LEVEL_1, 'address', 'person.address', 'street', 'street', 'data.person.address[street].prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address].street'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address].street.prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address][street]'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.person[address][street].prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address.street'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address.street.prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address[street]'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person].address[street].prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address].street'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address].street.prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address][street]'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data[person][address][street].prop'), array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'children[address].data'), array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'children[address].data.street.prop'), array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'children[address].data[street].prop'), array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'data.person.address.street'), array(self::LEVEL_1, 'address', 'person.address', 'street', '[street]', 'data.person.address.street.prop'), array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'data.person.address[street]'), array(self::LEVEL_2, 'address', 'person.address', 'street', '[street]', 'data.person.address[street].prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address].street'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address].street.prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address][street]'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data.person[address][street].prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address.street'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address.street.prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address[street]'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person].address[street].prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address].street'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address].street.prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address][street]'), array(self::LEVEL_0, 'address', 'person.address', 'street', '[street]', 'data[person][address][street].prop'), array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'children[address].data'), array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'children[address].data.street.prop'), array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'children[address].data[street].prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address.street'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address.street.prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address[street]'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data.person.address[street].prop'), array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'data.person[address].street'), array(self::LEVEL_2, 'address', 'person[address]', 'street', 'street', 'data.person[address].street.prop'), array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'data.person[address][street]'), array(self::LEVEL_1, 'address', 'person[address]', 'street', 'street', 'data.person[address][street].prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address.street'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address.street.prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address[street]'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person].address[street].prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address].street'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address].street.prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address][street]'), array(self::LEVEL_0, 'address', 'person[address]', 'street', 'street', 'data[person][address][street].prop'), array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'children[address].data'), array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'children[address].data.street.prop'), array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'children[address].data[street].prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address.street'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address.street.prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address[street]'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data.person.address[street].prop'), array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'data.person[address].street'), array(self::LEVEL_1, 'address', 'person[address]', 'street', '[street]', 'data.person[address].street.prop'), array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'data.person[address][street]'), array(self::LEVEL_2, 'address', 'person[address]', 'street', '[street]', 'data.person[address][street].prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address.street'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address.street.prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address[street]'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person].address[street].prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address].street'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address].street.prop'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address][street]'), array(self::LEVEL_0, 'address', 'person[address]', 'street', '[street]', 'data[person][address][street].prop'), array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'children[address].data'), array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'children[address].data.street.prop'), array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'children[address].data[street].prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address.street'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address.street.prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address[street]'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person.address[street].prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address].street'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address].street.prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address][street]'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data.person[address][street].prop'), array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'data[person].address.street'), array(self::LEVEL_2, 'address', '[person].address', 'street', 'street', 'data[person].address.street.prop'), array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'data[person].address[street]'), array(self::LEVEL_1, 'address', '[person].address', 'street', 'street', 'data[person].address[street].prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address].street'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address].street.prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address][street]'), array(self::LEVEL_0, 'address', '[person].address', 'street', 'street', 'data[person][address][street].prop'), array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'children[address].data'), array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'children[address].data.street.prop'), array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'children[address].data[street].prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address.street'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address.street.prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address[street]'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person.address[street].prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address].street'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address].street.prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address][street]'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data.person[address][street].prop'), array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'data[person].address.street'), array(self::LEVEL_1, 'address', '[person].address', 'street', '[street]', 'data[person].address.street.prop'), array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'data[person].address[street]'), array(self::LEVEL_2, 'address', '[person].address', 'street', '[street]', 'data[person].address[street].prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address].street'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address].street.prop'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address][street]'), array(self::LEVEL_0, 'address', '[person].address', 'street', '[street]', 'data[person][address][street].prop'), array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address]'), array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address].data'), array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'children[address].data.street.prop'), array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'children[address].data[street].prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address.street'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address.street.prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address[street]'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person.address[street].prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address].street'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address].street.prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address][street]'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data.person[address][street].prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address.street'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address.street.prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address[street]'), array(self::LEVEL_0, 'address', '[person][address]', 'street', 'street', 'data[person].address[street].prop'), array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'data[person][address].street'), array(self::LEVEL_2, 'address', '[person][address]', 'street', 'street', 'data[person][address].street.prop'), array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'data[person][address][street]'), array(self::LEVEL_1, 'address', '[person][address]', 'street', 'street', 'data[person][address][street].prop'), array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'children[address].data'), array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'children[address].data.street.prop'), array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'children[address].data[street].prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address.street'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address.street.prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address[street]'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person.address[street].prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address].street'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address].street.prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address][street]'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data.person[address][street].prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address.street'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address.street.prop'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address[street]'), array(self::LEVEL_0, 'address', '[person][address]', 'street', '[street]', 'data[person].address[street].prop'), array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'data[person][address].street'), array(self::LEVEL_1, 'address', '[person][address]', 'street', '[street]', 'data[person][address].street.prop'), array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'data[person][address][street]'), array(self::LEVEL_2, 'address', '[person][address]', 'street', '[street]', 'data[person][address][street].prop'), array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.office'), array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].data.office.street'), array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'children[address].data.office.street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.office[street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.office[street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office]'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office].street'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office].street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office][street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data[office][street].prop'), array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'data.address.office.street'), array(self::LEVEL_2, 'address', 'address', 'street', 'office.street', 'data.address.office.street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address.office[street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address.office[street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office].street'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office].street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office][street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address[office][street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office.street'), array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office.street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office[street]'), array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address].office[street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office].street'), array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office].street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office][street]'), array(self::LEVEL_0, 'address', 'address', 'street', 'office.street', 'data[address][office][street].prop'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data.office'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].data.office.street'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'children[address].data.office.street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data.office[street]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data.office[street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office].street'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office].street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office][street]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'children[address].data[office][street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office.street'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office.street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office[street]'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address.office[street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office].street'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office].street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office][street]'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office.street', 'data.address[office][street].prop'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'data[address].office.street'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office.street', 'data[address].office.street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address].office[street]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address].office[street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office].street'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office].street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office][street]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office.street', 'data[address][office][street].prop'), array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data.office'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data.office.street'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data.office.street.prop'), array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].data.office[street]'), array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'children[address].data.office[street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office]'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office].street'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office].street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office][street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'children[address].data[office][street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address.office.street'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address.office.street.prop'), array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'data.address.office[street]'), array(self::LEVEL_2, 'address', 'address', 'street', 'office[street]', 'data.address.office[street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office].street'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office].street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office][street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'office[street]', 'data.address[office][street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office.street'), array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office.street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office[street]'), array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address].office[street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office].street'), array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office].street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office][street]'), array(self::LEVEL_0, 'address', 'address', 'street', 'office[street]', 'data[address][office][street].prop'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office.street'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office.street.prop'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office[street]'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'children[address].data.office[street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office].street'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office].street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office][street]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'children[address].data[office][street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office.street'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office.street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office[street]'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address.office[street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office].street'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office].street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office][street]'), array(self::LEVEL_0, 'address', '[address]', 'street', 'office[street]', 'data.address[office][street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address].office.street'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address].office.street.prop'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'data[address].office[street]'), array(self::LEVEL_2, 'address', '[address]', 'street', 'office[street]', 'data[address].office[street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office].street'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office].street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office][street]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'office[street]', 'data[address][office][street].prop'), array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office.street'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office.street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office[street]'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data.office[street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data[office]'), array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].data[office].street'), array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'children[address].data[office].street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data[office][street]'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'children[address].data[office][street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office.street'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office.street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office[street]'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address.office[street].prop'), array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'data.address[office].street'), array(self::LEVEL_2, 'address', 'address', 'street', '[office].street', 'data.address[office].street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address[office][street]'), array(self::LEVEL_1, 'address', 'address', 'street', '[office].street', 'data.address[office][street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office.street'), array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office.street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office[street]'), array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address].office[street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office].street'), array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office].street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office][street]'), array(self::LEVEL_0, 'address', 'address', 'street', '[office].street', 'data[address][office][street].prop'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office.street'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office.street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office[street]'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data.office[street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data[office]'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].data[office].street'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'children[address].data[office].street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data[office][street]'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'children[address].data[office][street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office.street'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office.street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office[street]'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address.office[street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office].street'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office].street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office][street]'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office].street', 'data.address[office][street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office.street'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office.street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office[street]'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address].office[street].prop'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'data[address][office].street'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office].street', 'data[address][office].street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address][office][street]'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office].street', 'data[address][office][street].prop'), array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office.street'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office.street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office[street]'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data.office[street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data[office]'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data[office].street'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'children[address].data[office].street.prop'), array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].data[office][street]'), array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'children[address].data[office][street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office.street'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office.street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office[street]'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address.office[street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address[office].street'), array(self::LEVEL_1, 'address', 'address', 'street', '[office][street]', 'data.address[office].street.prop'), array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'data.address[office][street]'), array(self::LEVEL_2, 'address', 'address', 'street', '[office][street]', 'data.address[office][street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office.street'), array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office.street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office[street]'), array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address].office[street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office].street'), array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office].street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office][street]'), array(self::LEVEL_0, 'address', 'address', 'street', '[office][street]', 'data[address][office][street].prop'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office.street'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office.street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office[street]'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data.office[street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office]'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office].street'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office].street.prop'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office][street]'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'children[address].data[office][street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office.street'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office.street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office[street]'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address.office[street].prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office].street'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office].street.prop'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office][street]'), array(self::LEVEL_0, 'address', '[address]', 'street', '[office][street]', 'data.address[office][street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office.street'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office.street.prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office[street]'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address].office[street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address][office].street'), array(self::LEVEL_1, 'address', '[address]', 'street', '[office][street]', 'data[address][office].street.prop'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'data[address][office][street]'), array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'data[address][office][street].prop'), // Edge cases which must not occur array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address][street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address][street].prop'), array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address][street]'), array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address][street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address][street]'), array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address][street].prop'), array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address][street]'), array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address][street].prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'children[person].children[address].children[street]'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'children[person].children[address].data.street'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'children[person].data.address.street'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'data.address.street'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].children[office].children[street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].children[office].data.street'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'children[address].data.street'), array(self::LEVEL_1, 'address', 'address', 'street', 'office.street', 'data.address.street'), ); } /** * @dataProvider provideDefaultTests */ public function testDefaultErrorMapping($target, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) { $violation = $this->getConstraintViolation($violationPath); $parent = $this->getForm('parent'); $child = $this->getForm($childName, $childPath); $grandChild = $this->getForm($grandChildName, $grandChildPath); $parent->add($child); $child->add($grandChild); $this->mapper->mapViolation($violation, $parent); if (self::LEVEL_0 === $target) { $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); } } public function provideCustomDataErrorTests() { return array( // mapping target, error mapping, child name, its property path, grand child name, its property path, violation path array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo]'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo].prop'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address]'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address].prop'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo]'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address.prop'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address]'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo]'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address]'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo.prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo]'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address.prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address]'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address].prop'), array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo.street'), array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo.street.prop'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo[street]'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.foo[street].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo].street'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo].street.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo][street]'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[foo][street].prop'), array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address.street'), array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address.street.prop'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address[street]'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', 'street', 'data.address[street].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address].street'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address].street.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address][street]'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', 'street', 'data[address][street].prop'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street.prop'), array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street]'), array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street]'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street].prop'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address.street'), array(self::LEVEL_1, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address.street.prop'), array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address[street]'), array(self::LEVEL_2, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data.address[street].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address].street'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address].street.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address][street]'), array(self::LEVEL_0, 'foo', 'address', 'address', 'address', 'street', '[street]', 'data[address][street].prop'), array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street'), array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street.prop'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street]'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street]'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address.street'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address.street.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address[street]'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.address[street].prop'), array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address].street'), array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address].street.prop'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address][street]'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[address][street].prop'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street.prop'), array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street]'), array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street]'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street]'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street].prop'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street.prop'), array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street]'), array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street]'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street].prop'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street.prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street]'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street].prop'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address.street'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address.street.prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address[street]'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.address[street].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address].street'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address].street.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address][street]'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[address][street].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.street.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street]'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[street].prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].street.prop'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street]'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][street].prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address.street'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address.street.prop'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address[street]'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data.address[street].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address].street'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address].street.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address][street]'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', '[street]', 'data[address][street].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street]'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street].prop'), array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street'), array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street.prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street]'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address.street'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address.street.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address[street]'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data.address[street].prop'), array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address].street'), array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address].street.prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address][street]'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', 'street', 'data[address][street].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo.street.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street]'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.foo[street].prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo].street.prop'), array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street]'), array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[foo][street].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address.street.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street]'), array(self::LEVEL_0, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data.address[street].prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street'), array(self::LEVEL_1, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address].street.prop'), array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street]'), array(self::LEVEL_2, '[foo]', 'address', 'address', '[address]', 'street', '[street]', 'data[address][street].prop'), array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'), array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'), array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'), array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'), array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'), array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar]'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'), array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar]'), array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'), array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'), array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'), array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'), array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'), array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'), array(self::LEVEL_1, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'), array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'), array(self::LEVEL_2, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'), array(self::LEVEL_0, 'foo.bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'), array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'), array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'), array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'), array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'), array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'), array(self::LEVEL_1, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'), array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'), array(self::LEVEL_2, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'), array(self::LEVEL_0, 'foo[bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'), array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'), array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'), array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'), array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'), array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'), array(self::LEVEL_1, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'), array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'), array(self::LEVEL_2, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'), array(self::LEVEL_0, '[foo].bar', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar.street.prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street]'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo.bar[street].prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar].street.prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street]'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data.foo[bar][street].prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar.street.prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street]'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo].bar[street].prop'), array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street'), array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar].street.prop'), array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street]'), array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', 'street', 'data[foo][bar][street].prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar.street.prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street]'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo.bar[street].prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar].street.prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street]'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data.foo[bar][street].prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar.street.prop'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street]'), array(self::LEVEL_0, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo].bar[street].prop'), array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street'), array(self::LEVEL_1, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar].street.prop'), array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street]'), array(self::LEVEL_2, '[foo][bar]', 'address', 'address', 'address', 'street', '[street]', 'data[foo][bar][street].prop'), array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', 'street', 'data.foo'), array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', 'street', 'data.foo.prop'), array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo]'), array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo].prop'), array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo'), array(self::LEVEL_2, 'foo', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo.prop'), array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo]'), array(self::LEVEL_2, '[foo]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo].prop'), array(self::LEVEL_2, 'foo', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo'), array(self::LEVEL_2, 'foo', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo.prop'), array(self::LEVEL_2, '[foo]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo]'), array(self::LEVEL_2, '[foo]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo].prop'), array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', 'street', 'data.foo.bar'), array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', 'street', 'data.foo.bar.prop'), array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', 'street', 'data.foo[bar]'), array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', 'street', 'data.foo[bar].prop'), array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', 'street', 'data[foo].bar'), array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', 'street', 'data[foo].bar.prop'), array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo][bar]'), array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', 'street', 'data[foo][bar].prop'), array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo.bar'), array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo.bar.prop'), array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo[bar]'), array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data.foo[bar].prop'), array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo].bar'), array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo].bar.prop'), array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo][bar]'), array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', 'address', 'street', '[street]', 'data[foo][bar].prop'), array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo.bar'), array(self::LEVEL_2, 'foo.bar', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo.bar.prop'), array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo[bar]'), array(self::LEVEL_2, 'foo[bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data.foo[bar].prop'), array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo].bar'), array(self::LEVEL_2, '[foo].bar', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo].bar.prop'), array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo][bar]'), array(self::LEVEL_2, '[foo][bar]', 'address.street', 'address', '[address]', 'street', 'street', 'data[foo][bar].prop'), // Edge cases array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street'), array(self::LEVEL_2, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo.street.prop'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street]'), array(self::LEVEL_1, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data.foo[street].prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo].street.prop'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street]'), array(self::LEVEL_0, 'foo', 'address', 'address', '[address]', 'street', 'street', 'data[foo][street].prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo.street.prop'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street]'), array(self::LEVEL_0, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data.foo[street].prop'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street'), array(self::LEVEL_2, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo].street.prop'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street]'), array(self::LEVEL_1, '[foo]', 'address', 'address', 'address', 'street', 'street', 'data[foo][street].prop'), ); } /** * @dataProvider provideCustomDataErrorTests */ public function testCustomDataErrorMapping($target, $mapFrom, $mapTo, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) { $violation = $this->getConstraintViolation($violationPath); $parent = $this->getForm('parent', null, null, array($mapFrom => $mapTo)); $child = $this->getForm($childName, $childPath); $grandChild = $this->getForm($grandChildName, $grandChildPath); $parent->add($child); $child->add($grandChild); // Add a field mapped to the first element of $mapFrom // to try to distract the algorithm // Only add it if we expect the error to come up on a different // level than LEVEL_0, because in this case the error would // (correctly) be mapped to the distraction field if ($target !== self::LEVEL_0) { $mapFromPath = new PropertyPath($mapFrom); $mapFromPrefix = $mapFromPath->isIndex(0) ? '['.$mapFromPath->getElement(0).']' : $mapFromPath->getElement(0); $distraction = $this->getForm('distraction', $mapFromPrefix); $parent->add($distraction); } $this->mapper->mapViolation($violation, $parent); if ($target !== self::LEVEL_0) { $this->assertCount(0, $distraction->getErrors(), 'distraction should not have an error, but has one'); } if (self::LEVEL_0 === $target) { $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); } } public function provideCustomFormErrorTests() { // This case is different than the data errors, because here the // left side of the mapping refers to the property path of the actual // children. In other words, a child error only works if // 1) the error actually maps to an existing child and // 2) the property path of that child (relative to the form providing // the mapping) matches the left side of the mapping return array( // mapping target, map from, map to, child name, its property path, grand child name, its property path, violation path array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street]'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street].data'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street].data.prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street.prop'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street].prop'), // Property path of the erroneous field and mapping must match exactly array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'), array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'), array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street'), array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'), array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street]'), array(self::LEVEL_1B, 'foo', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'), array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'), array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'), array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street'), array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'), array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street]'), array(self::LEVEL_1B, '[foo]', 'address', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'), array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data'), array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].children[street].data.prop'), array(self::LEVEL_2, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street'), array(self::LEVEL_2, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data.street.prop'), array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street]'), array(self::LEVEL_1, '[foo]', 'address', 'foo', '[foo]', 'address', 'address', 'street', 'street', 'children[foo].data[street].prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].children[street].data'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].children[street].data.prop'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data.street'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data.street.prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data[street]'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo].data[street].prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street.prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street].prop'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].children[street].data'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].children[street].data.prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data.street'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data.street.prop'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data[street]'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo].data[street].prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street].data'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street].data.prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street.prop'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street].prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].children[street].data'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].children[street].data.prop'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data.street'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data.street.prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data[street]'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo].data[street].prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street].data'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street].data.prop'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street.prop'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'foo', 'address', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street].prop'), // Map to a nested child array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[foo]'), array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[foo]'), array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[foo]'), array(self::LEVEL_2, 'foo', 'address.street', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[foo]'), // Map from a nested child array(self::LEVEL_1B, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'), array(self::LEVEL_1B, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_1, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'), array(self::LEVEL_1B, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'), array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_1, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'), array(self::LEVEL_1, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_2, 'address.street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'), array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_1B, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1B, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'), array(self::LEVEL_1, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1B, 'address[street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'), array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_1, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'), array(self::LEVEL_1, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_2, 'address[street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'), array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_1, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'), array(self::LEVEL_1, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_1B, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'), array(self::LEVEL_1B, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_1, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'), array(self::LEVEL_1B, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_2, '[address].street', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].children[street]'), array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_1, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].children[street]'), array(self::LEVEL_1, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', 'address', 'street', '[street]', 'children[address].data[street]'), array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].children[street]'), array(self::LEVEL_2, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_1B, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1B, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].children[street]'), array(self::LEVEL_1, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data.street'), array(self::LEVEL_1B, '[address][street]', 'foo', 'foo', 'foo', 'address', '[address]', 'street', '[street]', 'children[address].data[street]'), ); } /** * @dataProvider provideCustomFormErrorTests */ public function testCustomFormErrorMapping($target, $mapFrom, $mapTo, $errorName, $errorPath, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) { $violation = $this->getConstraintViolation($violationPath); $parent = $this->getForm('parent', null, null, array($mapFrom => $mapTo)); $child = $this->getForm($childName, $childPath); $grandChild = $this->getForm($grandChildName, $grandChildPath); $errorChild = $this->getForm($errorName, $errorPath); $parent->add($child); $parent->add($errorChild); $child->add($grandChild); $this->mapper->mapViolation($violation, $parent); if (self::LEVEL_0 === $target) { $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1B === $target) { $this->assertEquals(array($this->getFormError()), $errorChild->getErrors(), $errorName.' should have an error, but has none'); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); } } public function provideErrorTestsForFormInheritingParentData() { return array( // mapping target, child name, its property path, grand child name, its property path, violation path array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].children[street].data.prop'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address].data.street.prop'), array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street]'), array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address].data[street].prop'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.street'), array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'data.street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[street]'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address.street'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address.street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address[street]'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data.address[street].prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address].street.prop'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street]'), array(self::LEVEL_0, 'address', 'address', 'street', 'street', 'data[address][street].prop'), ); } /** * @dataProvider provideErrorTestsForFormInheritingParentData */ public function testErrorMappingForFormInheritingParentData($target, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) { $violation = $this->getConstraintViolation($violationPath); $parent = $this->getForm('parent'); $child = $this->getForm($childName, $childPath, null, array(), true); $grandChild = $this->getForm($grandChildName, $grandChildPath); $parent->add($child); $child->add($grandChild); $this->mapper->mapViolation($violation, $parent); if (self::LEVEL_0 === $target) { $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); } } } Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php000064400000016664152374770060025353 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Extension\Validator\ViolationMapper; use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationPath; /** * @author Bernhard Schussek */ class ViolationPathTest extends \PHPUnit_Framework_TestCase { public function providePaths() { return array( array('children[address]', array( array('address', true, true), )), array('children[address].children[street]', array( array('address', true, true), array('street', true, true), )), array('children[address][street]', array( array('address', true, true), ), 'children[address]'), array('children[address].data', array( array('address', true, true), ), 'children[address]'), array('children[address].data.street', array( array('address', true, true), array('street', false, false), )), array('children[address].data[street]', array( array('address', true, true), array('street', false, true), )), array('children[address].children[street].data.name', array( array('address', true, true), array('street', true, true), array('name', false, false), )), array('children[address].children[street].data[name]', array( array('address', true, true), array('street', true, true), array('name', false, true), )), array('data.address', array( array('address', false, false), )), array('data[address]', array( array('address', false, true), )), array('data.address.street', array( array('address', false, false), array('street', false, false), )), array('data[address].street', array( array('address', false, true), array('street', false, false), )), array('data.address[street]', array( array('address', false, false), array('street', false, true), )), array('data[address][street]', array( array('address', false, true), array('street', false, true), )), // A few invalid examples array('data', array(), ''), array('children', array(), ''), array('children.address', array(), ''), array('children.address[street]', array(), ''), ); } /** * @dataProvider providePaths */ public function testCreatePath($string, $entries, $slicedPath = null) { if (null === $slicedPath) { $slicedPath = $string; } $path = new ViolationPath($string); $this->assertSame($slicedPath, $path->__toString()); $this->assertSame(count($entries), count($path->getElements())); $this->assertSame(count($entries), $path->getLength()); foreach ($entries as $index => $entry) { $this->assertEquals($entry[0], $path->getElement($index)); $this->assertSame($entry[1], $path->mapsForm($index)); $this->assertSame($entry[2], $path->isIndex($index)); $this->assertSame(!$entry[2], $path->isProperty($index)); } } public function provideParents() { return array( array('children[address]', null), array('children[address].children[street]', 'children[address]'), array('children[address].data.street', 'children[address]'), array('children[address].data[street]', 'children[address]'), array('data.address', null), array('data.address.street', 'data.address'), array('data.address[street]', 'data.address'), array('data[address].street', 'data[address]'), array('data[address][street]', 'data[address]'), ); } /** * @dataProvider provideParents */ public function testGetParent($violationPath, $parentPath) { $path = new ViolationPath($violationPath); $parent = $parentPath === null ? null : new ViolationPath($parentPath); $this->assertEquals($parent, $path->getParent()); } public function testGetElement() { $path = new ViolationPath('children[address].data[street].name'); $this->assertEquals('street', $path->getElement(1)); } /** * @expectedException \OutOfBoundsException */ public function testGetElementDoesNotAcceptInvalidIndices() { $path = new ViolationPath('children[address].data[street].name'); $path->getElement(3); } /** * @expectedException \OutOfBoundsException */ public function testGetElementDoesNotAcceptNegativeIndices() { $path = new ViolationPath('children[address].data[street].name'); $path->getElement(-1); } public function testIsProperty() { $path = new ViolationPath('children[address].data[street].name'); $this->assertFalse($path->isProperty(1)); $this->assertTrue($path->isProperty(2)); } /** * @expectedException \OutOfBoundsException */ public function testIsPropertyDoesNotAcceptInvalidIndices() { $path = new ViolationPath('children[address].data[street].name'); $path->isProperty(3); } /** * @expectedException \OutOfBoundsException */ public function testIsPropertyDoesNotAcceptNegativeIndices() { $path = new ViolationPath('children[address].data[street].name'); $path->isProperty(-1); } public function testIsIndex() { $path = new ViolationPath('children[address].data[street].name'); $this->assertTrue($path->isIndex(1)); $this->assertFalse($path->isIndex(2)); } /** * @expectedException \OutOfBoundsException */ public function testIsIndexDoesNotAcceptInvalidIndices() { $path = new ViolationPath('children[address].data[street].name'); $path->isIndex(3); } /** * @expectedException \OutOfBoundsException */ public function testIsIndexDoesNotAcceptNegativeIndices() { $path = new ViolationPath('children[address].data[street].name'); $path->isIndex(-1); } public function testMapsForm() { $path = new ViolationPath('children[address].data[street].name'); $this->assertTrue($path->mapsForm(0)); $this->assertFalse($path->mapsForm(1)); $this->assertFalse($path->mapsForm(2)); } /** * @expectedException \OutOfBoundsException */ public function testMapsFormDoesNotAcceptInvalidIndices() { $path = new ViolationPath('children[address].data[street].name'); $path->mapsForm(3); } /** * @expectedException \OutOfBoundsException */ public function testMapsFormDoesNotAcceptNegativeIndices() { $path = new ViolationPath('children[address].data[street].name'); $path->mapsForm(-1); } } Symfony/Component/Form/Tests/FormRegistryTest.php000064400000017351152374770060016206 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\FormRegistry; use Symfony\Component\Form\FormTypeGuesserChain; use Symfony\Component\Form\Tests\Fixtures\TestExtension; use Symfony\Component\Form\Tests\Fixtures\FooSubTypeWithParentInstance; use Symfony\Component\Form\Tests\Fixtures\FooSubType; use Symfony\Component\Form\Tests\Fixtures\FooTypeBazExtension; use Symfony\Component\Form\Tests\Fixtures\FooTypeBarExtension; use Symfony\Component\Form\Tests\Fixtures\FooType; /** * @author Bernhard Schussek */ class FormRegistryTest extends \PHPUnit_Framework_TestCase { /** * @var FormRegistry */ private $registry; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $resolvedTypeFactory; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $guesser1; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $guesser2; /** * @var TestExtension */ private $extension1; /** * @var TestExtension */ private $extension2; protected function setUp() { $this->resolvedTypeFactory = $this->getMock('Symfony\Component\Form\ResolvedFormTypeFactory'); $this->guesser1 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); $this->guesser2 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); $this->extension1 = new TestExtension($this->guesser1); $this->extension2 = new TestExtension($this->guesser2); $this->registry = new FormRegistry(array( $this->extension1, $this->extension2, ), $this->resolvedTypeFactory); } public function testGetTypeFromExtension() { $type = new FooType(); $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $this->extension2->addType($type); $this->resolvedTypeFactory->expects($this->once()) ->method('createResolvedType') ->with($type) ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->any()) ->method('getName') ->will($this->returnValue('foo')); $resolvedType = $this->registry->getType('foo'); $this->assertSame($resolvedType, $this->registry->getType('foo')); } public function testGetTypeWithTypeExtensions() { $type = new FooType(); $ext1 = new FooTypeBarExtension(); $ext2 = new FooTypeBazExtension(); $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $this->extension2->addType($type); $this->extension1->addTypeExtension($ext1); $this->extension2->addTypeExtension($ext2); $this->resolvedTypeFactory->expects($this->once()) ->method('createResolvedType') ->with($type, array($ext1, $ext2)) ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->any()) ->method('getName') ->will($this->returnValue('foo')); $this->assertSame($resolvedType, $this->registry->getType('foo')); } public function testGetTypeConnectsParent() { $parentType = new FooType(); $type = new FooSubType(); $parentResolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $this->extension1->addType($parentType); $this->extension2->addType($type); $this->resolvedTypeFactory->expects($this->at(0)) ->method('createResolvedType') ->with($parentType) ->will($this->returnValue($parentResolvedType)); $this->resolvedTypeFactory->expects($this->at(1)) ->method('createResolvedType') ->with($type, array(), $parentResolvedType) ->will($this->returnValue($resolvedType)); $parentResolvedType->expects($this->any()) ->method('getName') ->will($this->returnValue('foo')); $resolvedType->expects($this->any()) ->method('getName') ->will($this->returnValue('foo_sub_type')); $this->assertSame($resolvedType, $this->registry->getType('foo_sub_type')); } public function testGetTypeConnectsParentIfGetParentReturnsInstance() { $type = new FooSubTypeWithParentInstance(); $parentResolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $this->extension1->addType($type); $this->resolvedTypeFactory->expects($this->at(0)) ->method('createResolvedType') ->with($this->isInstanceOf('Symfony\Component\Form\Tests\Fixtures\FooType')) ->will($this->returnValue($parentResolvedType)); $this->resolvedTypeFactory->expects($this->at(1)) ->method('createResolvedType') ->with($type, array(), $parentResolvedType) ->will($this->returnValue($resolvedType)); $parentResolvedType->expects($this->any()) ->method('getName') ->will($this->returnValue('foo')); $resolvedType->expects($this->any()) ->method('getName') ->will($this->returnValue('foo_sub_type_parent_instance')); $this->assertSame($resolvedType, $this->registry->getType('foo_sub_type_parent_instance')); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testGetTypeThrowsExceptionIfParentNotFound() { $type = new FooSubType(); $this->extension1->addType($type); $this->registry->getType($type); } /** * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException */ public function testGetTypeThrowsExceptionIfTypeNotFound() { $this->registry->getType('bar'); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testGetTypeThrowsExceptionIfNoString() { $this->registry->getType(array()); } public function testHasTypeAfterLoadingFromExtension() { $type = new FooType(); $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $this->resolvedTypeFactory->expects($this->once()) ->method('createResolvedType') ->with($type) ->will($this->returnValue($resolvedType)); $resolvedType->expects($this->any()) ->method('getName') ->will($this->returnValue('foo')); $this->assertFalse($this->registry->hasType('foo')); $this->extension2->addType($type); $this->assertTrue($this->registry->hasType('foo')); } public function testGetTypeGuesser() { $expectedGuesser = new FormTypeGuesserChain(array($this->guesser1, $this->guesser2)); $this->assertEquals($expectedGuesser, $this->registry->getTypeGuesser()); $registry = new FormRegistry( array($this->getMock('Symfony\Component\Form\FormExtensionInterface')), $this->resolvedTypeFactory); $this->assertNull($registry->getTypeGuesser()); } public function testGetExtensions() { $expectedExtensions = array($this->extension1, $this->extension2); $this->assertEquals($expectedExtensions, $this->registry->getExtensions()); } } Symfony/Component/Form/Tests/FormFactoryBuilderTest.php000064400000003403152374770060017305 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\FormFactoryBuilder; use Symfony\Component\Form\Tests\Fixtures\FooType; class FormFactoryBuilderTest extends \PHPUnit_Framework_TestCase { private $registry; private $guesser; private $type; protected function setUp() { $factory = new \ReflectionClass('Symfony\Component\Form\FormFactory'); $this->registry = $factory->getProperty('registry'); $this->registry->setAccessible(true); $this->guesser = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); $this->type = new FooType(); } public function testAddType() { $factoryBuilder = new FormFactoryBuilder(); $factoryBuilder->addType($this->type); $factory = $factoryBuilder->getFormFactory(); $registry = $this->registry->getValue($factory); $extensions = $registry->getExtensions(); $this->assertCount(1, $extensions); $this->assertTrue($extensions[0]->hasType($this->type->getName())); $this->assertNull($extensions[0]->getTypeGuesser()); } public function testAddTypeGuesser() { $factoryBuilder = new FormFactoryBuilder(); $factoryBuilder->addTypeGuesser($this->guesser); $factory = $factoryBuilder->getFormFactory(); $registry = $this->registry->getValue($factory); $extensions = $registry->getExtensions(); $this->assertCount(1, $extensions); $this->assertNotNull($extensions[0]->getTypeGuesser()); } } Symfony/Component/Form/Tests/Util/OrderedHashMapTest.php000064400000033101152374770060017304 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Util; use Symfony\Component\Form\Util\OrderedHashMap; /** * @author Bernhard Schussek */ class OrderedHashMapTest extends \PHPUnit_Framework_TestCase { public function testGet() { $map = new OrderedHashMap(); $map['first'] = 1; $this->assertSame(1, $map['first']); } /** * @expectedException \OutOfBoundsException */ public function testGetNonExistingFails() { $map = new OrderedHashMap(); $map['first']; } public function testInsertStringKeys() { $map = new OrderedHashMap(); $map['first'] = 1; $map['second'] = 2; $this->assertSame(array('first' => 1, 'second' => 2), iterator_to_array($map)); } public function testInsertNullKeys() { $map = new OrderedHashMap(); $map[] = 1; $map['foo'] = 2; $map[] = 3; $this->assertSame(array(0 => 1, 'foo' => 2, 1 => 3), iterator_to_array($map)); } /** * Updates should not change the position of an element, otherwise we could * turn foreach loops into endless loops if they change the current * element: * * foreach ($map as $index => $value) { * $map[$index] = $value + 1; * } * * And we don't want this, right? :) */ public function testUpdateDoesNotChangeElementPosition() { $map = new OrderedHashMap(); $map['first'] = 1; $map['second'] = 2; $map['first'] = 1; $this->assertSame(array('first' => 1, 'second' => 2), iterator_to_array($map)); } public function testIsset() { $map = new OrderedHashMap(); $map['first'] = 1; $this->assertTrue(isset($map['first'])); } public function testIssetReturnsFalseForNonExisting() { $map = new OrderedHashMap(); $this->assertFalse(isset($map['first'])); } public function testIssetReturnsFalseForNull() { $map = new OrderedHashMap(); $map['first'] = null; $this->assertFalse(isset($map['first'])); } public function testUnset() { $map = new OrderedHashMap(); $map['first'] = 1; $map['second'] = 2; unset($map['first']); $this->assertSame(array('second' => 2), iterator_to_array($map)); } public function testUnsetNonExistingSucceeds() { $map = new OrderedHashMap(); unset($map['first']); } public function testEmptyIteration() { $map = new OrderedHashMap(); $it = $map->getIterator(); $it->rewind(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testIterationSupportsInsertion() { $map = new OrderedHashMap(array('first' => 1)); $it = $map->getIterator(); $it->rewind(); $this->assertTrue($it->valid()); $this->assertSame('first', $it->key()); $this->assertSame(1, $it->current()); // dynamic modification $map['added'] = 2; // iterator is unchanged $this->assertTrue($it->valid()); $this->assertSame('first', $it->key()); $this->assertSame(1, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('added', $it->key()); $this->assertSame(2, $it->current()); // end of map $it->next(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testIterationSupportsDeletionAndInsertion() { $map = new OrderedHashMap(array('first' => 1, 'removed' => 2)); $it = $map->getIterator(); $it->rewind(); $this->assertTrue($it->valid()); $this->assertSame('first', $it->key()); $this->assertSame(1, $it->current()); // dynamic modification unset($map['removed']); $map['added'] = 3; // iterator is unchanged $this->assertTrue($it->valid()); $this->assertSame('first', $it->key()); $this->assertSame(1, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('added', $it->key()); $this->assertSame(3, $it->current()); // end of map $it->next(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testIterationSupportsDeletionOfCurrentElement() { $map = new OrderedHashMap(array('removed' => 1, 'next' => 2)); $it = $map->getIterator(); $it->rewind(); $this->assertTrue($it->valid()); $this->assertSame('removed', $it->key()); $this->assertSame(1, $it->current()); unset($map['removed']); // iterator is unchanged $this->assertTrue($it->valid()); $this->assertSame('removed', $it->key()); $this->assertSame(1, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('next', $it->key()); $this->assertSame(2, $it->current()); // end of map $it->next(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testIterationIgnoresReplacementOfCurrentElement() { $map = new OrderedHashMap(array('replaced' => 1, 'next' => 2)); $it = $map->getIterator(); $it->rewind(); $this->assertTrue($it->valid()); $this->assertSame('replaced', $it->key()); $this->assertSame(1, $it->current()); $map['replaced'] = 3; // iterator is unchanged $this->assertTrue($it->valid()); $this->assertSame('replaced', $it->key()); $this->assertSame(1, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('next', $it->key()); $this->assertSame(2, $it->current()); // end of map $it->next(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testIterationSupportsDeletionOfCurrentAndLastElement() { $map = new OrderedHashMap(array('removed' => 1)); $it = $map->getIterator(); $it->rewind(); $this->assertTrue($it->valid()); $this->assertSame('removed', $it->key()); $this->assertSame(1, $it->current()); unset($map['removed']); // iterator is unchanged $this->assertTrue($it->valid()); $this->assertSame('removed', $it->key()); $this->assertSame(1, $it->current()); // end of map $it->next(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testIterationIgnoresReplacementOfCurrentAndLastElement() { $map = new OrderedHashMap(array('replaced' => 1)); $it = $map->getIterator(); $it->rewind(); $this->assertTrue($it->valid()); $this->assertSame('replaced', $it->key()); $this->assertSame(1, $it->current()); $map['replaced'] = 2; // iterator is unchanged $this->assertTrue($it->valid()); $this->assertSame('replaced', $it->key()); $this->assertSame(1, $it->current()); // end of map $it->next(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testIterationSupportsDeletionOfPreviousElement() { $map = new OrderedHashMap(array('removed' => 1, 'next' => 2, 'onemore' => 3)); $it = $map->getIterator(); $it->rewind(); $this->assertTrue($it->valid()); $this->assertSame('removed', $it->key()); $this->assertSame(1, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('next', $it->key()); $this->assertSame(2, $it->current()); unset($map['removed']); // iterator is unchanged $this->assertTrue($it->valid()); $this->assertSame('next', $it->key()); $this->assertSame(2, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('onemore', $it->key()); $this->assertSame(3, $it->current()); // end of map $it->next(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testIterationIgnoresReplacementOfPreviousElement() { $map = new OrderedHashMap(array('replaced' => 1, 'next' => 2, 'onemore' => 3)); $it = $map->getIterator(); $it->rewind(); $this->assertTrue($it->valid()); $this->assertSame('replaced', $it->key()); $this->assertSame(1, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('next', $it->key()); $this->assertSame(2, $it->current()); $map['replaced'] = 4; // iterator is unchanged $this->assertTrue($it->valid()); $this->assertSame('next', $it->key()); $this->assertSame(2, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('onemore', $it->key()); $this->assertSame(3, $it->current()); // end of map $it->next(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testIterationSupportsDeletionOfMultiplePreviousElements() { $map = new OrderedHashMap(array('removed' => 1, 'alsoremoved' => 2, 'next' => 3, 'onemore' => 4)); $it = $map->getIterator(); $it->rewind(); $this->assertTrue($it->valid()); $this->assertSame('removed', $it->key()); $this->assertSame(1, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('alsoremoved', $it->key()); $this->assertSame(2, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('next', $it->key()); $this->assertSame(3, $it->current()); unset($map['removed'], $map['alsoremoved']); // iterator is unchanged $this->assertTrue($it->valid()); $this->assertSame('next', $it->key()); $this->assertSame(3, $it->current()); // continue iteration $it->next(); $this->assertTrue($it->valid()); $this->assertSame('onemore', $it->key()); $this->assertSame(4, $it->current()); // end of map $it->next(); $this->assertFalse($it->valid()); $this->assertNull($it->key()); $this->assertNull($it->current()); } public function testParallelIteration() { $map = new OrderedHashMap(array('first' => 1, 'second' => 2)); $it1 = $map->getIterator(); $it2 = $map->getIterator(); $it1->rewind(); $this->assertTrue($it1->valid()); $this->assertSame('first', $it1->key()); $this->assertSame(1, $it1->current()); $it2->rewind(); $this->assertTrue($it2->valid()); $this->assertSame('first', $it2->key()); $this->assertSame(1, $it2->current()); // 1: continue iteration $it1->next(); $this->assertTrue($it1->valid()); $this->assertSame('second', $it1->key()); $this->assertSame(2, $it1->current()); // 2: remains unchanged $this->assertTrue($it2->valid()); $this->assertSame('first', $it2->key()); $this->assertSame(1, $it2->current()); // 1: advance to end of map $it1->next(); $this->assertFalse($it1->valid()); $this->assertNull($it1->key()); $this->assertNull($it1->current()); // 2: remains unchanged $this->assertTrue($it2->valid()); $this->assertSame('first', $it2->key()); $this->assertSame(1, $it2->current()); // 2: continue iteration $it2->next(); $this->assertTrue($it2->valid()); $this->assertSame('second', $it2->key()); $this->assertSame(2, $it2->current()); // 1: remains unchanged $this->assertFalse($it1->valid()); $this->assertNull($it1->key()); $this->assertNull($it1->current()); // 2: advance to end of map $it2->next(); $this->assertFalse($it2->valid()); $this->assertNull($it2->key()); $this->assertNull($it2->current()); // 1: remains unchanged $this->assertFalse($it1->valid()); $this->assertNull($it1->key()); $this->assertNull($it1->current()); } public function testCount() { $map = new OrderedHashMap(); $map[] = 1; $map['foo'] = 2; unset($map[0]); $map[] = 3; $this->assertSame(2, count($map)); } } Symfony/Component/Form/Tests/FormRendererTest.php000064400000001332152374770060016134 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; class FormRendererTest extends \PHPUnit_Framework_TestCase { public function testHumanize() { $renderer = $this->getMockBuilder('Symfony\Component\Form\FormRenderer') ->setMethods(null) ->disableOriginalConstructor() ->getMock() ; $this->assertEquals('Is active', $renderer->humanize('is_active')); $this->assertEquals('Is active', $renderer->humanize('isActive')); } } Symfony/Component/Form/Tests/Guess/GuessTest.php000064400000001635152374770060015724 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Guess; use Symfony\Component\Form\Guess\Guess; class TestGuess extends Guess {} class GuessTest extends \PHPUnit_Framework_TestCase { public function testGetBestGuessReturnsGuessWithHighestConfidence() { $guess1 = new TestGuess(Guess::MEDIUM_CONFIDENCE); $guess2 = new TestGuess(Guess::LOW_CONFIDENCE); $guess3 = new TestGuess(Guess::HIGH_CONFIDENCE); $this->assertSame($guess3, Guess::getBestGuess(array($guess1, $guess2, $guess3))); } /** * @expectedException \InvalidArgumentException */ public function testGuessExpectsValidConfidence() { new TestGuess(5); } } Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.php000064400000002125152374770060020570 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Exception\RuntimeException; class FixedDataTransformer implements DataTransformerInterface { private $mapping; public function __construct(array $mapping) { $this->mapping = $mapping; } public function transform($value) { if (!array_key_exists($value, $this->mapping)) { throw new RuntimeException(sprintf('No mapping for value "%s"', $value)); } return $this->mapping[$value]; } public function reverseTransform($value) { $result = array_search($value, $this->mapping, true); if ($result === false) { throw new RuntimeException(sprintf('No reverse mapping for value "%s"', $value)); } return $result; } } Symfony/Component/Form/Tests/Fixtures/Author.php000064400000002357152374770060015765 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; class Author { public $firstName; private $lastName; private $australian; public $child; private $readPermissions; private $privateProperty; public function setLastName($lastName) { $this->lastName = $lastName; } public function getLastName() { return $this->lastName; } private function getPrivateGetter() { return 'foobar'; } public function setAustralian($australian) { $this->australian = $australian; } public function isAustralian() { return $this->australian; } public function setReadPermissions($bool) { $this->readPermissions = $bool; } public function hasReadPermissions() { return $this->readPermissions; } private function isPrivateIsser() { return true; } public function getPrivateSetter() { } private function setPrivateSetter($data) { } } Symfony/Component/Form/Tests/Fixtures/AuthorType.php000064400000001310152374770060016613 0ustar00add('firstName') ->add('lastName') ; } public function getName() { return 'author'; } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', )); } } Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php000064400000003027152374770060020116 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; /** * This class is a hand written simplified version of PHP native `ArrayObject` * class, to show that it behaves differently than the PHP native implementation. */ class CustomArrayObject implements \ArrayAccess, \IteratorAggregate, \Countable, \Serializable { private $array; public function __construct(array $array = null) { $this->array = $array ?: array(); } public function offsetExists($offset) { return array_key_exists($offset, $this->array); } public function offsetGet($offset) { return $this->array[$offset]; } public function offsetSet($offset, $value) { if (null === $offset) { $this->array[] = $value; } else { $this->array[$offset] = $value; } } public function offsetUnset($offset) { unset($this->array[$offset]); } public function getIterator() { return new \ArrayIterator($this->array); } public function count() { return count($this->array); } public function serialize() { return serialize($this->array); } public function unserialize($serialized) { $this->array = (array) unserialize((string) $serialized); } } Symfony/Component/Form/Tests/Fixtures/FooTypeBazExtension.php000064400000001216152374770060020433 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\FormBuilderInterface; class FooTypeBazExtension extends AbstractTypeExtension { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->setAttribute('baz', 'x'); } public function getExtendedType() { return 'foo'; } } Symfony/Component/Form/Tests/Fixtures/FooTypeBarExtension.php000064400000001415152374770060020424 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\FormBuilderInterface; class FooTypeBarExtension extends AbstractTypeExtension { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->setAttribute('bar', 'x'); } public function getAllowedOptionValues() { return array( 'a_or_b' => array('c'), ); } public function getExtendedType() { return 'foo'; } } Symfony/Component/Form/Tests/Fixtures/FixedFilterListener.php000064400000003226152374770060020432 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; class FixedFilterListener implements EventSubscriberInterface { private $mapping; public function __construct(array $mapping) { $this->mapping = array_merge(array( 'preSubmit' => array(), 'onSubmit' => array(), 'preSetData' => array(), ), $mapping); } public function preSubmit(FormEvent $event) { $data = $event->getData(); if (isset($this->mapping['preSubmit'][$data])) { $event->setData($this->mapping['preSubmit'][$data]); } } public function onSubmit(FormEvent $event) { $data = $event->getData(); if (isset($this->mapping['onSubmit'][$data])) { $event->setData($this->mapping['onSubmit'][$data]); } } public function preSetData(FormEvent $event) { $data = $event->getData(); if (isset($this->mapping['preSetData'][$data])) { $event->setData($this->mapping['preSetData'][$data]); } } public static function getSubscribedEvents() { return array( FormEvents::PRE_SUBMIT => 'preSubmit', FormEvents::SUBMIT => 'onSubmit', FormEvents::PRE_SET_DATA => 'preSetData', ); } } Symfony/Component/Form/Tests/Fixtures/TestExtension.php000064400000003250152374770060017330 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\FormTypeInterface; use Symfony\Component\Form\FormTypeExtensionInterface; use Symfony\Component\Form\FormTypeGuesserInterface; use Symfony\Component\Form\FormExtensionInterface; class TestExtension implements FormExtensionInterface { private $types = array(); private $extensions = array(); private $guesser; public function __construct(FormTypeGuesserInterface $guesser) { $this->guesser = $guesser; } public function addType(FormTypeInterface $type) { $this->types[$type->getName()] = $type; } public function getType($name) { return isset($this->types[$name]) ? $this->types[$name] : null; } public function hasType($name) { return isset($this->types[$name]); } public function addTypeExtension(FormTypeExtensionInterface $extension) { $type = $extension->getExtendedType(); if (!isset($this->extensions[$type])) { $this->extensions[$type] = array(); } $this->extensions[$type][] = $extension; } public function getTypeExtensions($name) { return isset($this->extensions[$name]) ? $this->extensions[$name] : array(); } public function hasTypeExtensions($name) { return isset($this->extensions[$name]); } public function getTypeGuesser() { return $this->guesser; } } Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.php000064400000001374152374770060020323 0ustar00getFormFactory(); $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formFactory) { $form = $event->getForm(); $type = $form->getName() % 2 === 0 ? 'text' : 'textarea'; $form->add('title', $type); }); } public function getName() { return 'alternating_row'; } } Symfony/Component/Form/Tests/Fixtures/FooType.php000064400000001364152374770060016105 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class FooType extends AbstractType { public function getName() { return 'foo'; } public function getParent() { return null; } } Symfony/Component/Form/Tests/Fixtures/FooSubType.php000064400000001401152374770060016547 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class FooSubType extends AbstractType { public function getName() { return 'foo_sub_type'; } public function getParent() { return 'foo'; } } Symfony/Component/Form/Tests/Fixtures/FooSubTypeWithParentInstance.php000064400000001453152374770060022251 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class FooSubTypeWithParentInstance extends AbstractType { public function getName() { return 'foo_sub_type_parent_instance'; } public function getParent() { return new FooType(); } } Symfony/Component/Form/Tests/Fixtures/foo000064400000000000152374770060014477 0ustar00Symfony/Component/Form/Tests/FormBuilderTest.php000064400000015723152374770060015765 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\FormBuilder; class FormBuilderTest extends \PHPUnit_Framework_TestCase { private $dispatcher; private $factory; private $builder; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->builder = new FormBuilder('name', null, $this->dispatcher, $this->factory); } protected function tearDown() { $this->dispatcher = null; $this->factory = null; $this->builder = null; } /** * Changing the name is not allowed, otherwise the name and property path * are not synchronized anymore * * @see FormType::buildForm */ public function testNoSetName() { $this->assertFalse(method_exists($this->builder, 'setName')); } public function testAddNameNoStringAndNoInteger() { $this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException'); $this->builder->add(true); } public function testAddTypeNoString() { $this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException'); $this->builder->add('foo', 1234); } public function testAddWithGuessFluent() { $this->builder = new FormBuilder('name', 'stdClass', $this->dispatcher, $this->factory); $builder = $this->builder->add('foo'); $this->assertSame($builder, $this->builder); } public function testAddIsFluent() { $builder = $this->builder->add('foo', 'text', array('bar' => 'baz')); $this->assertSame($builder, $this->builder); } public function testAdd() { $this->assertFalse($this->builder->has('foo')); $this->builder->add('foo', 'text'); $this->assertTrue($this->builder->has('foo')); } public function testAddIntegerName() { $this->assertFalse($this->builder->has(0)); $this->builder->add(0, 'text'); $this->assertTrue($this->builder->has(0)); } public function testAll() { $this->factory->expects($this->once()) ->method('createNamedBuilder') ->with('foo', 'text') ->will($this->returnValue(new FormBuilder('foo', null, $this->dispatcher, $this->factory))); $this->assertCount(0, $this->builder->all()); $this->assertFalse($this->builder->has('foo')); $this->builder->add('foo', 'text'); $children = $this->builder->all(); $this->assertTrue($this->builder->has('foo')); $this->assertCount(1, $children); $this->assertArrayHasKey('foo', $children); } /* * https://github.com/symfony/symfony/issues/4693 */ public function testMaintainOrderOfLazyAndExplicitChildren() { $this->builder->add('foo', 'text'); $this->builder->add($this->getFormBuilder('bar')); $this->builder->add('baz', 'text'); $children = $this->builder->all(); $this->assertSame(array('foo', 'bar', 'baz'), array_keys($children)); } public function testAddFormType() { $this->assertFalse($this->builder->has('foo')); $this->builder->add('foo', $this->getMock('Symfony\Component\Form\FormTypeInterface')); $this->assertTrue($this->builder->has('foo')); } public function testRemove() { $this->builder->add('foo', 'text'); $this->builder->remove('foo'); $this->assertFalse($this->builder->has('foo')); } public function testRemoveUnknown() { $this->builder->remove('foo'); $this->assertFalse($this->builder->has('foo')); } // https://github.com/symfony/symfony/pull/4826 public function testRemoveAndGetForm() { $this->builder->add('foo', 'text'); $this->builder->remove('foo'); $form = $this->builder->getForm(); $this->assertInstanceOf('Symfony\Component\Form\Form', $form); } public function testCreateNoTypeNo() { $this->factory->expects($this->once()) ->method('createNamedBuilder') ->with('foo', 'text', null, array()) ; $this->builder->create('foo'); } public function testGetUnknown() { $this->setExpectedException('Symfony\Component\Form\Exception\InvalidArgumentException', 'The child with the name "foo" does not exist.'); $this->builder->get('foo'); } public function testGetExplicitType() { $expectedType = 'text'; $expectedName = 'foo'; $expectedOptions = array('bar' => 'baz'); $this->factory->expects($this->once()) ->method('createNamedBuilder') ->with($expectedName, $expectedType, null, $expectedOptions) ->will($this->returnValue($this->getFormBuilder())); $this->builder->add($expectedName, $expectedType, $expectedOptions); $builder = $this->builder->get($expectedName); $this->assertNotSame($builder, $this->builder); } public function testGetGuessedType() { $expectedName = 'foo'; $expectedOptions = array('bar' => 'baz'); $this->factory->expects($this->once()) ->method('createBuilderForProperty') ->with('stdClass', $expectedName, null, $expectedOptions) ->will($this->returnValue($this->getFormBuilder())); $this->builder = new FormBuilder('name', 'stdClass', $this->dispatcher, $this->factory); $this->builder->add($expectedName, null, $expectedOptions); $builder = $this->builder->get($expectedName); $this->assertNotSame($builder, $this->builder); } public function testGetFormConfigErasesReferences() { $builder = new FormBuilder('name', null, $this->dispatcher, $this->factory); $builder->add(new FormBuilder('child', null, $this->dispatcher, $this->factory)); $config = $builder->getFormConfig(); $reflClass = new \ReflectionClass($config); $children = $reflClass->getProperty('children'); $unresolvedChildren = $reflClass->getProperty('unresolvedChildren'); $children->setAccessible(true); $unresolvedChildren->setAccessible(true); $this->assertEmpty($children->getValue($config)); $this->assertEmpty($unresolvedChildren->getValue($config)); } private function getFormBuilder($name = 'name') { $mock = $this->getMockBuilder('Symfony\Component\Form\FormBuilder') ->disableOriginalConstructor() ->getMock(); $mock->expects($this->any()) ->method('getName') ->will($this->returnValue($name)); return $mock; } } Symfony/Component/Form/Tests/AbstractExtensionTest.php000064400000002005152374770060017200 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\Form\Tests\Fixtures\FooType; class AbstractExtensionTest extends \PHPUnit_Framework_TestCase { public function testHasType() { $loader = new ConcreteExtension(); $this->assertTrue($loader->hasType('foo')); $this->assertFalse($loader->hasType('bar')); } public function testGetType() { $loader = new ConcreteExtension(); $this->assertInstanceOf('Symfony\Component\Form\Tests\Fixtures\FooType', $loader->getType('foo')); } } class ConcreteExtension extends AbstractExtension { protected function loadTypes() { return array(new FooType()); } protected function loadTypeGuesser() { } } Symfony/Component/Form/Tests/FormConfigTest.php000064400000011175152374770060015601 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\Exception\InvalidArgumentException; /** * @author Bernhard Schussek */ class FormConfigTest extends \PHPUnit_Framework_TestCase { public function getHtml4Ids() { return array( array('z0', true), array('A0', true), array('A9', true), array('Z0', true), array('#', false), array('a#', false), array('a$', false), array('a%', false), array('a ', false), array("a\t", false), array("a\n", false), array('a-', true), array('a_', true), array('a:', true), // Periods are allowed by the HTML4 spec, but disallowed by us // because they break the generated property paths array('a.', false), // Contrary to the HTML4 spec, we allow names starting with a // number, otherwise naming fields by collection indices is not // possible. // For root forms, leading digits will be stripped from the // "id" attribute to produce valid HTML4. array('0', true), array('9', true), // Contrary to the HTML4 spec, we allow names starting with an // underscore, since this is already a widely used practice in // Symfony2. // For root forms, leading underscores will be stripped from the // "id" attribute to produce valid HTML4. array('_', true), // Integers are allowed array(0, true), array(123, true), // NULL is allowed array(null, true), // Other types are not array(1.23, false), array(5., false), array(true, false), array(new \stdClass(), false), ); } /** * @dataProvider getHtml4Ids */ public function testNameAcceptsOnlyNamesValidAsIdsInHtml4($name, $accepted) { $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); try { new FormConfigBuilder($name, null, $dispatcher); if (!$accepted) { $this->fail(sprintf('The value "%s" should not be accepted', $name)); } } catch (UnexpectedTypeException $e) { // if the value was not accepted, but should be, rethrow exception if ($accepted) { throw $e; } } catch (InvalidArgumentException $e) { // if the value was not accepted, but should be, rethrow exception if ($accepted) { throw $e; } } } public function testGetRequestHandlerCreatesNativeRequestHandlerIfNotSet() { $config = $this->getConfigBuilder()->getFormConfig(); $this->assertInstanceOf('Symfony\Component\Form\NativeRequestHandler', $config->getRequestHandler()); } public function testGetRequestHandlerReusesNativeRequestHandlerInstance() { $config1 = $this->getConfigBuilder()->getFormConfig(); $config2 = $this->getConfigBuilder()->getFormConfig(); $this->assertSame($config1->getRequestHandler(), $config2->getRequestHandler()); } public function testSetMethodAllowsGet() { $this->getConfigBuilder()->setMethod('GET'); } public function testSetMethodAllowsPost() { $this->getConfigBuilder()->setMethod('POST'); } public function testSetMethodAllowsPut() { $this->getConfigBuilder()->setMethod('PUT'); } public function testSetMethodAllowsDelete() { $this->getConfigBuilder()->setMethod('DELETE'); } public function testSetMethodAllowsPatch() { $this->getConfigBuilder()->setMethod('PATCH'); } /** * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException */ public function testSetMethodDoesNotAllowOtherValues() { $this->getConfigBuilder()->setMethod('foo'); } private function getConfigBuilder($name = 'name') { $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); return new FormConfigBuilder($name, null, $dispatcher); } } Symfony/Component/Form/Tests/CompoundFormPerformanceTest.php000064400000002557152374770060020346 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; /** * @author Bernhard Schussek */ class CompoundFormPerformanceTest extends \Symfony\Component\Form\Tests\FormPerformanceTestCase { /** * Create a compound form multiple times, as happens in a collection form * * @group benchmark */ public function testArrayBasedForm() { $this->setMaxRunningTime(1); for ($i = 0; $i < 40; ++$i) { $form = $this->factory->createBuilder('form') ->add('firstName', 'text') ->add('lastName', 'text') ->add('gender', 'choice', array( 'choices' => array('male' => 'Male', 'female' => 'Female'), 'required' => false, )) ->add('age', 'number') ->add('birthDate', 'birthday') ->add('city', 'choice', array( // simulate 300 different cities 'choices' => range(1, 300), )) ->getForm(); // load the form into a view $form->createView(); } } } Symfony/Component/Form/Tests/AbstractFormTest.php000064400000006025152374770060016135 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\FormBuilder; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcherInterface; abstract class AbstractFormTest extends \PHPUnit_Framework_TestCase { /** * @var EventDispatcherInterface */ protected $dispatcher; /** * @var \Symfony\Component\Form\FormFactoryInterface */ protected $factory; /** * @var \Symfony\Component\Form\FormInterface */ protected $form; protected function setUp() { // We need an actual dispatcher to use the deprecated // bindRequest() method $this->dispatcher = new EventDispatcher(); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->form = $this->createForm(); } protected function tearDown() { $this->dispatcher = null; $this->factory = null; $this->form = null; } /** * @return \Symfony\Component\Form\FormInterface */ abstract protected function createForm(); /** * @param string $name * @param EventDispatcherInterface $dispatcher * @param string $dataClass * @param array $options * * @return FormBuilder */ protected function getBuilder($name = 'name', EventDispatcherInterface $dispatcher = null, $dataClass = null, array $options = array()) { return new FormBuilder($name, $dataClass, $dispatcher ?: $this->dispatcher, $this->factory, $options); } /** * @param string $name * * @return \PHPUnit_Framework_MockObject_MockObject */ protected function getMockForm($name = 'name') { $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $config = $this->getMock('Symfony\Component\Form\FormConfigInterface'); $form->expects($this->any()) ->method('getName') ->will($this->returnValue($name)); $form->expects($this->any()) ->method('getConfig') ->will($this->returnValue($config)); return $form; } /** * @return \PHPUnit_Framework_MockObject_MockObject */ protected function getDataMapper() { return $this->getMock('Symfony\Component\Form\DataMapperInterface'); } /** * @return \PHPUnit_Framework_MockObject_MockObject */ protected function getDataTransformer() { return $this->getMock('Symfony\Component\Form\DataTransformerInterface'); } /** * @return \PHPUnit_Framework_MockObject_MockObject */ protected function getFormValidator() { return $this->getMock('Symfony\Component\Form\FormValidatorInterface'); } } Symfony/Component/Form/Tests/AbstractDivLayoutTest.php000064400000052132152374770060017152 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\FormError; use Symfony\Component\Form\Tests\Fixtures\AlternatingRowType; use Symfony\Component\Security\Csrf\CsrfToken; abstract class AbstractDivLayoutTest extends AbstractLayoutTest { public function testRow() { $form = $this->factory->createNamed('name', 'text'); $form->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $html = $this->renderRow($view); $this->assertMatchesXpath($html, '/div [ ./label[@for="name"] /following-sibling::ul [./li[.="[trans]Error![/trans]"]] [count(./li)=1] /following-sibling::input[@id="name"] ] ' ); } public function testRowOverrideVariables() { $view = $this->factory->createNamed('name', 'text')->createView(); $html = $this->renderRow($view, array( 'attr' => array('class' => 'my&class'), 'label' => 'foo&bar', 'label_attr' => array('class' => 'my&label&class'), )); $this->assertMatchesXpath($html, '/div [ ./label[@for="name"][@class="my&label&class required"][.="[trans]foo&bar[/trans]"] /following-sibling::input[@id="name"][@class="my&class"] ] ' ); } public function testRepeatedRow() { $form = $this->factory->createNamed('name', 'repeated'); $form->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $html = $this->renderRow($view); // The errors of the form are not rendered by intention! // In practice, repeated fields cannot have errors as all errors // on them are mapped to the first child. // (see RepeatedTypeValidatorExtension) $this->assertMatchesXpath($html, '/div [ ./label[@for="name_first"] /following-sibling::input[@id="name_first"] ] /following-sibling::div [ ./label[@for="name_second"] /following-sibling::input[@id="name_second"] ] ' ); } public function testButtonRow() { $form = $this->factory->createNamed('name', 'button'); $view = $form->createView(); $html = $this->renderRow($view); $this->assertMatchesXpath($html, '/div [ ./button[@type="button"][@name="name"] ] [count(//label)=0] ' ); } public function testRest() { $view = $this->factory->createNamedBuilder('name', 'form') ->add('field1', 'text') ->add('field2', 'repeated') ->add('field3', 'text') ->add('field4', 'text') ->getForm() ->createView(); // Render field2 row -> does not implicitly call renderWidget because // it is a repeated field! $this->renderRow($view['field2']); // Render field3 widget $this->renderWidget($view['field3']); // Rest should only contain field1 and field4 $html = $this->renderRest($view); $this->assertMatchesXpath($html, '/div [ ./label[@for="name_field1"] /following-sibling::input[@type="text"][@id="name_field1"] ] /following-sibling::div [ ./label[@for="name_field4"] /following-sibling::input[@type="text"][@id="name_field4"] ] [count(../div)=2] [count(..//label)=2] [count(..//input)=3] /following-sibling::input [@type="hidden"] [@id="name__token"] ' ); } public function testRestWithChildrenForms() { $child1 = $this->factory->createNamedBuilder('child1', 'form') ->add('field1', 'text') ->add('field2', 'text'); $child2 = $this->factory->createNamedBuilder('child2', 'form') ->add('field1', 'text') ->add('field2', 'text'); $view = $this->factory->createNamedBuilder('parent', 'form') ->add($child1) ->add($child2) ->getForm() ->createView(); // Render child1.field1 row $this->renderRow($view['child1']['field1']); // Render child2.field2 widget (remember that widget don't render label) $this->renderWidget($view['child2']['field2']); // Rest should only contain child1.field2 and child2.field1 $html = $this->renderRest($view); $this->assertMatchesXpath($html, '/div [ ./label[not(@for)] /following-sibling::div[@id="parent_child1"] [ ./div [ ./label[@for="parent_child1_field2"] /following-sibling::input[@id="parent_child1_field2"] ] ] ] /following-sibling::div [ ./label[not(@for)] /following-sibling::div[@id="parent_child2"] [ ./div [ ./label[@for="parent_child2_field1"] /following-sibling::input[@id="parent_child2_field1"] ] ] ] [count(//label)=4] [count(//input[@type="text"])=2] /following-sibling::input[@type="hidden"][@id="parent__token"] ' ); } public function testRestAndRepeatedWithRow() { $view = $this->factory->createNamedBuilder('name', 'form') ->add('first', 'text') ->add('password', 'repeated') ->getForm() ->createView(); $this->renderRow($view['password']); $html = $this->renderRest($view); $this->assertMatchesXpath($html, '/div [ ./label[@for="name_first"] /following-sibling::input[@type="text"][@id="name_first"] ] [count(.//input)=1] /following-sibling::input [@type="hidden"] [@id="name__token"] ' ); } public function testRestAndRepeatedWithRowPerChild() { $view = $this->factory->createNamedBuilder('name', 'form') ->add('first', 'text') ->add('password', 'repeated') ->getForm() ->createView(); $this->renderRow($view['password']['first']); $this->renderRow($view['password']['second']); $html = $this->renderRest($view); $this->assertMatchesXpath($html, '/div [ ./label[@for="name_first"] /following-sibling::input[@type="text"][@id="name_first"] ] [count(.//input)=1] [count(.//label)=1] /following-sibling::input [@type="hidden"] [@id="name__token"] ' ); } public function testRestAndRepeatedWithWidgetPerChild() { $view = $this->factory->createNamedBuilder('name', 'form') ->add('first', 'text') ->add('password', 'repeated') ->getForm() ->createView(); // The password form is considered as rendered as all its children // are rendered $this->renderWidget($view['password']['first']); $this->renderWidget($view['password']['second']); $html = $this->renderRest($view); $this->assertMatchesXpath($html, '/div [ ./label[@for="name_first"] /following-sibling::input[@type="text"][@id="name_first"] ] [count(//input)=2] [count(//label)=1] /following-sibling::input [@type="hidden"] [@id="name__token"] ' ); } public function testCollection() { $form = $this->factory->createNamed('name', 'collection', array('a', 'b'), array( 'type' => 'text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div[./input[@type="text"][@value="a"]] /following-sibling::div[./input[@type="text"][@value="b"]] ] [count(./div[./input])=2] ' ); } // https://github.com/symfony/symfony/issues/5038 public function testCollectionWithAlternatingRowTypes() { $data = array( array('title' => 'a'), array('title' => 'b'), ); $form = $this->factory->createNamed('name', 'collection', $data, array( 'type' => new AlternatingRowType(), )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div[./div/div/input[@type="text"][@value="a"]] /following-sibling::div[./div/div/textarea[.="b"]] ] [count(./div[./div/div/input])=1] [count(./div[./div/div/textarea])=1] ' ); } public function testEmptyCollection() { $form = $this->factory->createNamed('name', 'collection', array(), array( 'type' => 'text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [./input[@type="hidden"][@id="name__token"]] [count(./div)=0] ' ); } public function testCollectionRow() { $collection = $this->factory->createNamedBuilder( 'collection', 'collection', array('a', 'b'), array('type' => 'text') ); $form = $this->factory->createNamedBuilder('form', 'form') ->add($collection) ->getForm(); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [ ./label[not(@for)] /following-sibling::div [ ./div [ ./label[@for="form_collection_0"] /following-sibling::input[@type="text"][@value="a"] ] /following-sibling::div [ ./label[@for="form_collection_1"] /following-sibling::input[@type="text"][@value="b"] ] ] ] /following-sibling::input[@type="hidden"][@id="form__token"] ] [count(.//input)=3] ' ); } public function testForm() { $form = $this->factory->createNamedBuilder('name', 'form') ->setMethod('PUT') ->setAction('http://example.com') ->add('firstName', 'text') ->add('lastName', 'text') ->getForm(); // include ampersands everywhere to validate escaping $html = $this->renderForm($form->createView(), array( 'id' => 'my&id', 'attr' => array('class' => 'my&class'), )); $this->assertMatchesXpath($html, '/form [ ./input[@type="hidden"][@name="_method"][@value="PUT"] /following-sibling::div [ ./div [ ./label[@for="name_firstName"] /following-sibling::input[@type="text"][@id="name_firstName"] ] /following-sibling::div [ ./label[@for="name_lastName"] /following-sibling::input[@type="text"][@id="name_lastName"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] [count(.//input)=3] [@id="my&id"] [@class="my&class"] ] [@method="post"] [@action="http://example.com"] [@class="my&class"] ' ); } public function testFormWidget() { $form = $this->factory->createNamedBuilder('name', 'form') ->add('firstName', 'text') ->add('lastName', 'text') ->getForm(); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [ ./label[@for="name_firstName"] /following-sibling::input[@type="text"][@id="name_firstName"] ] /following-sibling::div [ ./label[@for="name_lastName"] /following-sibling::input[@type="text"][@id="name_lastName"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] [count(.//input)=3] ' ); } // https://github.com/symfony/symfony/issues/2308 public function testNestedFormError() { $form = $this->factory->createNamedBuilder('name', 'form') ->add($this->factory ->createNamedBuilder('child', 'form', null, array('error_bubbling' => false)) ->add('grandChild', 'form') ) ->getForm(); $form->get('child')->addError(new FormError('[trans]Error![/trans]')); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div/label /following-sibling::ul[./li[.="[trans]Error![/trans]"]] ] [count(.//li[.="[trans]Error![/trans]"])=1] ' ); } public function testCsrf() { $this->csrfTokenManager->expects($this->any()) ->method('getToken') ->will($this->returnValue(new CsrfToken('token_id', 'foo&bar'))); $form = $this->factory->createNamedBuilder('name', 'form') ->add($this->factory // No CSRF protection on nested forms ->createNamedBuilder('child', 'form') ->add($this->factory->createNamedBuilder('grandchild', 'text')) ) ->getForm(); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div /following-sibling::input[@type="hidden"][@id="name__token"][@value="foo&bar"] ] [count(.//input[@type="hidden"])=1] ' ); } public function testRepeated() { $form = $this->factory->createNamed('name', 'repeated', 'foobar', array( 'type' => 'text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [ ./label[@for="name_first"] /following-sibling::input[@type="text"][@id="name_first"] ] /following-sibling::div [ ./label[@for="name_second"] /following-sibling::input[@type="text"][@id="name_second"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] [count(.//input)=3] ' ); } public function testRepeatedWithCustomOptions() { $form = $this->factory->createNamed('name', 'repeated', null, array( // the global required value cannot be overridden 'first_options' => array('label' => 'Test', 'required' => false), 'second_options' => array('label' => 'Test2') )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [ ./label[@for="name_first"][.="[trans]Test[/trans]"] /following-sibling::input[@type="text"][@id="name_first"][@required="required"] ] /following-sibling::div [ ./label[@for="name_second"][.="[trans]Test2[/trans]"] /following-sibling::input[@type="text"][@id="name_second"][@required="required"] ] /following-sibling::input[@type="hidden"][@id="name__token"] ] [count(.//input)=3] ' ); } public function testSearchInputName() { $form = $this->factory->createNamedBuilder('full', 'form') ->add('name', 'search') ->getForm(); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [ ./label[@for="full_name"] /following-sibling::input[@type="search"][@id="full_name"][@name="full[name]"] ] /following-sibling::input[@type="hidden"][@id="full__token"] ] [count(//input)=2] ' ); } public function testLabelHasNoId() { $form = $this->factory->createNamed('name', 'text'); $html = $this->renderRow($form->createView()); $this->assertMatchesXpath($html, '/div [ ./label[@for="name"][not(@id)] /following-sibling::input[@id="name"] ] ' ); } public function testLabelIsNotRenderedWhenSetToFalse() { $form = $this->factory->createNamed('name', 'text', null, array( 'label' => false )); $html = $this->renderRow($form->createView()); $this->assertMatchesXpath($html, '/div [ ./input[@id="name"] ] [count(//label)=0] ' ); } /** * @dataProvider themeBlockInheritanceProvider */ public function testThemeBlockInheritance($theme) { $view = $this->factory ->createNamed('name', 'email') ->createView() ; $this->setTheme($view, $theme); $this->assertMatchesXpath( $this->renderWidget($view), '/input[@type="email"][@rel="theme"]' ); } /** * @dataProvider themeInheritanceProvider */ public function testThemeInheritance($parentTheme, $childTheme) { $child = $this->factory->createNamedBuilder('child', 'form') ->add('field', 'text'); $view = $this->factory->createNamedBuilder('parent', 'form') ->add('field', 'text') ->add($child) ->getForm() ->createView() ; $this->setTheme($view, $parentTheme); $this->setTheme($view['child'], $childTheme); $this->assertWidgetMatchesXpath($view, array(), '/div [ ./div [ ./label[.="parent"] /following-sibling::input[@type="text"] ] /following-sibling::div [ ./label[.="child"] /following-sibling::div [ ./div [ ./label[.="child"] /following-sibling::input[@type="text"] ] ] ] /following-sibling::input[@type="hidden"] ] ' ); } /** * The block "_name_child_label" should be overridden in the theme of the * implemented driver. */ public function testCollectionRowWithCustomBlock() { $collection = array('one', 'two', 'three'); $form = $this->factory->createNamedBuilder('name', 'collection', $collection) ->getForm(); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div[./label[.="Custom label: [trans]0[/trans]"]] /following-sibling::div[./label[.="Custom label: [trans]1[/trans]"]] /following-sibling::div[./label[.="Custom label: [trans]2[/trans]"]] ] ' ); } public function testFormEndWithRest() { $view = $this->factory->createNamedBuilder('name', 'form') ->add('field1', 'text') ->add('field2', 'text') ->getForm() ->createView(); $this->renderWidget($view['field1']); // Rest should only contain field2 $html = $this->renderEnd($view); // Insert the start tag, the end tag should be rendered by the helper $this->assertMatchesXpath('
' . $html, '/form [ ./div [ ./label[@for="name_field2"] /following-sibling::input[@type="text"][@id="name_field2"] ] /following-sibling::input [@type="hidden"] [@id="name__token"] ] ' ); } public function testFormEndWithoutRest() { $view = $this->factory->createNamedBuilder('name', 'form') ->add('field1', 'text') ->add('field2', 'text') ->getForm() ->createView(); $this->renderWidget($view['field1']); // Rest should only contain field2, but isn't rendered $html = $this->renderEnd($view, array('render_rest' => false)); $this->assertEquals('', $html); } public function testWidgetContainerAttributes() { $form = $this->factory->createNamed('form', 'form', null, array( 'attr' => array('class' => 'foobar', 'data-foo' => 'bar'), )); $form->add('text', 'text'); $html = $this->renderWidget($form->createView()); // compare plain HTML to check the whitespace $this->assertContains('
', $html); } public function testWidgetContainerAttributeNameRepeatedIfTrue() { $form = $this->factory->createNamed('form', 'form', null, array( 'attr' => array('foo' => true), )); $html = $this->renderWidget($form->createView()); // foo="foo" $this->assertContains('
', $html); } public function testWidgetContainerAttributeHiddenIfFalse() { $form = $this->factory->createNamed('form', 'form', null, array( 'attr' => array('foo' => false), )); $html = $this->renderWidget($form->createView()); // no foo $this->assertContains('
', $html); } } Symfony/Component/Form/Tests/AbstractLayoutTest.php000064400000161405152374770060016513 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Extension\Csrf\CsrfExtension; abstract class AbstractLayoutTest extends \Symfony\Component\Form\Test\FormIntegrationTestCase { protected $csrfTokenManager; protected function setUp() { if (!extension_loaded('intl')) { $this->markTestSkipped('The "intl" extension is not available'); } \Locale::setDefault('en'); $this->csrfTokenManager = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface'); parent::setUp(); } protected function getExtensions() { return array( new CsrfExtension($this->csrfTokenManager), ); } protected function tearDown() { $this->csrfTokenManager = null; parent::tearDown(); } protected function assertXpathNodeValue(\DomElement $element, $expression, $nodeValue) { $xpath = new \DOMXPath($element->ownerDocument); $nodeList = $xpath->evaluate($expression); $this->assertEquals(1, $nodeList->length); $this->assertEquals($nodeValue, $nodeList->item(0)->nodeValue); } protected function assertMatchesXpath($html, $expression, $count = 1) { $dom = new \DomDocument('UTF-8'); try { // Wrap in node so we can load HTML with multiple tags at // the top level $dom->loadXml(''.$html.''); } catch (\Exception $e) { $this->fail(sprintf( "Failed loading HTML:\n\n%s\n\nError: %s", $html, $e->getMessage() )); } $xpath = new \DOMXPath($dom); $nodeList = $xpath->evaluate('/root'.$expression); if ($nodeList->length != $count) { $dom->formatOutput = true; $this->fail(sprintf( "Failed asserting that \n\n%s\n\nmatches exactly %s. Matches %s in \n\n%s", $expression, $count == 1 ? 'once' : $count.' times', $nodeList->length == 1 ? 'once' : $nodeList->length.' times', // strip away and substr($dom->saveHTML(), 6, -8) )); } } protected function assertWidgetMatchesXpath(FormView $view, array $vars, $xpath) { // include ampersands everywhere to validate escaping $html = $this->renderWidget($view, array_merge(array( 'id' => 'my&id', 'attr' => array('class' => 'my&class'), ), $vars)); $xpath = trim($xpath).' [@id="my&id"] [@class="my&class"]'; $this->assertMatchesXpath($html, $xpath); } abstract protected function renderForm(FormView $view, array $vars = array()); abstract protected function renderEnctype(FormView $view); abstract protected function renderLabel(FormView $view, $label = null, array $vars = array()); abstract protected function renderErrors(FormView $view); abstract protected function renderWidget(FormView $view, array $vars = array()); abstract protected function renderRow(FormView $view, array $vars = array()); abstract protected function renderRest(FormView $view, array $vars = array()); abstract protected function renderStart(FormView $view, array $vars = array()); abstract protected function renderEnd(FormView $view, array $vars = array()); abstract protected function setTheme(FormView $view, array $themes); public function testEnctype() { $form = $this->factory->createNamedBuilder('name', 'form') ->add('file', 'file') ->getForm(); $this->assertEquals('enctype="multipart/form-data"', $this->renderEnctype($form->createView())); } public function testNoEnctype() { $form = $this->factory->createNamedBuilder('name', 'form') ->add('text', 'text') ->getForm(); $this->assertEquals('', $this->renderEnctype($form->createView())); } public function testLabel() { $form = $this->factory->createNamed('name', 'text'); $view = $form->createView(); $this->renderWidget($view, array('label' => 'foo')); $html = $this->renderLabel($view); $this->assertMatchesXpath($html, '/label [@for="name"] [.="[trans]Name[/trans]"] ' ); } public function testLabelOnForm() { $form = $this->factory->createNamed('name', 'date'); $view = $form->createView(); $this->renderWidget($view, array('label' => 'foo')); $html = $this->renderLabel($view); $this->assertMatchesXpath($html, '/label [@class="required"] [.="[trans]Name[/trans]"] ' ); } public function testLabelWithCustomTextPassedAsOption() { $form = $this->factory->createNamed('name', 'text', null, array( 'label' => 'Custom label', )); $html = $this->renderLabel($form->createView()); $this->assertMatchesXpath($html, '/label [@for="name"] [.="[trans]Custom label[/trans]"] ' ); } public function testLabelWithCustomTextPassedDirectly() { $form = $this->factory->createNamed('name', 'text'); $html = $this->renderLabel($form->createView(), 'Custom label'); $this->assertMatchesXpath($html, '/label [@for="name"] [.="[trans]Custom label[/trans]"] ' ); } public function testLabelWithCustomTextPassedAsOptionAndDirectly() { $form = $this->factory->createNamed('name', 'text', null, array( 'label' => 'Custom label', )); $html = $this->renderLabel($form->createView(), 'Overridden label'); $this->assertMatchesXpath($html, '/label [@for="name"] [.="[trans]Overridden label[/trans]"] ' ); } public function testLabelDoesNotRenderFieldAttributes() { $form = $this->factory->createNamed('name', 'text'); $html = $this->renderLabel($form->createView(), null, array( 'attr' => array( 'class' => 'my&class' ), )); $this->assertMatchesXpath($html, '/label [@for="name"] [@class="required"] ' ); } public function testLabelWithCustomAttributesPassedDirectly() { $form = $this->factory->createNamed('name', 'text'); $html = $this->renderLabel($form->createView(), null, array( 'label_attr' => array( 'class' => 'my&class' ), )); $this->assertMatchesXpath($html, '/label [@for="name"] [@class="my&class required"] ' ); } public function testLabelWithCustomTextAndCustomAttributesPassedDirectly() { $form = $this->factory->createNamed('name', 'text'); $html = $this->renderLabel($form->createView(), 'Custom label', array( 'label_attr' => array( 'class' => 'my&class' ), )); $this->assertMatchesXpath($html, '/label [@for="name"] [@class="my&class required"] [.="[trans]Custom label[/trans]"] ' ); } // https://github.com/symfony/symfony/issues/5029 public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly() { $form = $this->factory->createNamed('name', 'text', null, array( 'label' => 'Custom label', )); $html = $this->renderLabel($form->createView(), null, array( 'label_attr' => array( 'class' => 'my&class' ), )); $this->assertMatchesXpath($html, '/label [@for="name"] [@class="my&class required"] [.="[trans]Custom label[/trans]"] ' ); } public function testErrors() { $form = $this->factory->createNamed('name', 'text'); $form->addError(new FormError('[trans]Error 1[/trans]')); $form->addError(new FormError('[trans]Error 2[/trans]')); $view = $form->createView(); $html = $this->renderErrors($view); $this->assertMatchesXpath($html, '/ul [ ./li[.="[trans]Error 1[/trans]"] /following-sibling::li[.="[trans]Error 2[/trans]"] ] [count(./li)=2] ' ); } public function testOverrideWidgetBlock() { // see custom_widgets.html.twig $form = $this->factory->createNamed('text_id', 'text'); $html = $this->renderWidget($form->createView()); $this->assertMatchesXpath($html, '/div [ ./input [@type="text"] [@id="text_id"] ] [@id="container"] ' ); } public function testCheckedCheckbox() { $form = $this->factory->createNamed('name', 'checkbox', true); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="checkbox"] [@name="name"] [@checked="checked"] [@value="1"] ' ); } public function testUncheckedCheckbox() { $form = $this->factory->createNamed('name', 'checkbox', false); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="checkbox"] [@name="name"] [not(@checked)] ' ); } public function testCheckboxWithValue() { $form = $this->factory->createNamed('name', 'checkbox', false, array( 'value' => 'foo&bar', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="checkbox"] [@name="name"] [@value="foo&bar"] ' ); } public function testSingleChoice() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'multiple' => false, 'expanded' => false, )); // If the field is collapsed, has no "multiple" attribute, is required but // has *no* empty value, the "required" must not be added, otherwise // the resulting HTML is invalid. // https://github.com/symfony/symfony/issues/8942 // HTML 5 spec // http://www.w3.org/html/wg/drafts/html/master/forms.html#placeholder-label-option // "If a select element has a required attribute specified, does not // have a multiple attribute specified, and has a display size of 1, // then the select element must have a placeholder label option." $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [not(@required)] [ ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=2] ' ); } public function testSingleChoiceWithPreferred() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'preferred_choices' => array('&b'), 'multiple' => false, 'expanded' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array('separator' => '-- sep --'), '/select [@name="name"] [not(@required)] [ ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] /following-sibling::option[@disabled="disabled"][not(@selected)][.="-- sep --"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] ] [count(./option)=3] ' ); } public function testSingleChoiceWithPreferredAndNoSeparator() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'preferred_choices' => array('&b'), 'multiple' => false, 'expanded' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array('separator' => null), '/select [@name="name"] [not(@required)] [ ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] ] [count(./option)=2] ' ); } public function testSingleChoiceWithPreferredAndBlankSeparator() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'preferred_choices' => array('&b'), 'multiple' => false, 'expanded' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array('separator' => ''), '/select [@name="name"] [not(@required)] [ ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] /following-sibling::option[@disabled="disabled"][not(@selected)][.=""] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] ] [count(./option)=3] ' ); } public function testChoiceWithOnlyPreferred() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'preferred_choices' => array('&a', '&b'), 'multiple' => false, 'expanded' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [count(./option)=2] ' ); } public function testSingleChoiceNonRequired() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'required' => false, 'multiple' => false, 'expanded' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [not(@required)] [ ./option[@value=""][.="[trans][/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=3] ' ); } public function testSingleChoiceNonRequiredNoneSelected() { $form = $this->factory->createNamed('name', 'choice', null, array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'required' => false, 'multiple' => false, 'expanded' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [not(@required)] [ ./option[@value=""][.="[trans][/trans]"] /following-sibling::option[@value="&a"][not(@selected)][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=3] ' ); } public function testSingleChoiceWithNonRequiredEmptyValue() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'multiple' => false, 'expanded' => false, 'required' => false, 'empty_value' => 'Select&Anything&Not&Me', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [not(@required)] [ ./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Anything&Not&Me[/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=3] ' ); } public function testSingleChoiceRequiredWithEmptyValue() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'required' => true, 'multiple' => false, 'expanded' => false, 'empty_value' => 'Test&Me' )); // The "disabled" attribute was removed again due to a bug in the // BlackBerry 10 browser. // See https://github.com/symfony/symfony/pull/7678 $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [@required="required"] [ ./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Test&Me[/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=3] ' ); } public function testSingleChoiceRequiredWithEmptyValueViaView() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'required' => true, 'multiple' => false, 'expanded' => false, )); // The "disabled" attribute was removed again due to a bug in the // BlackBerry 10 browser. // See https://github.com/symfony/symfony/pull/7678 $this->assertWidgetMatchesXpath($form->createView(), array('empty_value' => ''), '/select [@name="name"] [@required="required"] [ ./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=3] ' ); } public function testSingleChoiceGrouped() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array( 'Group&1' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'Group&2' => array('&c' => 'Choice&C'), ), 'multiple' => false, 'expanded' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [./optgroup[@label="[trans]Group&1[/trans]"] [ ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=2] ] [./optgroup[@label="[trans]Group&2[/trans]"] [./option[@value="&c"][not(@selected)][.="[trans]Choice&C[/trans]"]] [count(./option)=1] ] [count(./optgroup)=2] ' ); } public function testMultipleChoice() { $form = $this->factory->createNamed('name', 'choice', array('&a'), array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'required' => true, 'multiple' => true, 'expanded' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name[]"] [@required="required"] [@multiple="multiple"] [ ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=2] ' ); } public function testMultipleChoiceSkipsEmptyValue() { $form = $this->factory->createNamed('name', 'choice', array('&a'), array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'multiple' => true, 'expanded' => false, 'empty_value' => 'Test&Me' )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name[]"] [@multiple="multiple"] [ ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=2] ' ); } public function testMultipleChoiceNonRequired() { $form = $this->factory->createNamed('name', 'choice', array('&a'), array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'required' => false, 'multiple' => true, 'expanded' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name[]"] [@multiple="multiple"] [ ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] [count(./option)=2] ' ); } public function testSingleChoiceExpanded() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'multiple' => false, 'expanded' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] /following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"] /following-sibling::input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] /following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"] /following-sibling::input[@type="hidden"][@id="name__token"] ] [count(./input)=3] ' ); } public function testSingleChoiceExpandedWithEmptyValue() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'multiple' => false, 'expanded' => true, 'empty_value' => 'Test&Me' )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./input[@type="radio"][@name="name"][@id="name_placeholder"][not(@checked)] /following-sibling::label[@for="name_placeholder"][.="[trans]Test&Me[/trans]"] /following-sibling::input[@type="radio"][@name="name"][@id="name_0"][@checked] /following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"] /following-sibling::input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] /following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"] /following-sibling::input[@type="hidden"][@id="name__token"] ] [count(./input)=4] ' ); } public function testSingleChoiceExpandedWithBooleanValue() { $form = $this->factory->createNamed('name', 'choice', true, array( 'choices' => array('1' => 'Choice&A', '0' => 'Choice&B'), 'multiple' => false, 'expanded' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./input[@type="radio"][@name="name"][@id="name_0"][@checked] /following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"] /following-sibling::input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] /following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"] /following-sibling::input[@type="hidden"][@id="name__token"] ] [count(./input)=3] ' ); } public function testMultipleChoiceExpanded() { $form = $this->factory->createNamed('name', 'choice', array('&a', '&c'), array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B', '&c' => 'Choice&C'), 'multiple' => true, 'expanded' => true, 'required' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)] /following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"] /following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)] /following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"] /following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)] /following-sibling::label[@for="name_2"][.="[trans]Choice&C[/trans]"] /following-sibling::input[@type="hidden"][@id="name__token"] ] [count(./input)=4] ' ); } public function testCountry() { $form = $this->factory->createNamed('name', 'country', 'AT'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [./option[@value="AT"][@selected="selected"][.="[trans]Austria[/trans]"]] [count(./option)>200] ' ); } public function testCountryWithEmptyValue() { $form = $this->factory->createNamed('name', 'country', 'AT', array( 'empty_value' => 'Select&Country', 'required' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Country[/trans]"]] [./option[@value="AT"][@selected="selected"][.="[trans]Austria[/trans]"]] [count(./option)>201] ' ); } public function testDateTime() { $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( 'input' => 'string', 'with_seconds' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@id="name_date"] [ ./select [@id="name_date_month"] [./option[@value="2"][@selected="selected"]] /following-sibling::select [@id="name_date_day"] [./option[@value="3"][@selected="selected"]] /following-sibling::select [@id="name_date_year"] [./option[@value="2011"][@selected="selected"]] ] /following-sibling::div [@id="name_time"] [ ./select [@id="name_time_hour"] [./option[@value="4"][@selected="selected"]] /following-sibling::select [@id="name_time_minute"] [./option[@value="5"][@selected="selected"]] ] ] [count(.//select)=5] ' ); } public function testDateTimeWithEmptyValueGlobal() { $form = $this->factory->createNamed('name', 'datetime', null, array( 'input' => 'string', 'empty_value' => 'Change&Me', 'required' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@id="name_date"] [ ./select [@id="name_date_month"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_date_day"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_date_year"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] ] /following-sibling::div [@id="name_time"] [ ./select [@id="name_time_hour"] [./option[@value=""][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_time_minute"] [./option[@value=""][.="[trans]Change&Me[/trans]"]] ] ] [count(.//select)=5] ' ); } public function testDateTimeWithHourAndMinute() { $data = array('year' => '2011', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5'); $form = $this->factory->createNamed('name', 'datetime', $data, array( 'input' => 'array', 'required' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@id="name_date"] [ ./select [@id="name_date_month"] [./option[@value="2"][@selected="selected"]] /following-sibling::select [@id="name_date_day"] [./option[@value="3"][@selected="selected"]] /following-sibling::select [@id="name_date_year"] [./option[@value="2011"][@selected="selected"]] ] /following-sibling::div [@id="name_time"] [ ./select [@id="name_time_hour"] [./option[@value="4"][@selected="selected"]] /following-sibling::select [@id="name_time_minute"] [./option[@value="5"][@selected="selected"]] ] ] [count(.//select)=5] ' ); } public function testDateTimeWithSeconds() { $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( 'input' => 'string', 'with_seconds' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./div [@id="name_date"] [ ./select [@id="name_date_month"] [./option[@value="2"][@selected="selected"]] /following-sibling::select [@id="name_date_day"] [./option[@value="3"][@selected="selected"]] /following-sibling::select [@id="name_date_year"] [./option[@value="2011"][@selected="selected"]] ] /following-sibling::div [@id="name_time"] [ ./select [@id="name_time_hour"] [./option[@value="4"][@selected="selected"]] /following-sibling::select [@id="name_time_minute"] [./option[@value="5"][@selected="selected"]] /following-sibling::select [@id="name_time_second"] [./option[@value="6"][@selected="selected"]] ] ] [count(.//select)=6] ' ); } public function testDateTimeSingleText() { $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( 'input' => 'string', 'date_widget' => 'single_text', 'time_widget' => 'single_text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./input [@type="date"] [@id="name_date"] [@name="name[date]"] [@value="2011-02-03"] /following-sibling::input [@type="time"] [@id="name_time"] [@name="name[time]"] [@value="04:05"] ] ' ); } public function testDateTimeWithWidgetSingleText() { $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( 'input' => 'string', 'widget' => 'single_text', 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="datetime"] [@name="name"] [@value="2011-02-03T04:05:06Z"] ' ); } public function testDateTimeWithWidgetSingleTextIgnoreDateAndTimeWidgets() { $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( 'input' => 'string', 'date_widget' => 'choice', 'time_widget' => 'choice', 'widget' => 'single_text', 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="datetime"] [@name="name"] [@value="2011-02-03T04:05:06Z"] ' ); } public function testDateChoice() { $form = $this->factory->createNamed('name', 'date', '2011-02-03', array( 'input' => 'string', 'widget' => 'choice', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./select [@id="name_month"] [./option[@value="2"][@selected="selected"]] /following-sibling::select [@id="name_day"] [./option[@value="3"][@selected="selected"]] /following-sibling::select [@id="name_year"] [./option[@value="2011"][@selected="selected"]] ] [count(./select)=3] ' ); } public function testDateChoiceWithEmptyValueGlobal() { $form = $this->factory->createNamed('name', 'date', null, array( 'input' => 'string', 'widget' => 'choice', 'empty_value' => 'Change&Me', 'required' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./select [@id="name_month"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_day"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_year"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] ] [count(./select)=3] ' ); } public function testDateChoiceWithEmptyValueOnYear() { $form = $this->factory->createNamed('name', 'date', null, array( 'input' => 'string', 'widget' => 'choice', 'required' => false, 'empty_value' => array('year' => 'Change&Me'), )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./select [@id="name_month"] [./option[@value="1"]] /following-sibling::select [@id="name_day"] [./option[@value="1"]] /following-sibling::select [@id="name_year"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] ] [count(./select)=3] ' ); } public function testDateText() { $form = $this->factory->createNamed('name', 'date', '2011-02-03', array( 'input' => 'string', 'widget' => 'text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./input [@id="name_month"] [@type="text"] [@value="2"] /following-sibling::input [@id="name_day"] [@type="text"] [@value="3"] /following-sibling::input [@id="name_year"] [@type="text"] [@value="2011"] ] [count(./input)=3] ' ); } public function testDateSingleText() { $form = $this->factory->createNamed('name', 'date', '2011-02-03', array( 'input' => 'string', 'widget' => 'single_text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="date"] [@name="name"] [@value="2011-02-03"] ' ); } public function testDateErrorBubbling() { $form = $this->factory->createNamedBuilder('form', 'form') ->add('date', 'date') ->getForm(); $form->get('date')->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $this->assertEmpty($this->renderErrors($view)); $this->assertNotEmpty($this->renderErrors($view['date'])); } public function testBirthDay() { $form = $this->factory->createNamed('name', 'birthday', '2000-02-03', array( 'input' => 'string', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./select [@id="name_month"] [./option[@value="2"][@selected="selected"]] /following-sibling::select [@id="name_day"] [./option[@value="3"][@selected="selected"]] /following-sibling::select [@id="name_year"] [./option[@value="2000"][@selected="selected"]] ] [count(./select)=3] ' ); } public function testBirthDayWithEmptyValue() { $form = $this->factory->createNamed('name', 'birthday', '1950-01-01', array( 'input' => 'string', 'empty_value' => '', 'required' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./select [@id="name_month"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]] [./option[@value="1"][@selected="selected"]] /following-sibling::select [@id="name_day"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]] [./option[@value="1"][@selected="selected"]] /following-sibling::select [@id="name_year"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]] [./option[@value="1950"][@selected="selected"]] ] [count(./select)=3] ' ); } public function testEmail() { $form = $this->factory->createNamed('name', 'email', 'foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="email"] [@name="name"] [@value="foo&bar"] [not(@maxlength)] ' ); } public function testEmailWithMaxLength() { $form = $this->factory->createNamed('name', 'email', 'foo&bar', array( 'max_length' => 123, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="email"] [@name="name"] [@value="foo&bar"] [@maxlength="123"] ' ); } public function testFile() { $form = $this->factory->createNamed('name', 'file'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="file"] ' ); } public function testHidden() { $form = $this->factory->createNamed('name', 'hidden', 'foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="hidden"] [@name="name"] [@value="foo&bar"] ' ); } public function testReadOnly() { $form = $this->factory->createNamed('name', 'text', null, array( 'read_only' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="text"] [@name="name"] [@readonly="readonly"] ' ); } public function testDisabled() { $form = $this->factory->createNamed('name', 'text', null, array( 'disabled' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="text"] [@name="name"] [@disabled="disabled"] ' ); } public function testInteger() { $form = $this->factory->createNamed('name', 'integer', 123); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="number"] [@name="name"] [@value="123"] ' ); } public function testLanguage() { $form = $this->factory->createNamed('name', 'language', 'de'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [./option[@value="de"][@selected="selected"][.="[trans]German[/trans]"]] [count(./option)>200] ' ); } public function testLocale() { $form = $this->factory->createNamed('name', 'locale', 'de_AT'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [./option[@value="de_AT"][@selected="selected"][.="[trans]German (Austria)[/trans]"]] [count(./option)>200] ' ); } public function testMoney() { $form = $this->factory->createNamed('name', 'money', 1234.56, array( 'currency' => 'EUR', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="text"] [@name="name"] [@value="1234.56"] [contains(.., "€")] ' ); } public function testNumber() { $form = $this->factory->createNamed('name', 'number', 1234.56); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="text"] [@name="name"] [@value="1234.56"] ' ); } public function testPassword() { $form = $this->factory->createNamed('name', 'password', 'foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="password"] [@name="name"] ' ); } public function testPasswordSubmittedWithNotAlwaysEmpty() { $form = $this->factory->createNamed('name', 'password', null, array( 'always_empty' => false, )); $form->submit('foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="password"] [@name="name"] [@value="foo&bar"] ' ); } public function testPasswordWithMaxLength() { $form = $this->factory->createNamed('name', 'password', 'foo&bar', array( 'max_length' => 123, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="password"] [@name="name"] [@maxlength="123"] ' ); } public function testPercent() { $form = $this->factory->createNamed('name', 'percent', 0.1); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="text"] [@name="name"] [@value="10"] [contains(.., "%")] ' ); } public function testCheckedRadio() { $form = $this->factory->createNamed('name', 'radio', true); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="radio"] [@name="name"] [@checked="checked"] [@value="1"] ' ); } public function testUncheckedRadio() { $form = $this->factory->createNamed('name', 'radio', false); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="radio"] [@name="name"] [not(@checked)] ' ); } public function testRadioWithValue() { $form = $this->factory->createNamed('name', 'radio', false, array( 'value' => 'foo&bar', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="radio"] [@name="name"] [@value="foo&bar"] ' ); } public function testTextarea() { $form = $this->factory->createNamed('name', 'textarea', 'foo&bar', array( 'pattern' => 'foo', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/textarea [@name="name"] [not(@pattern)] [.="foo&bar"] ' ); } public function testText() { $form = $this->factory->createNamed('name', 'text', 'foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="text"] [@name="name"] [@value="foo&bar"] [not(@maxlength)] ' ); } public function testTextWithMaxLength() { $form = $this->factory->createNamed('name', 'text', 'foo&bar', array( 'max_length' => 123, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="text"] [@name="name"] [@value="foo&bar"] [@maxlength="123"] ' ); } public function testSearch() { $form = $this->factory->createNamed('name', 'search', 'foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="search"] [@name="name"] [@value="foo&bar"] [not(@maxlength)] ' ); } public function testTime() { $form = $this->factory->createNamed('name', 'time', '04:05:06', array( 'input' => 'string', 'with_seconds' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./select [@id="name_hour"] [not(@size)] [./option[@value="4"][@selected="selected"]] /following-sibling::select [@id="name_minute"] [not(@size)] [./option[@value="5"][@selected="selected"]] ] [count(./select)=2] ' ); } public function testTimeWithSeconds() { $form = $this->factory->createNamed('name', 'time', '04:05:06', array( 'input' => 'string', 'with_seconds' => true, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./select [@id="name_hour"] [not(@size)] [./option[@value="4"][@selected="selected"]] [count(./option)>23] /following-sibling::select [@id="name_minute"] [not(@size)] [./option[@value="5"][@selected="selected"]] [count(./option)>59] /following-sibling::select [@id="name_second"] [not(@size)] [./option[@value="6"][@selected="selected"]] [count(./option)>59] ] [count(./select)=3] ' ); } public function testTimeText() { $form = $this->factory->createNamed('name', 'time', '04:05:06', array( 'input' => 'string', 'widget' => 'text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./input [@type="text"] [@id="name_hour"] [@name="name[hour]"] [@value="04"] [@size="1"] [@required="required"] /following-sibling::input [@type="text"] [@id="name_minute"] [@name="name[minute]"] [@value="05"] [@size="1"] [@required="required"] ] [count(./input)=2] ' ); } public function testTimeSingleText() { $form = $this->factory->createNamed('name', 'time', '04:05:06', array( 'input' => 'string', 'widget' => 'single_text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="time"] [@name="name"] [@value="04:05"] [not(@size)] ' ); } public function testTimeWithEmptyValueGlobal() { $form = $this->factory->createNamed('name', 'time', null, array( 'input' => 'string', 'empty_value' => 'Change&Me', 'required' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./select [@id="name_hour"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] [count(./option)>24] /following-sibling::select [@id="name_minute"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] [count(./option)>60] ] [count(./select)=2] ' ); } public function testTimeWithEmptyValueOnYear() { $form = $this->factory->createNamed('name', 'time', null, array( 'input' => 'string', 'required' => false, 'empty_value' => array('hour' => 'Change&Me'), )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ ./select [@id="name_hour"] [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] [count(./option)>24] /following-sibling::select [@id="name_minute"] [./option[@value="1"]] [count(./option)>59] ] [count(./select)=2] ' ); } public function testTimeErrorBubbling() { $form = $this->factory->createNamedBuilder('form', 'form') ->add('time', 'time') ->getForm(); $form->get('time')->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $this->assertEmpty($this->renderErrors($view)); $this->assertNotEmpty($this->renderErrors($view['time'])); } public function testTimezone() { $form = $this->factory->createNamed('name', 'timezone', 'Europe/Vienna'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [not(@required)] [./optgroup [@label="[trans]Europe[/trans]"] [./option[@value="Europe/Vienna"][@selected="selected"][.="[trans]Vienna[/trans]"]] ] [count(./optgroup)>10] [count(.//option)>200] ' ); } public function testTimezoneWithEmptyValue() { $form = $this->factory->createNamed('name', 'timezone', null, array( 'empty_value' => 'Select&Timezone', 'required' => false, )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Timezone[/trans]"]] [count(./optgroup)>10] [count(.//option)>201] ' ); } public function testUrl() { $url = 'http://www.google.com?foo1=bar1&foo2=bar2'; $form = $this->factory->createNamed('name', 'url', $url); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input [@type="url"] [@name="name"] [@value="http://www.google.com?foo1=bar1&foo2=bar2"] ' ); } public function testCollectionPrototype() { $form = $this->factory->createNamedBuilder('name', 'form', array('items' => array('one', 'two', 'three'))) ->add('items', 'collection', array('allow_add' => true)) ->getForm() ->createView(); $html = $this->renderWidget($form); $this->assertMatchesXpath($html, '//div[@id="name_items"][@data-prototype] | //table[@id="name_items"][@data-prototype]' ); } public function testEmptyRootFormName() { $form = $this->factory->createNamedBuilder('', 'form') ->add('child', 'text') ->getForm(); $this->assertMatchesXpath($this->renderWidget($form->createView()), '//input[@type="hidden"][@id="_token"][@name="_token"] | //input[@type="text"][@id="child"][@name="child"]' , 2); } public function testButton() { $form = $this->factory->createNamed('name', 'button'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/button[@type="button"][@name="name"][.="[trans]Name[/trans]"]' ); } public function testButtonLabelIsEmpty() { $form = $this->factory->createNamed('name', 'button'); $this->assertSame('', $this->renderLabel($form->createView())); } public function testSubmit() { $form = $this->factory->createNamed('name', 'submit'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/button[@type="submit"][@name="name"]' ); } public function testReset() { $form = $this->factory->createNamed('name', 'reset'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/button[@type="reset"][@name="name"]' ); } public function testStartTag() { $form = $this->factory->create('form', null, array( 'method' => 'get', 'action' => 'http://example.com/directory' )); $html = $this->renderStart($form->createView()); $this->assertSame('
', $html); } public function testStartTagForPutRequest() { $form = $this->factory->create('form', null, array( 'method' => 'put', 'action' => 'http://example.com/directory' )); $html = $this->renderStart($form->createView()); $this->assertMatchesXpath($html . '', '/form [./input[@type="hidden"][@name="_method"][@value="PUT"]] [@method="post"] [@action="http://example.com/directory"]' ); } public function testStartTagWithOverriddenVars() { $form = $this->factory->create('form', null, array( 'method' => 'put', 'action' => 'http://example.com/directory', )); $html = $this->renderStart($form->createView(), array( 'method' => 'post', 'action' => 'http://foo.com/directory' )); $this->assertSame('
', $html); } public function testStartTagForMultipartForm() { $form = $this->factory->createBuilder('form', null, array( 'method' => 'get', 'action' => 'http://example.com/directory' )) ->add('file', 'file') ->getForm(); $html = $this->renderStart($form->createView()); $this->assertSame('', $html); } public function testStartTagWithExtraAttributes() { $form = $this->factory->create('form', null, array( 'method' => 'get', 'action' => 'http://example.com/directory' )); $html = $this->renderStart($form->createView(), array( 'attr' => array('class' => 'foobar'), )); $this->assertSame('', $html); } public function testWidgetAttributes() { $form = $this->factory->createNamed('text', 'text', 'value', array( 'required' => true, 'disabled' => true, 'read_only' => true, 'max_length' => 10, 'pattern' => '\d+', 'attr' => array('class' => 'foobar', 'data-foo' => 'bar'), )); $html = $this->renderWidget($form->createView()); // compare plain HTML to check the whitespace $this->assertSame('', $html); } public function testWidgetAttributeNameRepeatedIfTrue() { $form = $this->factory->createNamed('text', 'text', 'value', array( 'attr' => array('foo' => true), )); $html = $this->renderWidget($form->createView()); // foo="foo" $this->assertSame('', $html); } public function testWidgetAttributeHiddenIfFalse() { $form = $this->factory->createNamed('text', 'text', 'value', array( 'attr' => array('foo' => false), )); $html = $this->renderWidget($form->createView()); // no foo $this->assertSame('', $html); } public function testButtonAttributes() { $form = $this->factory->createNamed('button', 'button', null, array( 'disabled' => true, 'attr' => array('class' => 'foobar', 'data-foo' => 'bar'), )); $html = $this->renderWidget($form->createView()); // compare plain HTML to check the whitespace $this->assertSame('', $html); } public function testButtonAttributeNameRepeatedIfTrue() { $form = $this->factory->createNamed('button', 'button', null, array( 'attr' => array('foo' => true), )); $html = $this->renderWidget($form->createView()); // foo="foo" $this->assertSame('', $html); } public function testButtonAttributeHiddenIfFalse() { $form = $this->factory->createNamed('button', 'button', null, array( 'attr' => array('foo' => false), )); $html = $this->renderWidget($form->createView()); // no foo $this->assertSame('', $html); } } Symfony/Component/Form/Tests/FormIntegrationTestCase.php000064400000001113152374770060017442 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\Test\FormIntegrationTestCase as BaseFormIntegrationTestCase; /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use Symfony\Component\Form\Test\FormIntegrationTestCase instead. */ abstract class FormIntegrationTestCase extends BaseFormIntegrationTestCase { } Symfony/Component/Form/Tests/ResolvedFormTypeTest.php000064400000031024152374770060017014 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\ResolvedFormType; use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\Form; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * @author Bernhard Schussek */ class ResolvedFormTypeTest extends \PHPUnit_Framework_TestCase { /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dispatcher; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $factory; /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $dataMapper; private $parentType; private $type; private $extension1; private $extension2; private $parentResolvedType; private $resolvedType; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->dataMapper = $this->getMock('Symfony\Component\Form\DataMapperInterface'); $this->parentType = $this->getMockFormType(); $this->type = $this->getMockFormType(); $this->extension1 = $this->getMockFormTypeExtension(); $this->extension2 = $this->getMockFormTypeExtension(); $this->parentResolvedType = new ResolvedFormType($this->parentType); $this->resolvedType = new ResolvedFormType($this->type, array($this->extension1, $this->extension2), $this->parentResolvedType); } public function testGetOptionsResolver() { if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) { $this->markTestSkipped('This test requires PHPUnit 3.7.'); } $test = $this; $i = 0; $assertIndexAndAddOption = function ($index, $option, $default) use (&$i, $test) { return function (OptionsResolverInterface $resolver) use (&$i, $test, $index, $option, $default) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertEquals($index, $i, 'Executed at index '.$index); ++$i; $resolver->setDefaults(array($option => $default)); }; }; // First the default options are generated for the super type $this->parentType->expects($this->once()) ->method('setDefaultOptions') ->will($this->returnCallback($assertIndexAndAddOption(0, 'a', 'a_default'))); // The form type itself $this->type->expects($this->once()) ->method('setDefaultOptions') ->will($this->returnCallback($assertIndexAndAddOption(1, 'b', 'b_default'))); // And its extensions $this->extension1->expects($this->once()) ->method('setDefaultOptions') ->will($this->returnCallback($assertIndexAndAddOption(2, 'c', 'c_default'))); $this->extension2->expects($this->once()) ->method('setDefaultOptions') ->will($this->returnCallback($assertIndexAndAddOption(3, 'd', 'd_default'))); $givenOptions = array('a' => 'a_custom', 'c' => 'c_custom'); $resolvedOptions = array('a' => 'a_custom', 'b' => 'b_default', 'c' => 'c_custom', 'd' => 'd_default'); $resolver = $this->resolvedType->getOptionsResolver(); $this->assertEquals($resolvedOptions, $resolver->resolve($givenOptions)); } public function testCreateBuilder() { if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) { $this->markTestSkipped('This test requires PHPUnit 3.7.'); } $givenOptions = array('a' => 'a_custom', 'c' => 'c_custom'); $resolvedOptions = array('a' => 'a_custom', 'b' => 'b_default', 'c' => 'c_custom', 'd' => 'd_default'); $optionsResolver = $this->getMock('Symfony\Component\OptionsResolver\OptionsResolverInterface'); $this->resolvedType = $this->getMockBuilder('Symfony\Component\Form\ResolvedFormType') ->setConstructorArgs(array($this->type, array($this->extension1, $this->extension2), $this->parentResolvedType)) ->setMethods(array('getOptionsResolver')) ->getMock(); $this->resolvedType->expects($this->once()) ->method('getOptionsResolver') ->will($this->returnValue($optionsResolver)); $optionsResolver->expects($this->once()) ->method('resolve') ->with($givenOptions) ->will($this->returnValue($resolvedOptions)); $factory = $this->getMockFormFactory(); $builder = $this->resolvedType->createBuilder($factory, 'name', $givenOptions); $this->assertSame($this->resolvedType, $builder->getType()); $this->assertSame($resolvedOptions, $builder->getOptions()); $this->assertNull($builder->getDataClass()); } public function testCreateBuilderWithDataClassOption() { if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) { $this->markTestSkipped('This test requires PHPUnit 3.7.'); } $givenOptions = array('data_class' => 'Foo'); $resolvedOptions = array('data_class' => '\stdClass'); $optionsResolver = $this->getMock('Symfony\Component\OptionsResolver\OptionsResolverInterface'); $this->resolvedType = $this->getMockBuilder('Symfony\Component\Form\ResolvedFormType') ->setConstructorArgs(array($this->type, array($this->extension1, $this->extension2), $this->parentResolvedType)) ->setMethods(array('getOptionsResolver')) ->getMock(); $this->resolvedType->expects($this->once()) ->method('getOptionsResolver') ->will($this->returnValue($optionsResolver)); $optionsResolver->expects($this->once()) ->method('resolve') ->with($givenOptions) ->will($this->returnValue($resolvedOptions)); $factory = $this->getMockFormFactory(); $builder = $this->resolvedType->createBuilder($factory, 'name', $givenOptions); $this->assertSame($this->resolvedType, $builder->getType()); $this->assertSame($resolvedOptions, $builder->getOptions()); $this->assertSame('\stdClass', $builder->getDataClass()); } public function testBuildForm() { if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) { $this->markTestSkipped('This test requires PHPUnit 3.7.'); } $test = $this; $i = 0; $assertIndex = function ($index) use (&$i, $test) { return function () use (&$i, $test, $index) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertEquals($index, $i, 'Executed at index '.$index); ++$i; }; }; $options = array('a' => 'Foo', 'b' => 'Bar'); $builder = $this->getMock('Symfony\Component\Form\Test\FormBuilderInterface'); // First the form is built for the super type $this->parentType->expects($this->once()) ->method('buildForm') ->with($builder, $options) ->will($this->returnCallback($assertIndex(0))); // Then the type itself $this->type->expects($this->once()) ->method('buildForm') ->with($builder, $options) ->will($this->returnCallback($assertIndex(1))); // Then its extensions $this->extension1->expects($this->once()) ->method('buildForm') ->with($builder, $options) ->will($this->returnCallback($assertIndex(2))); $this->extension2->expects($this->once()) ->method('buildForm') ->with($builder, $options) ->will($this->returnCallback($assertIndex(3))); $this->resolvedType->buildForm($builder, $options); } public function testCreateView() { $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $view = $this->resolvedType->createView($form); $this->assertInstanceOf('Symfony\Component\Form\FormView', $view); $this->assertNull($view->parent); } public function testCreateViewWithParent() { $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $parentView = $this->getMock('Symfony\Component\Form\FormView'); $view = $this->resolvedType->createView($form, $parentView); $this->assertInstanceOf('Symfony\Component\Form\FormView', $view); $this->assertSame($parentView, $view->parent); } public function testBuildView() { $options = array('a' => '1', 'b' => '2'); $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $view = $this->getMock('Symfony\Component\Form\FormView'); $test = $this; $i = 0; $assertIndex = function ($index) use (&$i, $test) { return function () use (&$i, $test, $index) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertEquals($index, $i, 'Executed at index '.$index); ++$i; }; }; // First the super type $this->parentType->expects($this->once()) ->method('buildView') ->with($view, $form, $options) ->will($this->returnCallback($assertIndex(0))); // Then the type itself $this->type->expects($this->once()) ->method('buildView') ->with($view, $form, $options) ->will($this->returnCallback($assertIndex(1))); // Then its extensions $this->extension1->expects($this->once()) ->method('buildView') ->with($view, $form, $options) ->will($this->returnCallback($assertIndex(2))); $this->extension2->expects($this->once()) ->method('buildView') ->with($view, $form, $options) ->will($this->returnCallback($assertIndex(3))); $this->resolvedType->buildView($view, $form, $options); } public function testFinishView() { $options = array('a' => '1', 'b' => '2'); $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $view = $this->getMock('Symfony\Component\Form\FormView'); $test = $this; $i = 0; $assertIndex = function ($index) use (&$i, $test) { return function () use (&$i, $test, $index) { /* @var \PHPUnit_Framework_TestCase $test */ $test->assertEquals($index, $i, 'Executed at index '.$index); ++$i; }; }; // First the super type $this->parentType->expects($this->once()) ->method('finishView') ->with($view, $form, $options) ->will($this->returnCallback($assertIndex(0))); // Then the type itself $this->type->expects($this->once()) ->method('finishView') ->with($view, $form, $options) ->will($this->returnCallback($assertIndex(1))); // Then its extensions $this->extension1->expects($this->once()) ->method('finishView') ->with($view, $form, $options) ->will($this->returnCallback($assertIndex(2))); $this->extension2->expects($this->once()) ->method('finishView') ->with($view, $form, $options) ->will($this->returnCallback($assertIndex(3))); $this->resolvedType->finishView($view, $form, $options); } /** * @return \PHPUnit_Framework_MockObject_MockObject */ private function getMockFormType() { return $this->getMock('Symfony\Component\Form\FormTypeInterface'); } /** * @return \PHPUnit_Framework_MockObject_MockObject */ private function getMockFormTypeExtension() { return $this->getMock('Symfony\Component\Form\FormTypeExtensionInterface'); } /** * @return \PHPUnit_Framework_MockObject_MockObject */ private function getMockFormFactory() { return $this->getMock('Symfony\Component\Form\FormFactoryInterface'); } /** * @param string $name * @param array $options * * @return FormBuilder */ protected function getBuilder($name = 'name', array $options = array()) { return new FormBuilder($name, null, $this->dispatcher, $this->factory, $options); } } Symfony/Component/Form/Tests/FormPerformanceTestCase.php000064400000001113152374770060017420 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\Test\FormPerformanceTestCase as BaseFormPerformanceTestCase; /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use Symfony\Component\Form\Test\FormPerformanceTestCase instead. */ abstract class FormPerformanceTestCase extends BaseFormPerformanceTestCase { } Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php000064400000016542152374770060020165 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Form\Tests; /** * @author Bernhard Schussek */ abstract class AbstractRequestHandlerTest extends \PHPUnit_Framework_TestCase { /** * @var \Symfony\Component\Form\RequestHandlerInterface */ protected $requestHandler; protected $request; protected function setUp() { $this->requestHandler = $this->getRequestHandler(); $this->request = null; } public function methodExceptGetProvider() { return array( array('POST'), array('PUT'), array('DELETE'), array('PATCH'), ); } public function methodProvider() { return array_merge(array( array('GET'), ), $this->methodExceptGetProvider()); } /** * @dataProvider methodProvider */ public function testSubmitIfNameInRequest($method) { $form = $this->getMockForm('param1', $method); $this->setRequestData($method, array( 'param1' => 'DATA', )); $form->expects($this->once()) ->method('submit') ->with('DATA', 'PATCH' !== $method); $this->requestHandler->handleRequest($form, $this->request); } /** * @dataProvider methodProvider */ public function testDoNotSubmitIfWrongRequestMethod($method) { $form = $this->getMockForm('param1', $method); $otherMethod = 'POST' === $method ? 'PUT' : 'POST'; $this->setRequestData($otherMethod, array( 'param1' => 'DATA', )); $form->expects($this->never()) ->method('submit'); $this->requestHandler->handleRequest($form, $this->request); } /** * @dataProvider methodExceptGetProvider */ public function testDoNoSubmitSimpleFormIfNameNotInRequestAndNotGetRequest($method) { $form = $this->getMockForm('param1', $method, false); $this->setRequestData($method, array( 'paramx' => array(), )); $form->expects($this->never()) ->method('submit'); $this->requestHandler->handleRequest($form, $this->request); } /** * @dataProvider methodExceptGetProvider */ public function testDoNotSubmitCompoundFormIfNameNotInRequestAndNotGetRequest($method) { $form = $this->getMockForm('param1', $method, true); $this->setRequestData($method, array( 'paramx' => array(), )); $form->expects($this->never()) ->method('submit'); $this->requestHandler->handleRequest($form, $this->request); } public function testDoNotSubmitIfNameNotInRequestAndGetRequest() { $form = $this->getMockForm('param1', 'GET'); $this->setRequestData('GET', array( 'paramx' => array(), )); $form->expects($this->never()) ->method('submit'); $this->requestHandler->handleRequest($form, $this->request); } /** * @dataProvider methodProvider */ public function testSubmitFormWithEmptyNameIfAtLeastOneFieldInRequest($method) { $form = $this->getMockForm('', $method); $form->expects($this->any()) ->method('all') ->will($this->returnValue(array( 'param1' => $this->getMockForm('param1'), 'param2' => $this->getMockForm('param2'), ))); $this->setRequestData($method, $requestData = array( 'param1' => 'submitted value', 'paramx' => 'submitted value', )); $form->expects($this->once()) ->method('submit') ->with($requestData, 'PATCH' !== $method); $this->requestHandler->handleRequest($form, $this->request); } /** * @dataProvider methodProvider */ public function testDoNotSubmitFormWithEmptyNameIfNoFieldInRequest($method) { $form = $this->getMockForm('', $method); $form->expects($this->any()) ->method('all') ->will($this->returnValue(array( 'param1' => $this->getMockForm('param1'), 'param2' => $this->getMockForm('param2'), ))); $this->setRequestData($method, array( 'paramx' => 'submitted value', )); $form->expects($this->never()) ->method('submit'); $this->requestHandler->handleRequest($form, $this->request); } /** * @dataProvider methodExceptGetProvider */ public function testMergeParamsAndFiles($method) { $form = $this->getMockForm('param1', $method); $file = $this->getMockFile(); $this->setRequestData($method, array( 'param1' => array( 'field1' => 'DATA', ), ), array( 'param1' => array( 'field2' => $file, ), )); $form->expects($this->once()) ->method('submit') ->with(array( 'field1' => 'DATA', 'field2' => $file, ), 'PATCH' !== $method); $this->requestHandler->handleRequest($form, $this->request); } /** * @dataProvider methodExceptGetProvider */ public function testParamTakesPrecedenceOverFile($method) { $form = $this->getMockForm('param1', $method); $file = $this->getMockFile(); $this->setRequestData($method, array( 'param1' => 'DATA', ), array( 'param1' => $file, )); $form->expects($this->once()) ->method('submit') ->with('DATA', 'PATCH' !== $method); $this->requestHandler->handleRequest($form, $this->request); } /** * @dataProvider methodExceptGetProvider */ public function testSubmitFileIfNoParam($method) { $form = $this->getMockForm('param1', $method); $file = $this->getMockFile(); $this->setRequestData($method, array( 'param1' => null, ), array( 'param1' => $file, )); $form->expects($this->once()) ->method('submit') ->with($file, 'PATCH' !== $method); $this->requestHandler->handleRequest($form, $this->request); } abstract protected function setRequestData($method, $data, $files = array()); abstract protected function getRequestHandler(); abstract protected function getMockFile(); protected function getMockForm($name, $method = null, $compound = true) { $config = $this->getMock('Symfony\Component\Form\FormConfigInterface'); $config->expects($this->any()) ->method('getMethod') ->will($this->returnValue($method)); $config->expects($this->any()) ->method('getCompound') ->will($this->returnValue($compound)); $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $form->expects($this->any()) ->method('getName') ->will($this->returnValue($name)); $form->expects($this->any()) ->method('getConfig') ->will($this->returnValue($config)); return $form; } } Symfony/Component/Form/phpunit.xml.dist000064400000001463152374770060014247 0ustar00 ./Tests/ ./ ./Tests ./vendor Symfony/Component/Form/CHANGELOG.md000064400000033457152402756160012712 0ustar00CHANGELOG ========= 2.4.0 ----- * moved CSRF implementation to the new Security CSRF sub-component * deprecated CsrfProviderInterface and its implementations * deprecated options "csrf_provider" and "intention" in favor of the new options "csrf_token_generator" and "csrf_token_id" 2.3.0 ----- * deprecated FormPerformanceTestCase and FormIntegrationTestCase in the Symfony\Component\Form\Tests namespace and moved them to the Symfony\Component\Form\Test namespace * deprecated TypeTestCase in the Symfony\Component\Form\Tests\Extension\Core\Type namespace and moved it to the Symfony\Component\Form\Test namespace * changed FormRenderer::humanize() to humanize also camel cased field name * added RequestHandlerInterface and FormInterface::handleRequest() * deprecated passing a Request instance to FormInterface::bind() * added options "method" and "action" to FormType * deprecated option "virtual" in favor "inherit_data" * deprecated VirtualFormAwareIterator in favor of InheritDataAwareIterator * [BC BREAK] removed the "array" type hint from DataMapperInterface * improved forms inheriting their parent data to actually return that data from getData(), getNormData() and getViewData() * added component-level exceptions for various SPL exceptions changed all uses of the deprecated Exception class to use more specialized exceptions instead removed NotInitializedException, NotValidException, TypeDefinitionException, TypeLoaderException, CreationException * added events PRE_SUBMIT, SUBMIT and POST_SUBMIT * deprecated events PRE_BIND, BIND and POST_BIND * [BC BREAK] renamed bind() and isBound() in FormInterface to submit() and isSubmitted() * added methods submit() and isSubmitted() to Form * deprecated bind() and isBound() in Form * deprecated AlreadyBoundException in favor of AlreadySubmittedException * added support for PATCH requests * [BC BREAK] added initialize() to FormInterface * [BC BREAK] added getAutoInitialize() to FormConfigInterface * [BC BREAK] added setAutoInitialize() to FormConfigBuilderInterface * [BC BREAK] initialization for Form instances added to a form tree must be manually disabled * PRE_SET_DATA is now guaranteed to be called after children were added by the form builder, unless FormInterface::setData() is called manually * fixed CSRF error message to be translated * custom CSRF error messages can now be set through the "csrf_message" option * fixed: expanded single-choice fields now show a radio button for the empty value 2.2.0 ----- * TrimListener now removes unicode whitespaces * deprecated getParent(), setParent() and hasParent() in FormBuilderInterface * FormInterface::add() now accepts a FormInterface instance OR a field's name, type and options * removed special characters between the choice or text fields of DateType unless the option "format" is set to a custom value * deprecated FormException and introduced ExceptionInterface instead * [BC BREAK] FormException is now an interface * protected FormBuilder methods from being called when it is turned into a FormConfigInterface with getFormConfig() * [BC BREAK] inserted argument `$message` in the constructor of `FormError` * the PropertyPath class and related classes were moved to a dedicated PropertyAccess component. During the move, InvalidPropertyException was renamed to NoSuchPropertyException. FormUtil was split: FormUtil::singularify() can now be found in Symfony\Component\PropertyAccess\StringUtil. The methods getValue() and setValue() from PropertyPath were extracted into a new class PropertyAccessor. * added an optional PropertyAccessorInterface parameter to FormType, ObjectChoiceList and PropertyPathMapper * [BC BREAK] PropertyPathMapper and FormType now have a constructor * [BC BREAK] setting the option "validation_groups" to ``false`` now disables validation instead of assuming group "Default" 2.1.0 ----- * [BC BREAK] ``read_only`` field attribute now renders as ``readonly="readonly"``, use ``disabled`` instead * [BC BREAK] child forms now aren't validated anymore by default * made validation of form children configurable (new option: cascade_validation) * added support for validation groups as callbacks * made the translation catalogue configurable via the "translation_domain" option * added Form::getErrorsAsString() to help debugging forms * allowed setting different options for RepeatedType fields (like the label) * added support for empty form name at root level, this enables rendering forms without form name prefix in field names * [BC BREAK] form and field names must start with a letter, digit or underscore and only contain letters, digits, underscores, hyphens and colons * [BC BREAK] changed default name of the prototype in the "collection" type from "$$name$$" to "\__name\__". No dollars are appended/prepended to custom names anymore. * [BC BREAK] improved ChoiceListInterface * [BC BREAK] added SimpleChoiceList and LazyChoiceList as replacement of ArrayChoiceList * added ChoiceList and ObjectChoiceList to use objects as choices * [BC BREAK] removed EntitiesToArrayTransformer and EntityToIdTransformer. The former has been replaced by CollectionToArrayTransformer in combination with EntityChoiceList, the latter is not required in the core anymore. * [BC BREAK] renamed * ArrayToBooleanChoicesTransformer to ChoicesToBooleanArrayTransformer * ScalarToBooleanChoicesTransformer to ChoiceToBooleanArrayTransformer * ArrayToChoicesTransformer to ChoicesToValuesTransformer * ScalarToChoiceTransformer to ChoiceToValueTransformer to be consistent with the naming in ChoiceListInterface. They were merged into ChoiceList and have no public equivalent anymore. * choice fields now throw a FormException if neither the "choices" nor the "choice_list" option is set * the radio type is now a child of the checkbox type * the collection, choice (with multiple selection) and entity (with multiple selection) types now make use of addXxx() and removeXxx() methods in your model if you set "by_reference" to false. For a custom, non-recognized singular form, set the "property_path" option like this: "plural|singular" * forms now don't create an empty object anymore if they are completely empty and not required. The empty value for such forms is null. * added constant Guess::VERY_HIGH_CONFIDENCE * [BC BREAK] The methods `add`, `remove`, `setParent`, `bind` and `setData` in class Form now throw an exception if the form is already bound * fields of constrained classes without a NotBlank or NotNull constraint are set to not required now, as stated in the docs * fixed TimeType and DateTimeType to not display seconds when "widget" is "single_text" unless "with_seconds" is set to true * checkboxes of in an expanded multiple-choice field don't include the choice in their name anymore. Their names terminate with "[]" now. * deprecated FormValidatorInterface and substituted its implementations by event subscribers * simplified CSRF protection and removed the csrf type * deprecated FieldType and merged it into FormType * added new option "compound" that lets you switch between field and form behavior * [BC BREAK] renamed theme blocks * "field_*" to "form_*" * "field_widget" to "form_widget_simple" * "widget_choice_options" to "choice_widget_options" * "generic_label" to "form_label" * added theme blocks "form_widget_compound", "choice_widget_expanded" and "choice_widget_collapsed" to make theming more modular * ValidatorTypeGuesser now guesses "collection" for array type constraint * added method `guessPattern` to FormTypeGuesserInterface to guess which pattern to use in the HTML5 attribute "pattern" * deprecated method `guessMinLength` in favor of `guessPattern` * labels don't display field attributes anymore. Label attributes can be passed in the "label_attr" option/variable * added option "mapped" which should be used instead of setting "property_path" to false * [BC BREAK] "data_class" now *must* be set if a form maps to an object and should be left empty otherwise * improved error mapping on forms * dot (".") rules are now allowed to map errors assigned to a form to one of its children * errors are not mapped to unsynchronized forms anymore * [BC BREAK] changed Form constructor to accept a single `FormConfigInterface` object * [BC BREAK] changed argument order in the FormBuilder constructor * added Form method `getViewData` * deprecated Form methods * `getTypes` * `getErrorBubbling` * `getNormTransformers` * `getClientTransformers` * `getAttribute` * `hasAttribute` * `getClientData` * added FormBuilder methods * `getTypes` * `addViewTransformer` * `getViewTransformers` * `resetViewTransformers` * `addModelTransformer` * `getModelTransformers` * `resetModelTransformers` * deprecated FormBuilder methods * `prependClientTransformer` * `appendClientTransformer` * `getClientTransformers` * `resetClientTransformers` * `prependNormTransformer` * `appendNormTransformer` * `getNormTransformers` * `resetNormTransformers` * deprecated the option "validation_constraint" in favor of the new option "constraints" * removed superfluous methods from DataMapperInterface * `mapFormToData` * `mapDataToForm` * added `setDefaultOptions` to FormTypeInterface and FormTypeExtensionInterface which accepts an OptionsResolverInterface instance * deprecated the methods `getDefaultOptions` and `getAllowedOptionValues` in FormTypeInterface and FormTypeExtensionInterface * options passed during construction can now be accessed from FormConfigInterface * added FormBuilderInterface and FormConfigEditorInterface * [BC BREAK] the method `buildForm` in FormTypeInterface and FormTypeExtensionInterface now receives a FormBuilderInterface instead of a FormBuilder instance * [BC BREAK] the method `buildViewBottomUp` was renamed to `finishView` in FormTypeInterface and FormTypeExtensionInterface * [BC BREAK] the options array is now passed as last argument of the methods * `buildView` * `finishView` in FormTypeInterface and FormTypeExtensionInterface * [BC BREAK] no options are passed to `getParent` of FormTypeInterface anymore * deprecated DataEvent and FilterDataEvent in favor of the new FormEvent which is now passed to all events thrown by the component * FormEvents::BIND now replaces FormEvents::BIND_NORM_DATA * FormEvents::PRE_SET_DATA now replaces FormEvents::SET_DATA * FormEvents::PRE_BIND now replaces FormEvents::BIND_CLIENT_DATA * deprecated FormEvents::SET_DATA, FormEvents::BIND_CLIENT_DATA and FormEvents::BIND_NORM_DATA * [BC BREAK] reversed the order of the first two arguments to `createNamed` and `createNamedBuilder` in `FormFactoryInterface` * deprecated `getChildren` in Form and FormBuilder in favor of `all` * deprecated `hasChildren` in Form and FormBuilder in favor of `count` * FormBuilder now implements \IteratorAggregate * [BC BREAK] compound forms now always need a data mapper * FormBuilder now maintains the order when explicitly adding form builders as children * ChoiceType now doesn't add the empty value anymore if the choices already contain an empty element * DateType, TimeType and DateTimeType now show empty values again if not required * [BC BREAK] fixed rendering of errors for DateType, BirthdayType and similar ones * [BC BREAK] fixed: form constraints are only validated if they belong to the validated group * deprecated `bindRequest` in `Form` and replaced it by a listener to FormEvents::PRE_BIND * fixed: the "data" option supersedes default values from the model * changed DateType to refer to the "format" option for calculating the year and day choices instead of padding them automatically * [BC BREAK] DateType defaults to the format "yyyy-MM-dd" now if the widget is "single_text", in order to support the HTML 5 date field out of the box * added the option "format" to DateTimeType * [BC BREAK] DateTimeType now outputs RFC 3339 dates by default, as generated and consumed by HTML5 browsers, if the widget is "single_text" * deprecated the options "data_timezone" and "user_timezone" in DateType, DateTimeType and TimeType and renamed them to "model_timezone" and "view_timezone" * fixed: TransformationFailedExceptions thrown in the model transformer are now caught by the form * added FormRegistryInterface, ResolvedFormTypeInterface and ResolvedFormTypeFactoryInterface * deprecated FormFactory methods * `addType` * `hasType` * `getType` * [BC BREAK] FormFactory now expects a FormRegistryInterface and a ResolvedFormTypeFactoryInterface as constructor argument * [BC BREAK] The method `createBuilder` in FormTypeInterface is not supported anymore for performance reasons * [BC BREAK] Removed `setTypes` from FormBuilder * deprecated AbstractType methods * `getExtensions` * `setExtensions` * ChoiceType now caches its created choice lists to improve performance * [BC BREAK] Rows of a collection field cannot be themed individually anymore. All rows in the collection field now have the same block names, which contains "entry" where it previously contained the row index. * [BC BREAK] When registering a type through the DI extension, the tag alias has to match the actual type name. * added FormRendererInterface, FormRendererEngineInterface and implementations of these interfaces * [BC BREAK] removed the following methods from FormUtil: * `toArrayKey` * `toArrayKeys` * `isChoiceGroup` * `isChoiceSelected` * [BC BREAK] renamed method `renderBlock` in FormHelper to `block` and changed its signature * made FormView properties public and deprecated their accessor methods * made the normalized data of a form accessible in the template through the variable "form.vars.data" * made the original data of a choice accessible in the template through the property "choice.data" * added convenience class Forms and FormFactoryBuilderInterface Symfony/Component/Form/LICENSE000064400000002051152402756160012070 0ustar00Copyright (c) 2004-2014 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Symfony/Component/Form/composer.json000064400000002441152402756160013610 0ustar00{ "name": "symfony/form", "type": "library", "description": "Symfony Form Component", "keywords": [], "homepage": "http://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" } ], "require": { "php": ">=5.3.3", "symfony/event-dispatcher": "~2.1", "symfony/intl": "~2.3", "symfony/options-resolver": "~2.1", "symfony/property-access": "~2.3" }, "require-dev": { "symfony/validator": "~2.2", "symfony/http-foundation": "~2.2", "symfony/security-csrf": "~2.4" }, "suggest": { "symfony/validator": "For form validation.", "symfony/security-csrf": "For protecting forms against CSRF attacks.", "symfony/twig-bridge": "For templating with Twig.", "symfony/framework-bundle": "For templating with PHP." }, "autoload": { "psr-0": { "Symfony\\Component\\Form\\": "" } }, "target-dir": "Symfony/Component/Form", "minimum-stability": "dev", "extra": { "branch-alias": { "dev-master": "2.4-dev" } } } Symfony/Component/Form/README.md000064400000001036152402756160012344 0ustar00Form Component ============== Form provides tools for defining forms, rendering and mapping request data to related models. Furthermore it provides integration with the Validation component. Resources --------- Silex integration: https://github.com/fabpot/Silex/blob/master/src/Silex/Provider/FormServiceProvider.php Documentation: http://symfony.com/doc/2.4/book/forms.html Resources --------- You can run the unit tests with the following command: $ cd path/to/Symfony/Component/Form/ $ composer.phar install $ phpunit