From e2ae6289aa11d31d0b4ad2447cdafc0b0ec0b278 Mon Sep 17 00:00:00 2001 From: meNeither Date: Mon, 6 Apr 2015 00:40:27 +0200 Subject: [PATCH 1/3] Fixed form collections with nested fieldsets that implements InputfilterProviderInterface --- library/Zend/Form/Form.php | 36 ++++++++++++++++- tests/ZendTest/Form/FormTest.php | 23 +++++++++++ .../TestAsset/InputFilterProviderFieldset.php | 39 +++++++++++++++++++ 3 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 tests/ZendTest/Form/TestAsset/InputFilterProviderFieldset.php diff --git a/library/Zend/Form/Form.php b/library/Zend/Form/Form.php index 854644f3f52..1db9080f07a 100644 --- a/library/Zend/Form/Form.php +++ b/library/Zend/Form/Form.php @@ -807,8 +807,31 @@ public function attachInputFilterDefaults(InputFilterInterface $inputFilter, Fie if ($childFieldset->getObject() instanceof InputFilterAwareInterface) { $inputFilter->add($childFieldset->getObject()->getInputFilter(), $name); } else { - if ($fieldset instanceof Collection && $inputFilter instanceof CollectionInputFilter) { - continue; + // Add input filter for collections via getInputFilterSpecification() + if ($childFieldset instanceof Collection + && $childFieldset->getTargetElement() instanceof InputFilterProviderInterface + && $childFieldset->getTargetElement()->getInputFilterSpecification() + ) { + $collectionContainerFilter = new CollectionInputFilter(); + + $spec = $childFieldset->getTargetElement()->getInputFilterSpecification(); + $filter = $inputFactory->createInputFilter($spec); + + $collectionContainerFilter->setInputFilter($filter); + + $inputFilter->add($collectionContainerFilter, $name); + + // We need to copy the inputs to the collection input filter + if ($inputFilter instanceof CollectionInputFilter) { + foreach ($inputFilter->getInputs() as $filterName => $input) { + if (!$inputFilter->getInputFilter()->has($filterName)) { + $inputFilter->getInputFilter()->add($input, $filterName); + } + } + } + + // Add child elements from target element + $childFieldset = $childFieldset->getTargetElement(); } else { $inputFilter->add(new InputFilter(), $name); } @@ -840,6 +863,15 @@ public function attachInputFilterDefaults(InputFilterInterface $inputFilter, Fie // Recursively attach sub filters $this->attachInputFilterDefaults($filter, $childFieldset); + + // We need to copy the inputs to the collection input filter to ensure that all sub filters are added + if ($inputFilter instanceof CollectionInputFilter) { + foreach ($inputFilter->getInputs() as $filterName => $input) { + if (!$inputFilter->getInputFilter()->has($filterName)) { + $inputFilter->getInputFilter()->add($input, $filterName); + } + } + } } } diff --git a/tests/ZendTest/Form/FormTest.php b/tests/ZendTest/Form/FormTest.php index 167c693eed3..b0826b85734 100644 --- a/tests/ZendTest/Form/FormTest.php +++ b/tests/ZendTest/Form/FormTest.php @@ -1874,6 +1874,29 @@ public function testFormWithNestedCollections() $this->assertEquals($data, $this->form->getData()); } + public function testFormWithCollectionsAndNestedFieldsetsWithInputFilterProviderInterface() + { + $this->form->add(array( + 'type' => 'Zend\Form\Element\Collection', + 'name' => 'nested_fieldset_with_input_filter_provider', + 'options' => array( + 'label' => 'InputFilterProviderFieldset', + 'count' => 1, + 'target_element' => array( + 'type' => 'ZendTest\Form\TestAsset\InputFilterProviderFieldset' + ) + ), + )); + + $this->assertTrue( + $this->form->getInputFilter() + ->get('nested_fieldset_with_input_filter_provider') + ->getInputFilter() + ->get('foo') + instanceof \Zend\InputFilter\Input + ); + } + public function testFormElementValidatorsMergeIntoAppliedInputFilter() { $this->form->add(array( diff --git a/tests/ZendTest/Form/TestAsset/InputFilterProviderFieldset.php b/tests/ZendTest/Form/TestAsset/InputFilterProviderFieldset.php new file mode 100644 index 00000000000..1a0400e4fa8 --- /dev/null +++ b/tests/ZendTest/Form/TestAsset/InputFilterProviderFieldset.php @@ -0,0 +1,39 @@ +add(array( + 'name' => 'foo', + 'options' => array( + 'label' => 'Foo' + ), + )); + + $this->add(new BasicFieldset()); + } + + public function getInputFilterSpecification() + { + return array( + 'foo' => array( + 'required' => true, + ) + ); + } +} From 8d1f6db25ae5fabb636f83745fe938a2ca420fe2 Mon Sep 17 00:00:00 2001 From: meNeither Date: Tue, 7 Apr 2015 02:50:11 +0200 Subject: [PATCH 2/3] Added private function addInputsToCollectionInputFilter --- library/Zend/Form/Form.php | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/library/Zend/Form/Form.php b/library/Zend/Form/Form.php index 1db9080f07a..f25ec683068 100644 --- a/library/Zend/Form/Form.php +++ b/library/Zend/Form/Form.php @@ -823,11 +823,7 @@ public function attachInputFilterDefaults(InputFilterInterface $inputFilter, Fie // We need to copy the inputs to the collection input filter if ($inputFilter instanceof CollectionInputFilter) { - foreach ($inputFilter->getInputs() as $filterName => $input) { - if (!$inputFilter->getInputFilter()->has($filterName)) { - $inputFilter->getInputFilter()->add($input, $filterName); - } - } + $inputFilter = $this->addInputsToCollectionInputFilter($inputFilter); } // Add child elements from target element @@ -866,15 +862,28 @@ public function attachInputFilterDefaults(InputFilterInterface $inputFilter, Fie // We need to copy the inputs to the collection input filter to ensure that all sub filters are added if ($inputFilter instanceof CollectionInputFilter) { - foreach ($inputFilter->getInputs() as $filterName => $input) { - if (!$inputFilter->getInputFilter()->has($filterName)) { - $inputFilter->getInputFilter()->add($input, $filterName); - } - } + $inputFilter = $this->addInputsToCollectionInputFilter($inputFilter); } } } + /** + * Add inputs to CollectionInputFilter + * + * @param CollectionInputFilter $inputFilter + * @return CollectionInputFilter + */ + private function addInputsToCollectionInputFilter(CollectionInputFilter $inputFilter) + { + foreach ($inputFilter->getInputs() as $name => $input) { + if (!$inputFilter->getInputFilter()->has($name)) { + $inputFilter->getInputFilter()->add($input, $name); + } + } + + return $inputFilter; + } + /** * Are the form elements/fieldsets names wrapped by the form name ? * From 87d15167016667f78c3cdd376f013be63c7594ab Mon Sep 17 00:00:00 2001 From: meNeither Date: Sat, 18 Apr 2015 04:32:18 +0200 Subject: [PATCH 3/3] Added element input filters to collection input filter --- library/Zend/Form/Form.php | 7 ++- tests/ZendTest/Form/FormTest.php | 2 +- .../Plugin/FilePostRedirectGetTest.php | 53 ------------------- 3 files changed, 7 insertions(+), 55 deletions(-) diff --git a/library/Zend/Form/Form.php b/library/Zend/Form/Form.php index f25ec683068..886f94eddee 100644 --- a/library/Zend/Form/Form.php +++ b/library/Zend/Form/Form.php @@ -788,7 +788,12 @@ public function attachInputFilterDefaults(InputFilterInterface $inputFilter, Fie } } - $inputFilter->add($input, $name); + // Add element input filter to CollectionInputFilter + if ($inputFilter instanceof CollectionInputFilter && !$inputFilter->getInputFilter()->has($name)) { + $inputFilter->getInputFilter()->add($input, $name); + } else { + $inputFilter->add($input, $name); + } } if ($fieldset === $this && $fieldset instanceof InputFilterProviderInterface) { diff --git a/tests/ZendTest/Form/FormTest.php b/tests/ZendTest/Form/FormTest.php index b0826b85734..29cf614381f 100644 --- a/tests/ZendTest/Form/FormTest.php +++ b/tests/ZendTest/Form/FormTest.php @@ -1255,7 +1255,7 @@ public function testDoNotApplyEmptyInputFiltersToSubFieldsetOfCollectionElements $this->form->setInputFilter($inputFilter); $this->assertInstanceOf('Zend\InputFilter\CollectionInputFilter', $this->form->getInputFilter()->get('items')); - $this->assertCount(1, $this->form->getInputFilter()->get('items')->getInputs()); + $this->assertCount(1, $this->form->getInputFilter()->get('items')->getInputFilter()->getInputs()); } public function testFormValidationCanHandleNonConsecutiveKeysOfCollectionInData() diff --git a/tests/ZendTest/Mvc/Controller/Plugin/FilePostRedirectGetTest.php b/tests/ZendTest/Mvc/Controller/Plugin/FilePostRedirectGetTest.php index 8ba52995b39..c699b86cccd 100644 --- a/tests/ZendTest/Mvc/Controller/Plugin/FilePostRedirectGetTest.php +++ b/tests/ZendTest/Mvc/Controller/Plugin/FilePostRedirectGetTest.php @@ -274,59 +274,6 @@ public function testReuseMatchedParametersWithSegmentController() $this->assertEquals(303, $prgResultRoute->getStatusCode()); } - public function testFieldsetAmountInFormEqualsFieldsetsInInputFilter() - { - // POST - $url = '/'; - $params = array( - 'links' => array( - '0' => array( - 'foobar' => 'val', - ), - '1' => array( - 'foobar' => 'val', - ), - ), - ); - $this->request->setMethod('POST'); - $this->request->setPost(new Parameters($params)); - $this->request->setUri($url); - - $this->form->add($this->collection); - - $routeMatch = $this->event->getRouter()->match($this->request); - $this->event->setRouteMatch($routeMatch); - - $this->controller->dispatch($this->request, $this->response); - $prgResultUrl = $this->controller->fileprg($this->form); - - $this->assertInstanceOf('Zend\Http\Response', $prgResultUrl); - $this->assertTrue($prgResultUrl->getHeaders()->has('Location')); - $this->assertEquals('/', $prgResultUrl->getHeaders()->get('Location')->getUri()); - $this->assertEquals(303, $prgResultUrl->getStatusCode()); - - $this->assertCount(count($params['links']), $this->form->get('links')->getFieldsets()); - $this->assertCount(count($this->form->get('links')->getFieldsets()), $this->form->getInputFilter()->get('links')->getInputs()); - - // GET - $this->request = new Request(); - $form = new Form(); - $collection = new Collection('links', array( - 'count' => 1, - 'allow_add' => true, - 'target_element' => array( - 'type' => 'ZendTest\Mvc\Controller\Plugin\TestAsset\LinksFieldset', - ), - )); - $form->add($collection); - $this->controller->dispatch($this->request, $this->response); - $prgResult = $this->controller->fileprg($form); - - $this->assertEquals($params, $prgResult); - $this->assertCount(count($params['links']), $form->get('links')->getFieldsets()); - $this->assertCount(count($form->get('links')->getFieldsets()), $form->getInputFilter()->get('links')->getInputs()); - } - public function testCollectionInputFilterIsInitializedBeforePluginRetrievesIt() { $fieldset = new TestAsset\InputFilterProviderFieldset();