diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 21d57da5..00000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "tools/phptools"] - path = tools/phptools - url = git://github.com/ralphschindler/PHPTools.git diff --git a/.travis/run-tests.sh b/.travis/run-tests.sh deleted file mode 100755 index a84e0ba2..00000000 --- a/.travis/run-tests.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -travisdir=$(dirname "$0") -testdir="$travisdir/../tests" -testedcomponents=(`cat "$travisdir/tested-components"`) -result=0 - -for tested in "${testedcomponents[@]}" - do - echo "$tested:" - phpunit -c $testdir/phpunit.xml.dist $testdir/$tested - result=$(($result || $?)) -done - -exit $result diff --git a/.travis/skipped-components b/.travis/skipped-components deleted file mode 100644 index 171dfe9d..00000000 --- a/.travis/skipped-components +++ /dev/null @@ -1,7 +0,0 @@ -Zend/Amf -Zend/Date -Zend/Dojo -Zend/Queue -Zend/Service -Zend/Test -Zend/Wildfire diff --git a/.travis/tested-components b/.travis/tested-components deleted file mode 100644 index b0b94380..00000000 --- a/.travis/tested-components +++ /dev/null @@ -1,61 +0,0 @@ -Zend/Acl -Zend/Authentication -Zend/Barcode -Zend/Cache -Zend/Captcha -Zend/Cloud -Zend/Code -Zend/Config -Zend/Console -Zend/Crypt -Zend/Currency -Zend/Db -Zend/Di -Zend/DocBook -Zend/Dojo -Zend/Dom -Zend/EventManager -Zend/Feed -Zend/File -Zend/Filter -Zend/Form -Zend/GData -Zend/Http -Zend/InfoCard -Zend/InputFilter -Zend/Json -Zend/Ldap -Zend/Loader -Zend/Locale -Zend/Log -Zend/Mail -Zend/Markup -Zend/Math -Zend/Measure -Zend/Memory -Zend/Mime -Zend/ModuleManager -Zend/Mvc -Zend/Navigation -Zend/OAuth -Zend/OpenId -Zend/Paginator -Zend/Pdf -Zend/ProgressBar -Zend/RegistryTest.php -Zend/Rest -Zend/Search -Zend/Serializer -Zend/Server -Zend/Session -Zend/Soap -Zend/Stdlib -Zend/Tag -Zend/Text -Zend/TimeSync -Zend/Translator -Zend/Uri -Zend/Validator -Zend/VersionTest.php -Zend/View -Zend/XmlRpc diff --git a/composer.json b/composer.json index c47a0de3..32083eac 100644 --- a/composer.json +++ b/composer.json @@ -1,28 +1,31 @@ { - "name": "zendframework/zend-input-filter", - "description": "Zend\\InputFilter component", + "name": "zendframework/zend-inputfilter", + "description": " ", "license": "BSD-3-Clause", "keywords": [ "zf2", - "input-filter" + "inputfilter" ], "autoload": { "psr-4": { - "Zend\\InputFilter\\": "src/" + "Zend\\InputFilter": "src/" } }, "require": { - "php": ">=5.3.23" - }, - "require-dev": { - "fabpot/php-cs-fixer": "1.7.*", - "satooshi/php-coveralls": "dev-master", - "phpunit/PHPUnit": "~4.0" + "php": ">=5.3.3", + "zendframework/zend-filter": "self.version", + "zendframework/zend-validator": "self.version", + "zendframework/zend-stdlib": "self.version" }, "homepage": "https://github.com/zendframework/zend-input-filter", "autoload-dev": { "psr-4": { "ZendTest\\InputFilter\\": "test/" } + }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "satooshi/php-coveralls": "dev-master", + "phpunit/PHPUnit": "~4.0" } } \ No newline at end of file diff --git a/src/BaseInputFilter.php b/src/BaseInputFilter.php index f7b56816..8d8f1f45 100644 --- a/src/BaseInputFilter.php +++ b/src/BaseInputFilter.php @@ -1,21 +1,11 @@ getName(); } + + if (isset($this->inputs[$name]) && $this->inputs[$name] instanceof InputInterface) { + // The element already exists, so merge the config. Please note that the order is important (already existing + // input is merged with the parameter given) + $input->merge($this->inputs[$name]); + } + $this->inputs[$name] = $input; return $this; } /** * Retrieve a named input - * - * @param string $name + * + * @param string $name * @return InputInterface|InputFilterInterface */ public function get($name) @@ -98,8 +94,8 @@ public function get($name) /** * Test if an input or input filter by the given name is attached - * - * @param string $name + * + * @param string $name * @return bool */ public function has($name) @@ -109,8 +105,8 @@ public function has($name) /** * Set data to use when validating and filtering - * - * @param array|Traversable $data + * + * @param array|Traversable $data * @return InputFilterInterface */ public function setData($data) @@ -132,7 +128,7 @@ public function setData($data) /** * Is the data set valid? - * + * * @return bool */ public function isValid() @@ -147,51 +143,28 @@ public function isValid() $this->validInputs = array(); $this->invalidInputs = array(); $valid = true; - + $inputs = $this->validationGroup ?: array_keys($this->inputs); + //var_dump($inputs); foreach ($inputs as $name) { $input = $this->inputs[$name]; - - if (!array_key_exists($name, $this->data)) { - // Not sure how to handle input filters in this case - if ($input instanceof InputFilterInterface) { - if (!$input->isValid()) { - $this->invalidInputs[$name] = $input; - $valid = false; + if (!array_key_exists($name, $this->data) || (is_string($this->data[$name]) && strlen($this->data[$name]) === 0)) { + if($input instanceof InputInterface) { + // - test if input is required + if (!$input->isRequired()) { + $this->validInputs[$name] = $input; + continue; + } + // - test if input allows empty + if ($input->allowEmpty()) { + $this->validInputs[$name] = $input; continue; } - $this->validInputs[$name] = $input; - continue; - } - - // no matching value in data - // - test if input is required - // - test if input allows empty - if (!$input->isRequired()) { - $this->validInputs[$name] = $input; - continue; - } - - if ($input->allowEmpty()) { - $this->validInputs[$name] = $input; - continue; - } - - // How do we mark the input as invalid in this case? - // (for purposes of a validation error message) - - // Mark validation as having failed - $this->invalidInputs[$name] = $input; - $valid = false; - if ($input->breakOnFailure()) { - // We failed validation, and this input is marked to - // break on failure - return false; } - continue; + // make sure we have a value (empty) for validation + $this->data[$name] = ''; } - $value = $this->data[$name]; if ($input instanceof InputFilterInterface) { if (!$input->isValid()) { $this->invalidInputs[$name] = $input; @@ -230,8 +203,8 @@ public function isValid() * * Implementations should allow passing a single array value, or multiple arguments, * each specifying a single input. - * - * @param mixed $name + * + * @param mixed $name * @return InputFilterInterface */ public function setValidationGroup($name) @@ -242,14 +215,30 @@ public function setValidationGroup($name) } if (is_array($name)) { - $this->validateValidationGroup($name); - $this->validationGroup = $name; + $inputs = array(); + foreach ($name as $key => $value) { + if (!$this->has($key)) { + $inputs[] = $value; + } else { + $inputs[] = $key; + + // Recursively populate validation groups for sub input filters + $this->inputs[$key]->setValidationGroup($value); + } + } + + if (!empty($inputs)) { + $this->validateValidationGroup($inputs); + $this->validationGroup = $inputs; + } + return $this; } $inputs = func_get_args(); $this->validateValidationGroup($inputs); $this->validationGroup = $inputs; + return $this; } @@ -258,7 +247,7 @@ public function setValidationGroup($name) * * Implementations should return an associative array of name/input pairs * that failed validation. - * + * * @return InputInterface[] */ public function getInvalidInput() @@ -271,7 +260,7 @@ public function getInvalidInput() * * Implementations should return an associative array of name/input pairs * that passed validation. - * + * * @return InputInterface[] */ public function getValidInput() @@ -281,8 +270,8 @@ public function getValidInput() /** * Retrieve a value from a named input - * - * @param string $name + * + * @param string $name * @return mixed */ public function getValue($name) @@ -303,7 +292,7 @@ public function getValue($name) * * List should be an associative array, with the values filtered. If * validation failed, this should raise an exception. - * + * * @return array */ public function getValues() @@ -324,8 +313,8 @@ public function getValues() /** * Retrieve a raw (unfiltered) value from a named input - * - * @param string $name + * + * @param string $name * @return mixed */ public function getRawValue($name) @@ -346,7 +335,7 @@ public function getRawValue($name) * * List should be an associative array of named input/value pairs, * with the values unfiltered. - * + * * @return array */ public function getRawValues() @@ -367,7 +356,7 @@ public function getRawValues() * * Should return an associative array of named input/message list pairs. * Pairs should only be returned for inputs that failed validation. - * + * * @return array */ public function getMessages() @@ -381,8 +370,8 @@ public function getMessages() /** * Ensure all names of a validation group exist as input in the filter - * - * @param array $inputs + * + * @param array $inputs * @return void * @throws Exception\InvalidArgumentException */ @@ -400,7 +389,7 @@ protected function validateValidationGroup(array $inputs) /** * Populate the values of all attached inputs - * + * * @return void */ protected function populate() diff --git a/src/Exception/ExceptionInterface.php b/src/Exception/ExceptionInterface.php index e3904da6..cc53d154 100644 --- a/src/Exception/ExceptionInterface.php +++ b/src/Exception/ExceptionInterface.php @@ -1,22 +1,11 @@ defaultFilterChain = $filterChain; return $this; } - + /** * Get default filter chain, if any * @@ -61,7 +49,7 @@ public function getDefaultFilterChain() /** * Clear the default filter chain (i.e., don't inject one into new inputs) - * + * * @return void */ public function clearDefaultFilterChain() @@ -80,7 +68,7 @@ public function setDefaultValidatorChain(ValidatorChain $validatorChain) $this->defaultValidatorChain = $validatorChain; return $this; } - + /** * Get default validator chain, if any * @@ -93,7 +81,7 @@ public function getDefaultValidatorChain() /** * Clear the default validator chain (i.e., don't inject one into new inputs) - * + * * @return void */ public function clearDefaultValidatorChain() @@ -103,8 +91,8 @@ public function clearDefaultValidatorChain() /** * Factory for input objects - * - * @param array|Traversable $inputSpecification + * + * @param array|Traversable $inputSpecification * @return InputInterface|InputFilterInterface */ public function createInput($inputSpecification) @@ -199,8 +187,8 @@ public function createInput($inputSpecification) /** * Factory for input filters - * - * @param array|Traversable $inputFilterSpecification + * + * @param array|Traversable $inputFilterSpecification * @return InputFilterInterface */ public function createInputFilter($inputFilterSpecification) diff --git a/src/Input.php b/src/Input.php index b889d991..611fcc56 100644 --- a/src/Input.php +++ b/src/Input.php @@ -1,21 +1,11 @@ allowEmpty; @@ -106,6 +93,11 @@ public function breakOnFailure() return $this->breakOnFailure; } + public function getErrorMessage() + { + return $this->errorMessage; + } + public function getFilterChain() { if (!$this->filterChain) { @@ -143,6 +135,22 @@ public function getValue() return $filter->filter($this->value); } + public function merge(InputInterface $input) + { + $this->setAllowEmpty($input->allowEmpty()); + $this->setBreakOnFailure($input->breakOnFailure()); + $this->setErrorMessage($input->getErrorMessage()); + $this->setName($input->getName()); + $this->setRequired($input->isRequired()); + $this->setValue($input->getValue()); + + $filterChain = $input->getFilterChain(); + $this->getFilterChain()->merge($filterChain); + + $validatorChain = $input->getValidatorChain(); + $this->getValidatorChain()->merge($validatorChain); + } + public function isValid($context = null) { $this->injectNotEmptyValidator(); diff --git a/src/InputFilter.php b/src/InputFilter.php index ece34036..a6721608 100644 --- a/src/InputFilter.php +++ b/src/InputFilter.php @@ -1,21 +1,11 @@ getFilterChain()->attachByName('stringtrim'); $bar->getValidatorChain()->addValidator(new Validator\Digits()); + $baz = new Input(); + $baz->setRequired(false); + $baz->getFilterChain()->attachByName('stringtrim'); + $baz->getValidatorChain()->addValidator(new Validator\StringLength(1, 6)); + $filter->add($foo, 'foo') ->add($bar, 'bar') + ->add($baz, 'baz') ->add($this->getChildInputFilter(), 'nest'); return $filter; @@ -99,8 +94,14 @@ public function getChildInputFilter() $bar->getFilterChain()->attachByName('stringtrim'); $bar->getValidatorChain()->addValidator(new Validator\Digits()); + $baz = new Input(); + $baz->setRequired(false); + $baz->getFilterChain()->attachByName('stringtrim'); + $baz->getValidatorChain()->addValidator(new Validator\StringLength(1, 6)); + $filter->add($foo, 'foo') - ->add($bar, 'bar'); + ->add($bar, 'bar') + ->add($baz, 'baz'); return $filter; } @@ -110,9 +111,11 @@ public function testCanValidateEntireDataset() $validData = array( 'foo' => ' bazbat ', 'bar' => '12345', + 'baz' => '', 'nest' => array( 'foo' => ' bazbat ', 'bar' => '12345', + 'baz' => '', ), ); $filter->setData($validData); @@ -121,9 +124,11 @@ public function testCanValidateEntireDataset() $invalidData = array( 'foo' => ' baz bat ', 'bar' => 'abc45', + 'baz' => ' ', 'nest' => array( 'foo' => ' baz bat ', 'bar' => '123ab', + 'baz' => ' ', ), ); $filter->setData($invalidData); @@ -170,7 +175,7 @@ public function testCanRetrieveInvalidInputsOnFailedValidation() $this->assertArrayNotHasKey('foo', $invalidInputs); $this->assertArrayHasKey('bar', $invalidInputs); $this->assertInstanceOf('Zend\InputFilter\Input', $invalidInputs['bar']); - $this->assertArrayHasKey('nest', $invalidInputs, var_export($invalidInputs, 1)); + $this->assertArrayHasKey('nest', $invalidInputs/*, var_export($invalidInputs, 1)*/); $this->assertInstanceOf('Zend\InputFilter\InputFilterInterface', $invalidInputs['nest']); $nestInvalids = $invalidInputs['nest']->getInvalidInput(); $this->assertArrayHasKey('foo', $nestInvalids); @@ -210,9 +215,11 @@ public function testValuesRetrievedAreFiltered() $validData = array( 'foo' => ' bazbat ', 'bar' => '12345', + 'baz' => '', 'nest' => array( 'foo' => ' bazbat ', 'bar' => '12345', + 'baz' => '', ), ); $filter->setData($validData); @@ -220,9 +227,11 @@ public function testValuesRetrievedAreFiltered() $expected = array( 'foo' => 'bazbat', 'bar' => '12345', + 'baz' => '', 'nest' => array( 'foo' => 'bazbat', 'bar' => '12345', + 'baz' => '', ), ); $this->assertEquals($expected, $filter->getValues()); @@ -234,9 +243,11 @@ public function testCanGetRawInputValues() $validData = array( 'foo' => ' bazbat ', 'bar' => '12345', + 'baz' => '', 'nest' => array( 'foo' => ' bazbat ', 'bar' => '12345', + 'baz' => '', ), ); $filter->setData($validData); @@ -247,12 +258,16 @@ public function testCanGetRawInputValues() public function testCanGetValidationMessages() { $filter = $this->getInputFilter(); + $filter->get('baz')->setRequired(true); + $filter->get('nest')->get('baz')->setRequired(true); $invalidData = array( 'foo' => ' bazbat boo ', 'bar' => 'abc45', + 'baz' => '', 'nest' => array( 'foo' => ' baz bat boo ', 'bar' => '123yz', + 'baz' => '', ), ); $filter->setData($invalidData); @@ -268,6 +283,9 @@ public function testCanGetValidationMessages() case 'bar': $this->assertArrayHasKey(Validator\Digits::NOT_DIGITS, $currentMessages); break; + case 'baz': + $this->assertArrayHasKey(Validator\NotEmpty::IS_EMPTY, $currentMessages); + break; case 'nest': foreach ($value as $k => $v) { $this->assertArrayHasKey($k, $messages[$key]); @@ -279,6 +297,9 @@ public function testCanGetValidationMessages() case 'bar': $this->assertArrayHasKey(Validator\Digits::NOT_DIGITS, $currentMessages); break; + case 'baz': + $this->assertArrayHasKey(Validator\NotEmpty::IS_EMPTY, $currentMessages); + break; default: $this->fail(sprintf('Invalid key "%s" encountered in messages array', $k)); } @@ -301,7 +322,7 @@ public function testCanConditionallyInvokeValidators() */ /** - * Idea for this one is that validation may need to rely on context -- e.g., a "password confirmation" + * Idea for this one is that validation may need to rely on context -- e.g., a "password confirmation" * field may need to know what the original password entered was in order to compare. */ public function testValidationCanUseContext() diff --git a/test/FactoryTest.php b/test/FactoryTest.php index 00f3d990..adecdd20 100644 --- a/test/FactoryTest.php +++ b/test/FactoryTest.php @@ -1,22 +1,11 @@ setBroker($broker); + $factory = new Factory(); + $filterChain = new Filter\FilterChain(); + $pluginManager = new Filter\FilterPluginManager(); + $filterChain->setPluginManager($pluginManager); $factory->setDefaultFilterChain($filterChain); $input = $factory->createInput(array( 'name' => 'foo', @@ -72,15 +60,15 @@ public function testFactoryUsesComposedFilterChainWhenCreatingNewInputObjects() $this->assertInstanceOf('Zend\InputFilter\InputInterface', $input); $inputFilterChain = $input->getFilterChain(); $this->assertNotSame($filterChain, $inputFilterChain); - $this->assertSame($broker, $inputFilterChain->getBroker()); + $this->assertSame($pluginManager, $inputFilterChain->getPluginManager()); } public function testFactoryUsesComposedValidatorChainWhenCreatingNewInputObjects() { - $factory = new Factory(); - $validatorChain = new Validator\ValidatorChain(); - $broker = new PluginBroker; - $validatorChain->setBroker($broker); + $factory = new Factory(); + $validatorChain = new Validator\ValidatorChain(); + $validatorPlugins = new Validator\ValidatorPluginManager(); + $validatorChain->setPluginManager($validatorPlugins); $factory->setDefaultValidatorChain($validatorChain); $input = $factory->createInput(array( 'name' => 'foo', @@ -88,17 +76,18 @@ public function testFactoryUsesComposedValidatorChainWhenCreatingNewInputObjects $this->assertInstanceOf('Zend\InputFilter\InputInterface', $input); $inputValidatorChain = $input->getValidatorChain(); $this->assertNotSame($validatorChain, $inputValidatorChain); - $this->assertSame($broker, $inputValidatorChain->getBroker()); + $this->assertSame($validatorPlugins, $inputValidatorChain->getPluginManager()); } public function testFactoryInjectsComposedFilterAndValidatorChainsIntoInputObjectsWhenCreatingNewInputFilterObjects() { - $factory = new Factory(); - $broker = new PluginBroker; - $filterChain = new Filter\FilterChain(); - $validatorChain = new Validator\ValidatorChain(); - $filterChain->setBroker($broker); - $validatorChain->setBroker($broker); + $factory = new Factory(); + $filterPlugins = new Filter\FilterPluginManager(); + $validatorPlugins = new Validator\ValidatorPluginManager(); + $filterChain = new Filter\FilterChain(); + $validatorChain = new Validator\ValidatorChain(); + $filterChain->setPluginManager($filterPlugins); + $validatorChain->setPluginManager($validatorPlugins); $factory->setDefaultFilterChain($filterChain); $factory->setDefaultValidatorChain($validatorChain); @@ -113,8 +102,8 @@ public function testFactoryInjectsComposedFilterAndValidatorChainsIntoInputObjec $this->assertInstanceOf('Zend\InputFilter\InputInterface', $input); $inputFilterChain = $input->getFilterChain(); $inputValidatorChain = $input->getValidatorChain(); - $this->assertSame($broker, $inputFilterChain->getBroker()); - $this->assertSame($broker, $inputValidatorChain->getBroker()); + $this->assertSame($filterPlugins, $inputFilterChain->getPluginManager()); + $this->assertSame($validatorPlugins, $inputValidatorChain->getPluginManager()); } public function testFactoryWillCreateInputWithSuggestedFilters() @@ -226,7 +215,7 @@ public function testFactoryWillCreateInputWithSuggestedRequiredFlagAndAlternativ $this->assertInstanceOf('Zend\InputFilter\InputInterface', $input); $this->assertFalse($input->isRequired()); $this->assertFalse($input->allowEmpty()); - + } public function testFactoryWillCreateInputWithSuggestedAllowEmptyFlagAndImpliesRequiredFlag() @@ -325,7 +314,7 @@ public function testFactoryWillCreateInputFilterAndAllInputObjectsFromGivenConfi )); $this->assertInstanceOf('Zend\InputFilter\InputFilter', $inputFilter); $this->assertEquals(4, count($inputFilter)); - + foreach (array('foo', 'bar', 'baz', 'bat') as $name) { $input = $inputFilter->get($name); diff --git a/test/InputFilterTest.php b/test/InputFilterTest.php index 2916fb10..92cd3d21 100644 --- a/test/InputFilterTest.php +++ b/test/InputFilterTest.php @@ -1,22 +1,11 @@ setValue('bar'); - $validator = new Validator\Alpha(); + $input->setValue('123'); + $validator = new Validator\Digits(); $input->getValidatorChain()->addValidator($validator); $this->assertTrue($input->isValid()); } @@ -144,10 +133,10 @@ public function testIsValidReturnsTrueIfValidationChainSucceeds() public function testValidationOperatesOnFilteredValue() { $input = new Input('foo'); - $input->setValue(' bar '); + $input->setValue(' 123 '); $filter = new Filter\StringTrim(); $input->getFilterChain()->attach($filter); - $validator = new Validator\Alpha(); + $validator = new Validator\Digits(); $input->getValidatorChain()->addValidator($validator); $this->assertTrue($input->isValid()); } diff --git a/test/TestAsset/CustomInput.php b/test/TestAsset/CustomInput.php index 4d3523cb..7492cf26 100644 --- a/test/TestAsset/CustomInput.php +++ b/test/TestAsset/CustomInput.php @@ -1,22 +1,11 @@