{"action":"created","issue":{"url":"https://api.github.com/repos/zendframework/zend-inputfilter/issues/111","repository_url":"https://api.github.com/repos/zendframework/zend-inputfilter","labels_url":"https://api.github.com/repos/zendframework/zend-inputfilter/issues/111/labels{/name}","comments_url":"https://api.github.com/repos/zendframework/zend-inputfilter/issues/111/comments","events_url":"https://api.github.com/repos/zendframework/zend-inputfilter/issues/111/events","html_url":"https://github.com/zendframework/zend-inputfilter/issues/111","id":162673136,"number":111,"title":"[WIP] [ZF3] Refactor input filter component","user":{"login":"GeeH","id":613376,"avatar_url":"https://avatars1.githubusercontent.com/u/613376?v=4","gravatar_id":"","url":"https://api.github.com/users/GeeH","html_url":"https://github.com/GeeH","followers_url":"https://api.github.com/users/GeeH/followers","following_url":"https://api.github.com/users/GeeH/following{/other_user}","gists_url":"https://api.github.com/users/GeeH/gists{/gist_id}","starred_url":"https://api.github.com/users/GeeH/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GeeH/subscriptions","organizations_url":"https://api.github.com/users/GeeH/orgs","repos_url":"https://api.github.com/users/GeeH/repos","events_url":"https://api.github.com/users/GeeH/events{/privacy}","received_events_url":"https://api.github.com/users/GeeH/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/zendframework/zend-inputfilter/milestones/2","html_url":"https://github.com/zendframework/zend-inputfilter/milestone/2","labels_url":"https://api.github.com/repos/zendframework/zend-inputfilter/milestones/2/labels","id":1137645,"number":2,"title":"3.0.0","description":"next backward compatibility break release","creator":{"login":"Maks3w","id":1301698,"avatar_url":"https://avatars1.githubusercontent.com/u/1301698?v=4","gravatar_id":"","url":"https://api.github.com/users/Maks3w","html_url":"https://github.com/Maks3w","followers_url":"https://api.github.com/users/Maks3w/followers","following_url":"https://api.github.com/users/Maks3w/following{/other_user}","gists_url":"https://api.github.com/users/Maks3w/gists{/gist_id}","starred_url":"https://api.github.com/users/Maks3w/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Maks3w/subscriptions","organizations_url":"https://api.github.com/users/Maks3w/orgs","repos_url":"https://api.github.com/users/Maks3w/repos","events_url":"https://api.github.com/users/Maks3w/events{/privacy}","received_events_url":"https://api.github.com/users/Maks3w/received_events","type":"User","site_admin":false},"open_issues":8,"closed_issues":0,"state":"open","created_at":"2015-05-28T09:28:03Z","updated_at":"2016-08-18T17:33:45Z","due_on":null,"closed_at":null},"comments":3,"created_at":"2016-06-28T12:24:56Z","updated_at":"2017-09-08T09:32:30Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"This issue has been moved from the `zendframework` repository as part of the bug migration program as outlined here - http://framework.zend.com/blog/2016-04-11-issue-closures.html\n\n---\n\nOriginal Issue: https://api.github.com/repos/zendframework/zendframework/issues/4772\nUser: @bakura10\nCreated On: 2013-07-02T12:52:46Z\nUpdated At: 2014-09-28T00:34:50Z\nBody\nHi everyone,\n\nThis is a branch I'm working on on my free time, to refactor the input filter component for ZF 3. I mostly push this for people who want to see the code and help.\n\nIt is not yet usable because it relies on some refactoring I'm doing in both Validator and Filter components. It completely embraces the service manager, so now we should not have the VERY annoying problem of adding custom validators/filters, and not being able to use them using the short name because it uses plugin managers that were not fetched from SM.\n\nUnder the hood, the component is completely rewritten and now uses SPL RecursiveFilter. From my first experiments, this allow an around x5-8 performance improvements and a memory consumption divided by 13 for complex input filters (magic happen here: https://github.com/bakura10/zf2/blob/943abe025ed578c4068cf19df079b34726d449a3/library/Zend/InputFilter/BaseInputFilter.php#L274-L300)\n\nWhat I've seen is that the input filter component got more and more bloated, and it is now slow as hell. Checking the isValid method as it is now makes it quite clear where the problem is.\n\nTherefore, for ZF3, I suggest that the base input filter to stay as simple as possible, and people wanting to have custom behaviors to extend the class and override the isValid for their use-cases (as a more general rule, I'd like this for most components too).\n\nTo help this, it also uses internally SPL RecursiveFilter. Basically, it allows to have very powerful validation group rules. For instance, this branch features a ValidationGroupRegex filter, and usage would be as follow:\n\n``` php\n$inputFilter = new InputFilter();\n// … populate the input filter with lot of fields\n\n// You can use the as-usual validation group:\n$inputFilter->setValidationGroup(array('username', 'email'));\n\n// But also some more complex rules. Here it only validate fields that contain 'registration-'\n// in their names\n$validationGroupRegex = new ValidationGroupRegexFilter($inputFilter, '/registration-/i')\n$inputFilter->setValidationGroupFilter($validationGroupRegex);\n```\n\nThose filters are really easy to write. They must extend AbstractValidationGroupFilter and implements the \"accept\" method (like this: https://github.com/bakura10/zf2/blob/943abe025ed578c4068cf19df079b34726d449a3/library/Zend/InputFilter/Filter/ValidationGroupRegexFilter.php)\n\nWhat do you think ? :)\n\nNOTE : not all features have been back ported yet.\n\n---\n### Comment\n\nUser: @desem\nCreated On: 2013-07-02T13:33:40Z\nUpdated At: 2013-07-02T13:33:40Z\nBody\nAnd I like it :)\nhttp://www.ivangospodinow.com/simple-form-validator-for-zend-framework-2-forms\n\n---\n### Comment\n\nUser: @bakura10\nCreated On: 2013-07-02T13:38:22Z\nUpdated At: 2013-07-02T13:38:22Z\nBody\nThanks :). I change a little bit the logic so now any recursive iterator filter can be specific, so you can use the RecursiveCallbackFilterIterator:\n\n``` php\n$filter = new RecursiveCallbackFilterIterator($inputFilter, function($value, $key)) {\n    if ($key === 'toto') {\n        return false;\n    }\n\n    return true;\n}\n```\n\nThis will only validate fields except the one different than \"toto\".\n\nPretty powerful :D.\n\n---\n### Comment\n\nUser: @desem\nCreated On: 2013-07-02T13:56:33Z\nUpdated At: 2013-07-02T13:56:33Z\nBody\nIt's interesting. But I would start with a common forum for zend :)\n\n---\n### Comment\n\nUser: @texdc\nCreated On: 2013-07-04T19:13:03Z\nUpdated At: 2013-07-04T19:13:03Z\nBody\nPlease see my [notes](https://gist.github.com/texdc/5929229).\n\n---\n### Comment\n\nUser: @bakura10\nCreated On: 2013-07-04T19:23:45Z\nUpdated At: 2013-07-04T19:23:45Z\nBody\nI answered :).\n\n---\n### Comment\n\nUser: @bakura10\nCreated On: 2013-08-09T09:51:01Z\nUpdated At: 2013-08-09T09:51:01Z\nBody\nI tried to add more exciting stuff to this refactor. Now you can add a callback recursive filter to act as a validation group:\n\n``` php\n$inputFilter = new InputFilter();\n$recursiveFilter = new ValidationGroupCallbackFilter($inputFilter, function($value, $key, $iterator) {\n   // This get called for each element, so you can reject easily\n   if ($key === 'lol') {\n       return false;\n   }\n\n   return true;\n});\n\n$inputFilter->isValid();\n```\n\n---\n### Comment\n\nUser: @bakura10\nCreated On: 2013-08-09T10:17:43Z\nUpdated At: 2013-08-09T10:17:43Z\nBody\nBased on ocramius feedback, I've renamed the InputFilter class to InputCollection, which may be clearer for people. What do you think?\n\nThe only problem is that people may be confused between the InputCollection and CollectionInputCollection (previously CollectionInputFilter). I'll try to have a better idea for this.\n\n---\n### Comment\n\nUser: @texdc\nCreated On: 2013-08-09T15:06:32Z\nUpdated At: 2013-08-09T15:06:32Z\nBody\nI like the 'InputCollection' name!  I've just started to use 'CollectionInputFilter', so I understand the issue.  Why not just 'CollectionInput'?\n\nOn Aug 9, 2013, at 5:17 AM, Michaël Gallego notifications@github.com wrote:\n\n> Based on ocramius feedback, I've renamed the InputFilter class to InputCollection, which may be clearer for people. What do you think?\n> \n> The only problem is that people may be confused between the InputCollection and CollectionInputCollection (previously CollectionInputFilter). I'll try to have a better idea for this.\n> \n> —\n> Reply to this email directly or view it on GitHub.\n\n---\n### Comment\n\nUser: @bakura10\nCreated On: 2013-08-10T08:21:41Z\nUpdated At: 2013-08-10T08:21:41Z\nBody\n@texdc , I'm not even sure the CollectionInputFilter is really needed. After all, the collection input filter does nothing more than applying the same input filter to a collection. Can't we simply run the same input filter against different set of data ? (if I managed to make the input filter stateless it's going to be even more true… but turning it stateless is really hard…)\n\n---\n### Comment\n\nUser: @bakura10\nCreated On: 2013-08-10T08:39:19Z\nUpdated At: 2013-08-10T08:42:23Z\nBody\nBy the way, here are some performance figures. I simply created a single input filter. Please note that my current implementation does a little more than the current one as each element are created using a factory (both input and input collection), so that now the global validator and filter plugin managers are always correctly injected (this was always hard in current implementation). Please note also that a major time during construction is instead spent on the service locator, therefore I've decided to create the element using new instead of using the plugin manager (after doing this test I realized how service manager is slow).\n\nIn order not to make the test wrong, no validator nor filters are attached to elements. This test just take into account the traversal time.\n\n**With 50 elements**\n\n_ZF2 :_\nInput filter construction time: 0.0015020370483398 msec\nTraversal time: 0.0062439441680908 msec\nMemory consumption: 3 Mb\n\n_ZF3 :_\nInput filter construction time: 0.00066399574279785 msec\nTraversal time: 0.0010840892791748 msec\nMemory consumption: 2,75 Mb\n\n**With 500 elements**\n\n_ZF2 :_\nInput filter construction time: 0.010568141937256 msec\nTraversal time: 0.058469772338867 msec\nMemory consumption: 6 Mb\n\n_ZF3 :_\nInput filter construction time: 0.0047299861907959 msec\nTraversal time: 0.0099430084228516 msec\nMemory consumption: 3,75 Mb\n\n**With 5000 elements**\n\n_ZF2 :_\nInput filter construction time: 0.1059877872467 msec\nTraversal time: 0.60562801361084 msec\nMemory consumption: 37 Mb\n\n_ZF3 :_\nInput filter construction time: 0.048290014266968 msec\nTraversal time: 0.10112690925598 msec\nMemory consumption: 11,75 Mb\n\nWe can expect the difference to be even more when using nested input filters (which is quite common), but already, the implementation that uses RecursiveIteratorIterator, once most important features were back ported, traversal is around 6 times faster and construction 2 times faster, and consumes a lot less memory with a lot of elements.\n\nFurthermore, all the validation group features, even with complex ones like Callback, come nearly for free with RecursiveIteratorIterator.\n\n---\n### Comment\n\nUser: @bakura10\nCreated On: 2013-09-02T15:54:03Z\nUpdated At: 2013-09-02T15:54:03Z\nBody\nHi everyone,\n\nI've taken into account a lot of feedbacks and I've completely rewritten some parts of it.\n\nThe big news is that now **input filter component is completely stateless**. Both input and input collection. Because of this, I had to abandon the RecursiveIteratorIterator implementation that was not flexible enough. Now it uses IteratorIterator instead. As a consequence, perf improvements are a bit less drastic (especially in construction time).\n## How to use it\n\nNow, input filter component is stateless. This means that there is no longer \"isValid\" method. Instead, you are expected to use the \"validate\" method:\n\n``` php\n// Note: the Factory dependency will be hanlded by a ZF factory\n$inputCollection = new InputCollection(new Factory(new InputFilterManager()));\n\n$inputCollection->add(array(\n    'name' => 'foo'\n));\n\n$data = array('foo' => 'myValue');\n\n$validationResult = $inputCollection->validate($data, $optionalContext);\n\nif ($validationResult->isValid()) {\n    $values = $validationResult->getValues();\n    // or $rawValues = $validationResult->getRawValues()\n} else {\n    $error = $validationResult->getErrorMessages();\n}\n```\n\nBecause validation result is completely decoupled, it can now be serialized or converted to JSON:\n\n``` php\njson_encode($validationResult); // Output error messages in JSON\n```\n## Validation result\n\nOne of the main goal of this refactor was, as I said it, to simplify it and remove a lot of crap because of everyone adding its edge cases.\n\nInstead, I've written several methods that make it easy to extend default behaviour:\n- People can extend InputCollection and override the \"buildValidationResult\", if they need to construct a custom validation result that also contains unknown inputs, for instance.\n- You can also extend \"buildErrorMessages\", which is called for each input collection.\n\nAlso, the validation group feature got more powerful thanks to SPL filters. Iteration is not made using a simple foreach, but using an IteratorIterator:\n\n``` php\n$iterator         = $this->getValidationGroupFilter();\n$iteratorIterator = new IteratorIterator($iterator);\n$errorMessages    = array();\n\n/** @var InputInterface|InputCollectionInterface $inputOrInputCollection */\nforeach ($iteratorIterator as $inputOrInputCollection) {\n```\n\nSPL filter iterators are automatically executed for us and allow to accept or refuse a specific key.\n\nBy default, ZF attaches a \"Zend\\InputFilter\\ValidationGroup\\NoOpFilterIterator\" filter that accepts all fields (it is the same as setting an empty array as validation group). But you can also attach more complex filter. For instance using an array:\n\n``` php\n$arrayFilter = new ArrayFilterIterator($inputCollection, array('foo'));\n$inputCollection->setValidationGroupFilter($arrayFilter);\n```\n\nNow, only the \"foo\" input of this input collection will be validated.\n\nIt comes with other filter:\n\n``` php\n$callableFilter = new CallbackFilterIterator($inputCollection, function($key, $value) {});\n$regexFilter = new RegexFilterIterator($inputCollection, '/user/');\n```\n\nThis should open the way to very fine filtering, as an input collection can contain another input collection that contains its own validation group filter. In the future, I'll write the code to be able to specifcy an input filter through config:\n\n``` php\n$inputCollection->add(\n    'type' => 'Zend\\InputFilter\\InputCollection',\n    'name' => 'top',\n    'children' => array(\n        array('name' => 'bar')\n    ),\n    'validation_group_filter' => array(\n        'type' => 'Zend\\InputFilter\\ValidationGroup\\RegexFilterIterator',\n        'options' => array(\n            'regex' => '/blabla/'\n        )\n    )\n));\n```\n### Performance\n\nI've made some performance test, once again without adding any validators/filters so that the test focus only on input filter: \n\nZF2:\n\n5 elements,\n3 input collections with 5 elements inside\n\nConstruction time : 0.00055599212646484 secondes\nTraversal time : 0.0064549446105957 secondes\nMemory: 3 Mb\n\n50 elements,\n10 input collections with 50 elements inside\n\nConstruction time : 0.0096118450164795 secondes\nTraversal time : 0.11807513237 secondes\nMemory: 6,5 Mb\n\n100 elements,\n25 input collections with 100 elements inside\n\nConstruction time : 0.033029079437256 secondes\nTraversal time : 0.51178097724915 secondes\nMemory: 19,75 Mb\n\nZF3\n\n5 elements,\n3 input collections with 5 elements inside\n\nConstruction time : 0.00034809112548828 secondes\nTraversal time : 0.0011918544769287 secondes\nMemory: 2,5 Mb\n\n50 elements,\n10 input collections with 50 elements inside\n\nConstruction time : 0.0085010528564453 secondes\nTraversal time : 0.01695990562439 secondes\nMemory: 2,75 Mb\n\n100 elements,\n25 input collections with 100 elements inside\n\nConstruction time : 0.031938076019287 secondes\nTraversal time : 0.060458183288574 secondes\nMemory: 4,25 Mb\n\n---\n### Comment\n\nUser: @Ocramius\nCreated On: 2013-09-02T16:17:17Z\nUpdated At: 2013-09-02T16:17:17Z\nBody\nAs discussed with @bakura10 on IRC, we should have the same interface for `Input` and `InputFilter`. An `InputFilter` is just a normal `Input` with an `array` or `Traversable` value. Otherwise, I see no difference with the `Input` API.\n\nAny pluralization of method names in the API shall be removed.\n\n---\n### Comment\n\nUser: @bakura10\nCreated On: 2013-09-02T16:22:36Z\nUpdated At: 2013-09-02T16:24:21Z\nBody\nDone.\n\nSo now InputCollection extends Input, and have the same \"validate\" method. I didn't change it yet but Input should return a ValidationResult too.\n\nThe question now is that InputFilter will receive an array of ValidationResult, so we must find an efficient way to inject the result into the main ValidationResult.\n\nAs @Ocramius suggested, I've alos removed the fallback value capability. In fact this is a Filter job. So maybe we should create a FallbackValueFilter, but this sohuld not be handled in Input Filter component.\n\n---\n### Comment\n\nUser: @bakura10\nCreated On: 2013-09-02T17:47:51Z\nUpdated At: 2013-09-02T17:48:47Z\nBody\nI have integrated several new things:\n- Input collection can now have their own validators and filters. When an input collection is validated, it FIRST execute its own validators, and then execute the validators of all its children. On the other hand, when data is filtered, all children are filtered, THEN the filters attached to the collection is executed. This allow to have, for instance, a Date input collection with three inputs, and validate or filter based on this context. This should open some nice simplifications to the form component, especially with the Collection element.\n- The validation process is a bit complicatd, I'm not sure about hte best way to handle it.\n\nCurrently, whenever an input collection is validated, a new ValidationResult is built. If the input collection contains no errors, then the values are filtered. This means that in the following hiearrchy:\n\n``` php\nInput filter 1\n    input 1\n    input 2\n    input filter 2\n        input 3\n        input 4\n```\n\nif input 3, 4 and input filter 2 are valid, then the values are filtered EVEN THOUGH input 1 failed. The filter step is \"on an input collection\" basis.\n\nThis may not be the most efficient way because we need to do the recursion twice... If you have any better idea, please shout!\n\nI also need people to evaluate this: https://github.com/bakura10/zf2/blob/d0cfc2e6643732b1e5e020f6154a6617e7e4d20d/library/Zend/InputFilter/InputCollection.php#L157\n\n---\n### Comment\n\nUser: @bakura10\nCreated On: 2013-09-02T19:14:05Z\nUpdated At: 2013-09-02T19:14:05Z\nBody\nI've been using IteratorAggregate, which is around 30% faster than implement IteratorIterator. We are now even faster than when using RecursiveIteratorIterator :D. Some funny benchmark with HEAVY input filters (450 inputs, and 50 sub-input collections with 450 elements inside):\n\nZF2:\n\nConstruction time : 0.47534704208374 secondes\nTraversal time : 7.0274820327759 secondes\nMemory consumption: 154 Mb\n\nZF3: \n\nConstruction time : 0.48701810836792 secondes\nTraversal time : 0.83196616172791 secondes\nMemory consumption: 18 Mb\n\n---\n### Comment\n\nUser: @netiul\nCreated On: 2013-09-03T06:58:37Z\nUpdated At: 2013-09-03T06:58:37Z\nBody\nImpressive, I must say. Keep up the great work!\n\n---\n### Comment\n\nUser: @bakura10\nCreated On: 2013-09-03T09:58:39Z\nUpdated At: 2013-09-03T09:58:39Z\nBody\nThanks @netiul .\n\nI've just noticed something strange, I'd like your feedback. Since this time, I've always thought that the input filters does : validation using the raw data, then filtering. However, it seems that I was wrong: https://github.com/zendframework/zf2/blob/master/library/Zend/InputFilter/Input.php#L309\n\nThe filtering is done prior to the validation. Is this something expected? Is this normal behaviour and what we want? I'm always lost about this.\n\n---\n### Comment\n\nUser: @bakura10\nCreated On: 2013-09-03T12:26:28Z\nUpdated At: 2013-09-03T12:26:28Z\nBody\nAnother massive performance improvement for today (around 20%), because the whole input collection is now traversed only once instead of twice.\n\nThis is possible thanks to the previous remark about filtering data, some talk with @Ocramius, and the new stateless that allows interesting optimizations.\n\nFirst, the ValidationResult has been renamed to InputFilterResult. This is because I'll try to make Validator component completely stateless too. It will return ValidationResult, so it was important to make the two different by the naming.\n\nAbout the performance improvement it comes from the reason of my previous comment:\n\nI realized that current implementation of Input, the \"isValid\" method filter data before validating it. In fact, it makes sense (if you have an input with a \"Alnum\" validator and a trimming Filter, you want \" abc \" to be valid). The thing is that in ZF2, values were filtered twice: once when the \"isValid\" method of the input filter is called, and another time you do \"getValues\". This is useless work.\n\nNow, when the \"validate\" method for an input is called, as the value is filtered anyway, it's stored directly in the ValidationResult, and aggregated by the ValidationResult of the Input Collection. So calling \"getData\" from the input collection does not incur another recursion.\n\nThe second thing is that as I said before, InputCollection now can have their validators and filters (which shuld remove the need of the previous CollectionInputFilter class). I'm not sure about the workflow:\n\nLet's assume the following input collection, called \"coll\", which contains two inputs \"a\", \"b\".\n\nWhen calling validate, the following happens:\n1. The InputCollection validators (if any) are run. The array that the validator will receive will by [\"a\" => ..., \"b\" => ...].\n   1.1 If invalid, register error messages.\n   1.2 If input collection is configured to break on failure, we immediately return an input filter result.\n2. Otherwise, each inputs (a and b) are filtered and validated.\n3. If everything is correct, the input filter result is built, and the input collection filters are run for the value (in this case, the filtered values of a and b).\n\nDoes the order make sense to everyone?\n\nAnother question I have is: if an input has failed (not valid), should we insert the filtered value into the input filter result ?\n\nRemark: because InputFilter is a stateless component now, I think we can safely switch the plugin manager to share instance by default. This should be a pretty memory consumption improvment for people using a lot of input filters.\n\n---\n### Comment\n\nUser: @dphn\nCreated On: 2013-09-03T12:35:53Z\nUpdated At: 2013-09-03T12:35:53Z\nBody\nTell me, please, why do not you rename InputFilter to InputSpecification? After all, it contains both filters and validators?\n\n---\n### Comment\n\nUser: @bakura10\nCreated On: 2013-09-03T12:37:35Z\nUpdated At: 2013-09-03T12:37:35Z\nBody\n??? You're mixing everything again... InputSpecifciation does not exist. No classes have been renamed to InputSpecification.\n\nInputFilter has been however renamed to InputCollection, because it represents more what it is (a collection of inputs).\n\n---\n### Comment\n\nUser: @dphn\nCreated On: 2013-09-03T12:38:54Z\nUpdated At: 2013-09-03T12:38:54Z\nBody\nThank you, I get it. So really better.\n\n---\n### Comment\n\nUser: @weierophinney\nCreated On: 2013-09-03T16:10:05Z\nUpdated At: 2013-09-03T16:10:05Z\nBody\n\n> The filtering is done prior to the validation. Is this something expected? Is this normal behaviour and what we want? I'm always lost about this.\n\n@bakura10 :\n\nYes, this is normal behavior, and has been since ZF1. The idea is that you do normalization tasks, and then validate the normalized data (this is particularly useful for things like phone numbers and CC numbers, to allow stripping non-digit input such as spaces, dots, parens, etc). I've seen some requests in the past for a post-filter process as well, but the idea has never gained traction.\n\n---\n### Comment\n\nUser: @bakura10\nCreated On: 2013-09-03T16:11:22Z\nUpdated At: 2013-09-03T16:11:22Z\nBody\nOk thanks to confirm this then :).\n\n---\n### Comment\n\nUser: @dphn\nCreated On: 2013-09-05T16:25:15Z\nUpdated At: 2013-09-05T16:25:15Z\nBody\nI wonder, in the third version will remain a mass func_get_arg () in the constructor of each validator?\n\n---\n### Comment\n\nUser: @Ocramius\nCreated On: 2013-09-05T16:35:37Z\nUpdated At: 2013-09-05T16:35:37Z\nBody\n@dphn not sure if that's relevant to this PR - the main focus here is moving to a stateless interface first. Otherwise we'd need an `Options` object for every validator, which is probably a further step for a different PR\n\n---\n### Comment\n\nUser: @dphn\nCreated On: 2013-09-05T16:42:16Z\nUpdated At: 2013-09-05T16:42:16Z\nBody\nI'm sorry, I just took the most active channel of communication :) Not anymore.\n\n---\n### Comment\n\nUser: @dphn\nCreated On: 2013-09-05T22:00:49Z\nUpdated At: 2013-09-05T22:00:49Z\nBody\n\n```\nThe filtering is done prior to the validation. Is this something expected? Is this normal behaviour and what we want? I'm always lost about this.\n```\n\nIt would be nice if it were true. I'm trying to add a filter in the multiupload  form, but it is always executed after validators.\n\n---\n### Comment\n\nUser: @bakura10\nCreated On: 2013-09-05T22:02:35Z\nUpdated At: 2013-09-05T22:02:35Z\nBody\nYes, this is expected for file upload though and won't change. For file it makes sense to first validate and then filter (which include things like file upload).\n\n---\n### Comment\n\nUser: @dphn\nCreated On: 2013-09-05T22:11:39Z\nUpdated At: 2013-09-05T22:11:39Z\nBody\nI think that uploading files is not a task to be performed by the filter. If the filters and validators can be added to Form as listeners, this problem would not exist. But what can I do in the current situation?\n\n---\n### Comment\n\nUser: @bakura10\nCreated On: 2013-09-05T22:13:49Z\nUpdated At: 2013-09-05T22:13:49Z\nBody\nIn fact, I was a bit vague. Filters does not \"upload\", they rename. Eventually, they could rename and move to something else, which would upload the file to another server. But if you think at it, \"moving\" or \"renaming\" can be the job of a filter.\n\n---\n"},"comment":{"url":"https://api.github.com/repos/zendframework/zend-inputfilter/issues/comments/328054461","html_url":"https://github.com/zendframework/zend-inputfilter/issues/111#issuecomment-328054461","issue_url":"https://api.github.com/repos/zendframework/zend-inputfilter/issues/111","id":328054461,"user":{"login":"froschdesign","id":103362,"avatar_url":"https://avatars2.githubusercontent.com/u/103362?v=4","gravatar_id":"","url":"https://api.github.com/users/froschdesign","html_url":"https://github.com/froschdesign","followers_url":"https://api.github.com/users/froschdesign/followers","following_url":"https://api.github.com/users/froschdesign/following{/other_user}","gists_url":"https://api.github.com/users/froschdesign/gists{/gist_id}","starred_url":"https://api.github.com/users/froschdesign/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/froschdesign/subscriptions","organizations_url":"https://api.github.com/users/froschdesign/orgs","repos_url":"https://api.github.com/users/froschdesign/repos","events_url":"https://api.github.com/users/froschdesign/events{/privacy}","received_events_url":"https://api.github.com/users/froschdesign/received_events","type":"User","site_admin":false},"created_at":"2017-09-08T09:32:30Z","updated_at":"2017-09-08T09:32:30Z","author_association":"MEMBER","body":"@Seryus \r\n> Although they are often unwanted, we can't assume that this is always the case.\r\n\r\nThis sentence is irrelevant, because zend-inputfilter does not force you to use a filter to remove the whitespace. It's your choice!\r\n\r\n> …in my opinion the pre-filtering process is unnecessary.\r\n\r\nA simple example: a text field for the age of a person. Many values are possible:\r\n(`_` for whitespace)\r\n\r\n1. `40`\r\n2. ` _40`\r\n3. `40_`\r\n4. `_40_ `\r\n\r\nWith pre-filtering all values will pass the validator.\r\nWithout pre-filtering only the number 1. will pass the validator.\r\n\r\nNow the question: which filtering is user-friendly? 😉 \r\n\r\n---\r\n\r\n@weierophinney \r\n\r\nThe current problem is the \"background magic\" like the `FileInput` class, which runs the filter after validation. It's correct, but too much magic and it is a different behaviour opposite to all other input classes.\r\n\r\n> For this reason, I'd recommend a factor of the component provide post filtering capabilities, and that we rename the current filters to be called normalizers instead.\r\n\r\nThis will remove the \"background magic\" and introduce many more possibilities for the InputFilter.   👍 "}}
{"actor":{"display_login":"froschdesign"}}