Giter Site home page Giter Site logo

laminas / laminas-inputfilter Goto Github PK

View Code? Open in Web Editor NEW
41.0 19.0 29.0 3.18 MB

Normalize and validate input sets from the web, APIs, the CLI, and more, including files

Home Page: https://docs.laminas.dev/laminas-inputfilter/

License: BSD 3-Clause "New" or "Revised" License

PHP 100.00%
filtering validations

laminas-inputfilter's Introduction

laminas-inputfilter

Build Status

🇷🇺 Русским гражданам

Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм.

У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую.

Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!"

🇺🇸 To Citizens of Russia

We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism.

One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences.

You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!"

The laminas-inputfilter component can be used to filter and validate generic sets of input data. For instance, you could use it to filter $_GET or $_POST values, CLI arguments, etc.

Installation

Run the following to install this library:

$ composer require laminas/laminas-inputfilter

Documentation

Browse the documentation online at https://docs.laminas.dev/laminas-inputfilter/

Support

laminas-inputfilter's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

laminas-inputfilter's Issues

[Refactor] ZF3

Hi everyone,

Some years ago I've started a big refactor of Input Filter. You can see the initial work there: zf-fr/input-filter#1

The idea was to take advantage of stateless component, by re-using refactored validator and filter components (made stateless too). It also aimed to be much faster, as well as simplify some concepts (mostly related to continue_if_empty, allow_empty... although I don't remember the exact details as it's been a long time).

I won't work on this before we have refactored the validator and filter as it would be wasted work, but I open the thread just for refernece for people wanting to erefactor this one.


Originally posted by @bakura10 at zendframework/zend-inputfilter#13

Add possibility to reference other input (using token name) from the same input filter

Feature Request

Q A
New Feature yes
RFC no
BC Break no

Summary

It would be nice to be able to get the filtered/validated value for other input element (referenced with token), as per form example for Identical Validator.

https://docs.laminas.dev/laminas-validator/validators/identical/#form-elements

Currently it seems impossible to do this. Even for Identical Validator this only can validate a static value, not other input value.

[WIP] [ZF3] Refactor filter

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


Original Issue: https://api.github.com/repos/zendframework/zendframework/issues/5097
User: @bakura10
Created On: 2013-09-09T19:01:52Z
Updated At: 2014-09-28T00:34:45Z
Body
As asked by @weierophinney on IRC, I should create the PR against develop.

So let's focus for now on Filter, this is the most advanced one and mostly done (just need to find a great way for some plugin manager), and some tests were already updated.

As a reminder, the Filter refactor is mostly:

  • Code cleaning (now, all filters accept the same options array, which allow to configure a filter)
  • Options are now underscore_separated
  • Some filters were remade

Comment

User: @bakura10
Created On: 2013-09-09T19:44:33Z
Updated At: 2013-09-09T19:44:33Z
Body
For people that want to help: I've spotted some test that say the test is invalid with PHP 5.4. Why? Does this means some thing can be removed in PHP 5.4?


Comment

User: @ThomasCantonnet
Created On: 2013-09-10T18:02:40Z
Updated At: 2013-09-10T18:06:48Z
Body
@bakura10 Although some have reported that iconv's //IGNORE option is broken on PHP 5.3.10 too, it seems that it's broken in PHP5.4 <= 5.4.6 (https://bugs.php.net/bug.php?id=61484). I don't know what the status on that issue is, but that might explain this test. It appears it's a glibc issue though, not sure how PHP versions affect this behaviour.

(Edit: my bad, it seems that it's just iconv that doesn't accept this //IGNORE option anymore and it hasn't been fixed in PHP 5.3, but it's been removed in 5.4. I guess we need to fix that filter.)

Seems like @Maks3w was the one who marked this test as incompatible (bakura10/zf2@ab87188) so he might answer you on the reasons :)



Originally posted by @GeeH at zendframework/zend-inputfilter#112

Validation group not applied correctly when validating a CollectionInputFilter

While debugging a problem when validating a complex form containing collections and validation groups to limit the fields that are being validated I notice the following code in CollectionInputFilter:

        foreach ($this->data as $key => $data) {
            // ....
            if (null !== $this->validationGroup) {
                $inputFilter->setValidationGroup($this->validationGroup[$key]);
            }

If the CollectionInputFilter has a validation group then the validation group is indexed using the same key as the data. A validation group is assigned like this:

$collection = new CollectionInputFilter(...);
$collection->setValidationGroup(array(
    'a', 'b', 'c'
));

Now, for the first element in the list only property a is validated, property b for the second, etc.

Am I missing something in the way I assign my validation group? Or should the line where the validation group is assigned read:

                $inputFilter->setValidationGroup($this->validationGroup);

I can work around this by calling $collection->getInputFilter()->setValidationGroup(...) instead, however this prevents me of performing a single setValidationGroup call at the root of my form with a single nested array for the entire form.


Originally posted by @erikorbons at zendframework/zend-inputfilter#113

How use Callback validator when field is conditionally required?

I have two fields and one of them is required if the value of the other is equal to one condition.

How can I do this?

The "campaignFranchise" field is only required when the value of the "campaign" is equal to "franchise".

            4 => [
                'required' => true,
                'validators' => [
                    0 => [
                        'name' => NotEmpty::class,
                        'options' => [...],
                    ],
                    1 => [
                        'name' => StringLength::class,
                        'options' => [...],
                    ],
                ],
                'filters' => [...],
                'name' => 'campaign',
            ],
            5 => [
                'required' => true,
                'validators' => [
                    0 => [
                        'name' => NotEmpty::class,
                        'options' => [
                            'translatorenabled' => true,
                        ],
                        'break_chain_on_failure' => true,
                    ],
                    1 => [
                        'name' => Callback::class,
                        'options' => [
                            'callback' => [
                                CampaignFranchise::class,
                                'isValid',
                            ],
                        ],
                    ],
                    2 => [
                        'name' => StringLength::class,
                        'options' => [...],
                    ],
                ],
                'filters' => [...],
                'name' => 'campaignFranchise',
            ],

I try use "continueIfEmpty" and "allowEmpty" but how I don't have value and is required, the validation return false.
https://github.com/zendframework/zend-inputfilter/blob/master/src/Input.php#L410-415

If the field is required false, the validation does not trigger.
https://github.com/zendframework/zend-inputfilter/blob/master/src/BaseInputFilter.php#L251-L256

And if I use the callback validator in "campaign" field, the message error result display in wrong field.


Originally posted by @vincequeiroz at zendframework/zend-inputfilter#146

PHP 8.0 support

Feature Request

Q A
New Feature yes

Summary

To be prepared for the december release of PHP 8.0, this repository has some additional TODOs to be tested against the new major version.

In order to make this repository compatible, one has to follow these steps:

  • Modify composer.json to provide support for PHP 8.0 by adding the constraint ~8.0.0
  • Modify composer.json to drop support for PHP less than 7.3
  • Modify composer.json to implement phpunit 9.3 which supports PHP 7.3+
  • Modify .travis.yml to ignore platform requirements when installing composer dependencies (simply add --ignore-platform-reqs to COMPOSER_ARGS env variable)
  • Modify .travis.yml to add PHP 8.0 to the matrix (NOTE: Do not allow failures as PHP 8.0 has a feature freeze since 2020-08-04!)
  • Modify source code in case there are incompatibilities with PHP 8.0

InputFilterInterface::getInvalidInput() and InputFilterInterface::getValidInput() are incosistent with InputFilterInterface::add()

Bug Report

Q A
Versions Since version 2.0

Summary

While InputFilterInterface::add() allows InputInterface|InputFilterInterface|array|Traversable to be added, InputFilterInterface::getInvalidInput() and InputFilterInterface::getValidInput() only return InputInterface to be returned.

This leads to inconsistent behavior, because InputFilterInterface does not implement InputInterface and would cause errors in instances where they are treated as equal (for example here: https://github.com/mvlabs/ze-content-validation/blob/master/src/Validator/ValidationResult.php#L68-L70).

The included implementation of InputFilterInterface \Laminas\InputFilter\BaseInputFilter does not comply to the interface itself either. It fills its properties BaseInputFilter::$validInputs and BaseInputFilter::$invalidInputs with InputInterface and InputFilterInterface alike and though only type hints @return InputInterface[] on BaseInputFilter::getInvalidInputs() and BaseInputFilter::getValidInputs().

Current behavior

BaseInputFilter::getInvalidInputs() and BaseInputFilter::getValidInputs() return InputFilterInterface and InputFilter alike.

How to reproduce

$requiredInput = new \Laminas\InputFilter\Input();
$requiredInput->setRequired(true);

$inputFilter = new \Laminas\InputFilter\BaseInputFilter();
$inputFilter->add(clone $requiredInput, 'foo');

$nestedInputFilter = new \Laminas\InputFilter\BaseInputFilter();
$nestedInputFilter->add(clone $requiredInput, 'bar1');
$inputFilter->add($nestedInputFilter, 'bar');

// Date in here is purposely commented out, to land their respective inputs/input filter in `$invalidInput`
$data = [
    // 'foo' => 'ff',
    'bar' => [
        // 'bar1' => 'gg',
    ]
];
$inputFilter->setData($data);
$inputFilter->isValid();

foreach ($inputFilter->getInvalidInput() as $input) {
    echo $input->getName();
}

This code is no beauty, but it shows the problem.

Expected behavior

This is not 100% clear, because I can not say, if the interface is right or the implementation.

The result that I would wish for is, that the InputFilterInterface would type hint InputFilterInterface and InputInterface.


There are two ways of this problem at this point in time.

Either the output of BaseInputFilter::getInvalidInputs() and BaseInputFilter::getValidInputs() is filtered before it is returned.
This would result in a bugfix release with minimal impact on version numbers and people who follow interfaces.

Since we are using PHP and PHP is just growing into following interfaces properly, there would probably be a lot of backlash from just filtering out the InputFilterInterfaces from the above mentioned results.

If the interface was changed, there would need to be a new major release.
This would be the cleanest way to deal with this problem.

[RFC]: Allow empty array validation group

RFC

In my project I use laminas-inputfilter together with laminas-api-tools/api-tools-rest, laminas-api-tools/api-tools-content-validation.
I implemented patchList(), to be able to patch multiple items at once.
The challenge here is how to match change sets with items we need to patch. An obvious idea would be to add an 'id' input to change set, but

  1. This is wrong as we are not going to change an 'id' so it shouldn't be in change set.
  2. This solution is not generic - what if entity has property with different name as PK or entities with composite PKs.
  3. This solution is not reliable because laminas-api-tools/api-tools-content-validation ContentValidationListener::validatePatch() sets only posted properties as validation group. So even if we add an 'id' input and mark it 'required' - it won't be validated hence items without id will be allowed.

Then I looked at JSON Patch (RFC 6902), where the operation objects have "path" property which is subject for an operation. In case of array/collections path includes an index/position of an element. Example:

[
    { "op": "add", "path": "/items/2/name", "value": "New name" }
]

To integrate JSON Patch is big piece of work as it will require different validation and hydration layers.

So my idea is to use the same approach - match change set with entity by its position in the collection. So the example above can be changed to

[
    {},
    {},
    {
        "name": "New name"
    }
]

However, the empty change set is causing a problems for me.

Laminas\InputFilter\BaseInputFilter

  1. setValidationGroup() - won't set an empty array as a validation group
        if (! empty($inputs)) {
            $this->validateValidationGroup($inputs);
            $this->validationGroup = $inputs;
        }
  1. getValues() - will try to get values from all inputs when validation group is empty
    $inputs = $this->validationGroup ?: array_keys($this->inputs);
  1. isValid() - will validate all inputs when validation group is empty
    $inputs = $this->validationGroup ?: array_keys($this->inputs);

My main question - why empty array validation group is not allowed ? Or maybe you would suggest some other approach that would be compatible with Laminas components.

P.S. I extended the Laminas' InputFilter and overridden functions with Null Coalescing Operator (??) instead of Ternary Operator (?:) to solve second and third problems, to solve first problem, I removed the if statement. So far I don't see any problems.

CI failing on documentation build due inline HTML in docs

Bug Report

Q A
Version(s) 2.12.0

Summary

See failure:

Finding: docs/book/application-integration/usage-in-a-laminas-mvc-application.md docs/book/application-integration/usage-in-a-mezzio-application.md
Linting: 2 file(s)
Summary: 2 error(s)
Error: docs/book/application-integration/usage-in-a-laminas-mvc-application.md:131:1 MD033/no-inline-html Inline HTML [Element: pre]
Error: docs/book/application-integration/usage-in-a-laminas-mvc-application.md:131:49 MD033/no-inline-html Inline HTML [Element: code]

https://github.com/laminas/laminas-inputfilter/runs/2122275541?check_suite_focus=true#step:3:286

[WIP] [ZF3] Refactor input filter component

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


Original Issue: https://api.github.com/repos/zendframework/zendframework/issues/4772
User: @bakura10
Created On: 2013-07-02T12:52:46Z
Updated At: 2014-09-28T00:34:50Z
Body
Hi everyone,

This 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.

It 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.

Under 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)

What 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.

Therefore, 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).

To 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:

$inputFilter = new InputFilter();
// … populate the input filter with lot of fields

// You can use the as-usual validation group:
$inputFilter->setValidationGroup(array('username', 'email'));

// But also some more complex rules. Here it only validate fields that contain 'registration-'
// in their names
$validationGroupRegex = new ValidationGroupRegexFilter($inputFilter, '/registration-/i')
$inputFilter->setValidationGroupFilter($validationGroupRegex);

Those 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)

What do you think ? :)

NOTE : not all features have been back ported yet.


Comment

User: @desem
Created On: 2013-07-02T13:33:40Z
Updated At: 2013-07-02T13:33:40Z
Body
And I like it :)
http://www.ivangospodinow.com/simple-form-validator-for-zend-framework-2-forms


Comment

User: @bakura10
Created On: 2013-07-02T13:38:22Z
Updated At: 2013-07-02T13:38:22Z
Body
Thanks :). I change a little bit the logic so now any recursive iterator filter can be specific, so you can use the RecursiveCallbackFilterIterator:

$filter = new RecursiveCallbackFilterIterator($inputFilter, function($value, $key)) {
    if ($key === 'toto') {
        return false;
    }

    return true;
}

This will only validate fields except the one different than "toto".

Pretty powerful :D.


Comment

User: @desem
Created On: 2013-07-02T13:56:33Z
Updated At: 2013-07-02T13:56:33Z
Body
It's interesting. But I would start with a common forum for zend :)


Comment

User: @texdc
Created On: 2013-07-04T19:13:03Z
Updated At: 2013-07-04T19:13:03Z
Body
Please see my notes.


Comment

User: @bakura10
Created On: 2013-07-04T19:23:45Z
Updated At: 2013-07-04T19:23:45Z
Body
I answered :).


Comment

User: @bakura10
Created On: 2013-08-09T09:51:01Z
Updated At: 2013-08-09T09:51:01Z
Body
I tried to add more exciting stuff to this refactor. Now you can add a callback recursive filter to act as a validation group:

$inputFilter = new InputFilter();
$recursiveFilter = new ValidationGroupCallbackFilter($inputFilter, function($value, $key, $iterator) {
   // This get called for each element, so you can reject easily
   if ($key === 'lol') {
       return false;
   }

   return true;
});

$inputFilter->isValid();

Comment

User: @bakura10
Created On: 2013-08-09T10:17:43Z
Updated At: 2013-08-09T10:17:43Z
Body
Based on ocramius feedback, I've renamed the InputFilter class to InputCollection, which may be clearer for people. What do you think?

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.


Comment

User: @texdc
Created On: 2013-08-09T15:06:32Z
Updated At: 2013-08-09T15:06:32Z
Body
I like the 'InputCollection' name! I've just started to use 'CollectionInputFilter', so I understand the issue. Why not just 'CollectionInput'?

On Aug 9, 2013, at 5:17 AM, Michaël Gallego [email protected] wrote:

Based on ocramius feedback, I've renamed the InputFilter class to InputCollection, which may be clearer for people. What do you think?

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.


Reply to this email directly or view it on GitHub.


Comment

User: @bakura10
Created On: 2013-08-10T08:21:41Z
Updated At: 2013-08-10T08:21:41Z
Body
@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…)


Comment

User: @bakura10
Created On: 2013-08-10T08:39:19Z
Updated At: 2013-08-10T08:42:23Z
Body
By 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).

In order not to make the test wrong, no validator nor filters are attached to elements. This test just take into account the traversal time.

With 50 elements

ZF2 :
Input filter construction time: 0.0015020370483398 msec
Traversal time: 0.0062439441680908 msec
Memory consumption: 3 Mb

ZF3 :
Input filter construction time: 0.00066399574279785 msec
Traversal time: 0.0010840892791748 msec
Memory consumption: 2,75 Mb

With 500 elements

ZF2 :
Input filter construction time: 0.010568141937256 msec
Traversal time: 0.058469772338867 msec
Memory consumption: 6 Mb

ZF3 :
Input filter construction time: 0.0047299861907959 msec
Traversal time: 0.0099430084228516 msec
Memory consumption: 3,75 Mb

With 5000 elements

ZF2 :
Input filter construction time: 0.1059877872467 msec
Traversal time: 0.60562801361084 msec
Memory consumption: 37 Mb

ZF3 :
Input filter construction time: 0.048290014266968 msec
Traversal time: 0.10112690925598 msec
Memory consumption: 11,75 Mb

We 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.

Furthermore, all the validation group features, even with complex ones like Callback, come nearly for free with RecursiveIteratorIterator.


Comment

User: @bakura10
Created On: 2013-09-02T15:54:03Z
Updated At: 2013-09-02T15:54:03Z
Body
Hi everyone,

I've taken into account a lot of feedbacks and I've completely rewritten some parts of it.

The 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).

How to use it

Now, input filter component is stateless. This means that there is no longer "isValid" method. Instead, you are expected to use the "validate" method:

// Note: the Factory dependency will be hanlded by a ZF factory
$inputCollection = new InputCollection(new Factory(new InputFilterManager()));

$inputCollection->add(array(
    'name' => 'foo'
));

$data = array('foo' => 'myValue');

$validationResult = $inputCollection->validate($data, $optionalContext);

if ($validationResult->isValid()) {
    $values = $validationResult->getValues();
    // or $rawValues = $validationResult->getRawValues()
} else {
    $error = $validationResult->getErrorMessages();
}

Because validation result is completely decoupled, it can now be serialized or converted to JSON:

json_encode($validationResult); // Output error messages in JSON

Validation result

One 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.

Instead, I've written several methods that make it easy to extend default behaviour:

  • People can extend InputCollection and override the "buildValidationResult", if they need to construct a custom validation result that also contains unknown inputs, for instance.
  • You can also extend "buildErrorMessages", which is called for each input collection.

Also, the validation group feature got more powerful thanks to SPL filters. Iteration is not made using a simple foreach, but using an IteratorIterator:

$iterator         = $this->getValidationGroupFilter();
$iteratorIterator = new IteratorIterator($iterator);
$errorMessages    = array();

/** @var InputInterface|InputCollectionInterface $inputOrInputCollection */
foreach ($iteratorIterator as $inputOrInputCollection) {

SPL filter iterators are automatically executed for us and allow to accept or refuse a specific key.

By 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:

$arrayFilter = new ArrayFilterIterator($inputCollection, array('foo'));
$inputCollection->setValidationGroupFilter($arrayFilter);

Now, only the "foo" input of this input collection will be validated.

It comes with other filter:

$callableFilter = new CallbackFilterIterator($inputCollection, function($key, $value) {});
$regexFilter = new RegexFilterIterator($inputCollection, '/user/');

This 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:

$inputCollection->add(
    'type' => 'Zend\InputFilter\InputCollection',
    'name' => 'top',
    'children' => array(
        array('name' => 'bar')
    ),
    'validation_group_filter' => array(
        'type' => 'Zend\InputFilter\ValidationGroup\RegexFilterIterator',
        'options' => array(
            'regex' => '/blabla/'
        )
    )
));

Performance

I've made some performance test, once again without adding any validators/filters so that the test focus only on input filter:

ZF2:

5 elements,
3 input collections with 5 elements inside

Construction time : 0.00055599212646484 secondes
Traversal time : 0.0064549446105957 secondes
Memory: 3 Mb

50 elements,
10 input collections with 50 elements inside

Construction time : 0.0096118450164795 secondes
Traversal time : 0.11807513237 secondes
Memory: 6,5 Mb

100 elements,
25 input collections with 100 elements inside

Construction time : 0.033029079437256 secondes
Traversal time : 0.51178097724915 secondes
Memory: 19,75 Mb

ZF3

5 elements,
3 input collections with 5 elements inside

Construction time : 0.00034809112548828 secondes
Traversal time : 0.0011918544769287 secondes
Memory: 2,5 Mb

50 elements,
10 input collections with 50 elements inside

Construction time : 0.0085010528564453 secondes
Traversal time : 0.01695990562439 secondes
Memory: 2,75 Mb

100 elements,
25 input collections with 100 elements inside

Construction time : 0.031938076019287 secondes
Traversal time : 0.060458183288574 secondes
Memory: 4,25 Mb


Comment

User: @Ocramius
Created On: 2013-09-02T16:17:17Z
Updated At: 2013-09-02T16:17:17Z
Body
As 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.

Any pluralization of method names in the API shall be removed.


Comment

User: @bakura10
Created On: 2013-09-02T16:22:36Z
Updated At: 2013-09-02T16:24:21Z
Body
Done.

So now InputCollection extends Input, and have the same "validate" method. I didn't change it yet but Input should return a ValidationResult too.

The 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.

As @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.


Comment

User: @bakura10
Created On: 2013-09-02T17:47:51Z
Updated At: 2013-09-02T17:48:47Z
Body
I have integrated several new things:

  • 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.
  • The validation process is a bit complicatd, I'm not sure about hte best way to handle it.

Currently, 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:

Input filter 1
    input 1
    input 2
    input filter 2
        input 3
        input 4

if 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.

This may not be the most efficient way because we need to do the recursion twice... If you have any better idea, please shout!

I also need people to evaluate this: https://github.com/bakura10/zf2/blob/d0cfc2e6643732b1e5e020f6154a6617e7e4d20d/library/Zend/InputFilter/InputCollection.php#L157


Comment

User: @bakura10
Created On: 2013-09-02T19:14:05Z
Updated At: 2013-09-02T19:14:05Z
Body
I'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):

ZF2:

Construction time : 0.47534704208374 secondes
Traversal time : 7.0274820327759 secondes
Memory consumption: 154 Mb

ZF3:

Construction time : 0.48701810836792 secondes
Traversal time : 0.83196616172791 secondes
Memory consumption: 18 Mb


Comment

User: @Netiul
Created On: 2013-09-03T06:58:37Z
Updated At: 2013-09-03T06:58:37Z
Body
Impressive, I must say. Keep up the great work!


Comment

User: @bakura10
Created On: 2013-09-03T09:58:39Z
Updated At: 2013-09-03T09:58:39Z
Body
Thanks @Netiul .

I'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

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.


Comment

User: @bakura10
Created On: 2013-09-03T12:26:28Z
Updated At: 2013-09-03T12:26:28Z
Body
Another massive performance improvement for today (around 20%), because the whole input collection is now traversed only once instead of twice.

This is possible thanks to the previous remark about filtering data, some talk with @Ocramius, and the new stateless that allows interesting optimizations.

First, 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.

About the performance improvement it comes from the reason of my previous comment:

I 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.

Now, 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.

The 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:

Let's assume the following input collection, called "coll", which contains two inputs "a", "b".

When calling validate, the following happens:

  1. The InputCollection validators (if any) are run. The array that the validator will receive will by ["a" => ..., "b" => ...].
    1.1 If invalid, register error messages.
    1.2 If input collection is configured to break on failure, we immediately return an input filter result.
  2. Otherwise, each inputs (a and b) are filtered and validated.
  3. 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).

Does the order make sense to everyone?

Another question I have is: if an input has failed (not valid), should we insert the filtered value into the input filter result ?

Remark: 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.


Comment

User: @dphn
Created On: 2013-09-03T12:35:53Z
Updated At: 2013-09-03T12:35:53Z
Body
Tell me, please, why do not you rename InputFilter to InputSpecification? After all, it contains both filters and validators?


Comment

User: @bakura10
Created On: 2013-09-03T12:37:35Z
Updated At: 2013-09-03T12:37:35Z
Body
??? You're mixing everything again... InputSpecifciation does not exist. No classes have been renamed to InputSpecification.

InputFilter has been however renamed to InputCollection, because it represents more what it is (a collection of inputs).


Comment

User: @dphn
Created On: 2013-09-03T12:38:54Z
Updated At: 2013-09-03T12:38:54Z
Body
Thank you, I get it. So really better.


Comment

User: @weierophinney
Created On: 2013-09-03T16:10:05Z
Updated At: 2013-09-03T16:10:05Z
Body

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.

@bakura10 :

Yes, 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.


Comment

User: @bakura10
Created On: 2013-09-03T16:11:22Z
Updated At: 2013-09-03T16:11:22Z
Body
Ok thanks to confirm this then :).


Comment

User: @dphn
Created On: 2013-09-05T16:25:15Z
Updated At: 2013-09-05T16:25:15Z
Body
I wonder, in the third version will remain a mass func_get_arg () in the constructor of each validator?


Comment

User: @Ocramius
Created On: 2013-09-05T16:35:37Z
Updated At: 2013-09-05T16:35:37Z
Body
@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


Comment

User: @dphn
Created On: 2013-09-05T16:42:16Z
Updated At: 2013-09-05T16:42:16Z
Body
I'm sorry, I just took the most active channel of communication :) Not anymore.


Comment

User: @dphn
Created On: 2013-09-05T22:00:49Z
Updated At: 2013-09-05T22:00:49Z
Body

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.

It 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.


Comment

User: @bakura10
Created On: 2013-09-05T22:02:35Z
Updated At: 2013-09-05T22:02:35Z
Body
Yes, 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).


Comment

User: @dphn
Created On: 2013-09-05T22:11:39Z
Updated At: 2013-09-05T22:11:39Z
Body
I 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?


Comment

User: @bakura10
Created On: 2013-09-05T22:13:49Z
Updated At: 2013-09-05T22:13:49Z
Body
In 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.



Originally posted by @GeeH at zendframework/zend-inputfilter#111

psr-container-stub causes Declaration incompatibile issues on using PHP preload

Bug Report

Q A
Version(s) 2.16.0

Summary

File .psr-container-stub.php causes problems using PHP preload because it has a more strict convetion than psr\container in version 1.1
Removing this file locally solves all related issues. E.g. see issue 23 at laminas-crypt

Workaround

Explicit remove file from preload files

RenameUpload filter breaks UploadFile validator

Bug Report

Q A
Version laminas-validator 2.15.0
Version laminas-filter 2.12.0
Version laminas-inputfilter 2.12.0

Summary

when the RenameUpload filter is added to a field containing the UploadFile validator the UploadFile validator fails and issues an error about a possible attack

see also laminas/laminas-filter#33

the reason for that is that inside the UploadFile a check is performed using the tmp_name to check if the file was uploaded by using the method is_uploaded_file. as the RenameUpload filter is applied before calling the validator the tmp_name has been already changed based on the configuration for the RenameUpload filter and so the check fails as tmp_name is no longer the name to the uploaded file in the $_FILES array

Current behavior

impossible to upload a file when the RenameUpload filter and the UploadFile validator are used on the same field

How to reproduce

configure a field like this (using array notation for configuring a field):

    public function getInputFilterSpecification(): array
    {
        return [
            'logo' => [
                'required' => false,
                'validators' => [
                    [
                        'name' => UploadFile::class,
                    ],
                ],
                'filters' => [
                    [
                        'name' => RenameUpload::class,
                        'options' => [
                            'target' => './public_html/img/uploads/logo',
                            'randomize' => true,
                        ],
                    ],
                ],
            ],
        ];
    }

Expected behavior

the filter and validator can be used together

[RFC] Replace Input with a chain of callbacks.

I started to think the best way of build a custom pipe of filters and validators where you can filter after validation, etc.

I propose replace Zend\InputFilter\Input with a custom chain of methods like A+ promises.

For resume A+ promises have the following main properties along others I won't detail here:

  • has the shape of then(callback success = null, callback error = null)
  • success chain is broken when an exception is raised
  • if error chain return a value then the next success callback continue with the value provided.

So basically the chain do two kind of things. Transformations of the input value and reject the chain if is invalid.

$chain = new Chain();
$chain
  ->then(
    // Tipical filter function
    function($inputValue) use ($context) {
      return $filteredValue;
    }
  )
  ->then(
    // Tipical validation function
    function($inputValue) use ($context) {
      if ( ! isValid($inputValue) {
        throw new ValidationException(); // Break the chain
      }

      // Note MUST return a value, not the isValid boolean.
      // It can return any other object like DateTime or a database Entity
      return $inputValue;
    }
  )

  ->then($hydrate)
  ->then($validate)
  ->then($filter)

  ->then(
    null,
    function ($error) use ($context) {
      if  ($error === null) {
        // chain was invoked without `$inputValue` (i.e. optional field)
        return $fallbackValue;
      }

      throw $error;
    }
  )
  ->then(
    null,
    function ($error) use ($context) {
      // Use the fallback value when input is invalid
      return $fallbackValue ? : throw $error;
    }
  ),
  ->then(
    null,
    function ($error) use ($context) {
      // A fixed error message when input is invalid
      throw new ValidationException("fixed error message");
    }
  )
;

$context = mixed;
$chain->resolve($inputValue);

Options:

  • Reject promise using a reject method callback instead throwing exceptions.

    ->then($reject($errror) {}, $inputValue);

Benefits of this design:

  • Complete customization of the pipe.
  • Avoid create two times the same object, one for validate and another one for normalize (like DateTime)

Thoughts?

/cc @weierophinney, @Ocramius, @bakura10, @zendframework/community-review-team


Originally posted by @Maks3w at zendframework/zend-inputfilter#87

Laminas\InputFilter\Factory::createInputFilter erroneous use of Traversable

Bug Report

On version 2.16

Summary

Right now it's not really a bug, it's a problem with the PHPDoc that leads PHPStorm to report a problem.

Expected parameter of type 'Laminas\InputFilter\CollectionSpecification|Laminas\InputFilter\InputFilterProviderInterface|Laminas\InputFilter\InputFilterSpecification|Traversable', 'array[]' provided

I am passing an array to Laminas\InputFilter\Factory::createInputFilter() and because an array doesn't really implement any of the types listed (InputFilterSpecification|CollectionSpecification|Traversable|InputFilterProviderInterface) it's not officially valid.

Expected behavior

We should be able to pass an array without having warnings from an IDE checking for PHPDoc types. Also, this wouldn't work with multi types checking with PHP 8+. Maybe the iterable pseudo type would be a better type to use here, but I'm not sure.

Inputfilter getValues() returns the field which is not in input data

$specs =  array(
    'title' => array(
        'name'       => 'title',
        'filters' => array(
            array(
                'name' => 'Zend\Filter\StringToLower',
            ),
        ),
    ),
);

$inputFilterFactory = new \Zend\InputFilter\Factory();
$inputFilter = $inputFilterFactory->createInputFilter($specs);
$data = array(
    'title' => 'TEST',
);
$inputFilter->setData($data);
var_dump($inputFilter->getValues());

Expected Output:

array(1) {
  ["title"]=>
  string(3) "test"
}
$data = array(
    'xyz' => 'something',
);
$inputFilter->setData($data);
var_dump($inputFilter->getValues());

Unexpected (or it is intentional?) Output:

array(1) {
  ["title"]=> NULL
}

Originally posted by @metanav at zendframework/zend-inputfilter#66

ZF3 - type issue field for fieldsets or nested input filter

This issue describes a problem with the ZF2 input filtering that I would like to be fixed in the future ZF3 solution for input filtering.

Our preferred solution for building input filters in our application is by using config arrays and generating them through the input filter factory class. We often have nested input filters (for validating field-sets or nested resources). To reuse input filters inside other configs, when using field-sets or when handling complex nested resources it is necessary to add a type field to the config as follows:

$config = array(
    'resource' => array(
        'property_one' => array(
            'name' => 'property_one',
            'required' => false
        ),
        'property_two' => array(
            'name' => 'property_two',
            'required' => false
        ),
        'property_three' => array(
            'name' => 'property_three',
            'required' => false
        ),
        // type key necessary for nested input filter
        'type' => 'Zend\InputFilter\InputFilter'
    )
);

The factory will recognize the type key and sets it as the $class to use during building of the InputFilter. So now we can make our input filter like this:

$inputFilter = $factory->createInputFilter($config);

You can even another class as long as the class implements the InputFilterInterface

Now comes the issue...
It is not uncommon to use the field type for data, in our case we have type as a property for several of our resources. This breaks the whole pattern of configuring our input filters with arrays. If we use the type field for input we can no longer set the input filter class in the config...

I think it is a design mistake to use a key with a common name like type at the same level as the input fields (properties) for setting the class in the config array.
A solution could be to use a more specific key to make it less likely to have conflicts with input field names, for example input_class, or maybe even input_type.
Probably it would even better to move the type field one level up in the config, so conflicts will never be an issue. The config could for example look like this:

$config = array(
    'resource' => array(
        'name' => 'resource',
        'class' => 'Zend\InputFilter\InputFilter', // declaring type
        'config' => array(
            'property_one' => array(
                'name' => 'property_one',
                'required' => false
            ),
            'property_two' => array(
                'name' => 'property_two',
                'required' => false
            ),
            'property_three' => array(
                'name' => 'property_three',
                'required' => false
            )
        )
    )
);

I have no idea about what the design for ZF3 input filtering looks like, but I just want to make sure that this issue would be solved in case it might be done similarly in ZF3.


Originally posted by @Wilt at zendframework/zend-inputfilter#81

InputFilterManager and merging/adding input filters to a base input filter

Q A
New Feature yes
RFC no
BC Break no

Summary

Currently there is no out of the box way to construct an Input filter by InputFilterManager by merging multiple Input Filters without having to construct a factory where each of the merged input filters to be requested from IFM first.

So constructing the final IF is now like this:
Fire IFM for each IF which are going to be merged
Merge all IF into final IF

Eg:
$inputFilter = new StockGetCheckInputFilter();
$inputFilter->merge( $container->get('InputFilterManager')->get(OldEntityCheckInputFilter::class) );
$inputFilter->merge( $container->get('InputFilterManager')->get(SaleInputFilter::class) );
$inputFilter->merge( $container->get('InputFilterManager')->get(InstanceInputFilter::class) );

rather I see more appropriate (by example when subclassing InputFilter) to:
construct final IF into IF init, merging here all other IF
Fire just one time the IFM to actually get the instance

We need a mergeByClass functionality to be used on main IF to merge with the rest of IF's and IFM to be fired one time only...


A similar situation is for adding filters, if we are about to set a name to the "sub-inputfilter" we can't unless we provide an instance, not a class as below:

$this->add([
'type' => InstanceInputFilter::class,
'name' => 'instance'
]);

Of course the below example works, but it's just useless complicating situation as would require addition fire of IFM to build the sub-inputfilter...

$this->add($instanceInputFilter, 'instance');

InputFilterInterface::getMessages() - invalid type hint

Bug Report

Interface InputFilterInterface contains method getMessages with return type hint string[] which is invalid.

BaseInputFilter implementing this interface returns string[][], for example:

array(2) {
    ["field1"]=>  array(1) {
        ["isEmpty"]=> "Field is required"
    }  
    ["field2"]=>  array(1) {
        ["isEmpty"]=> "Field is required"
    }  
}

It's result of BaseInputFilter:;getMessages creating response form fields getMessages:

$messages[$name] = $input->getMessages();

As result developer using phpstan or psalm is told to implement one loop while there should be two.

Allow implementing own validator which (also) validates NotEmpty

Feature Request

Q A
New Feature yes
RFC kinda
BC Break no

Summary

Hey there,

I've seen #10 and the work which has been done in former zendframework package.
I am not sure if @Maks3w is still working on this but I'd like to propose some kind of NotEmptyValidatorImplementedInterface, which tells the \Laminas\InputFilter\Inputobject, that it does not have to add the NotEmpty validator to the ValidatorChain.

Even tho this feature is deprecated and with v3 of this package it would've been necessary to add the NotEmpty validator manually, I have to work with the current implementation and this implementation does not allow me to handle NotEmpty by myself.

So - why do I need this?

We want to keep things simple and specify own validators for all Form Elements.
So in case, one Element needs more than one validator, we just implement that validator as some kind of chain.

This gives us the flexibility of re-using that validator in multiple forms and we could specify dedicated NotEmpty messages for each element (without having to use the existing annotation/logic - I know that there is such a thing ;-) ).

So, in the current implementation, the NotEmpty validator kicks in when the field is empty. But we want to specify own error messages for the NotEmpty validation and we dont want to use the existing Annotation (we are using Annotations) as that would require unreadable annotation specs and further more - when re-using validators we have to copy & paste that to all other implementations.

What would be the next steps?

  1. I'd like to create a PR (or probably a colleague) which provides the new interface NotEmptyValidatorImplementedInterface.
  2. That interface is being verified within Laminas\InputFilter\Input:: injectNotEmptyValidator until v3 removes that method so we can skip the injection without adding NotEmpty manually.
  3. Mark NotEmptyValidatorImplementedInterface as deprecated in the initial implementation

Any vetos here?

Input filter specification and merging

Now it is not possible to use input filter merging on input filters created from specification. Merging saves plenty of time when dealing with many input filters. I suppose extending Factory class to enable merging.

Specification example

$config = [
    'input_filter_specs' => [
         MyInput::class => [
             'foo' => [
             ],
        ],
         MyInput2::class => [
             'merge' => MyInput::class,
             'bar' => [
             ],
        ],
    ],
],

What is your opinion?


Originally posted by @vaclavvanik at zendframework/zend-inputfilter#178

Psalm integration

Feature Request

Q A
QA yes

Summary

As decided during the Technical-Steering-Committee Meeting on August 3rd, 2020, Laminas wants to implement vimeo/psalm in all packages.

Implementing psalm is quite easy.

Required

  • Create a .psalm.xml.dist in the project root
  • Copy and paste the contents from this psalm.xml.dist
  • Run $ composer require vimeo/psalm
  • Run $ vendor/bin/psalm --set-baseline=psalm-baseline.xml
  • Add a composer script static-analysis with the command psalm --shepherd --stats
  • Add a new line to script: in .travis.yml: - if [[ $TEST_COVERAGE == 'true' ]]; then composer static-analysis ; fi
  • Remove phpstan from the project (phpstan.neon.dist, .travis.yml entry, composer.json require-dev and scripts)
Optional
  • Fix as many psalm errors as possible.

Array Input has strange behaviour

I would expect that using an ArrayInput with InputFilter to fail validation when given non-array input, but instead an exception is thrown.

Given that the whole idea is filtering and validation of untrusted input, causing a crash in this situation seems odd to me.

$inputFilter = new InputFilter();
$inputFilter->add([
    'type'       => ArrayInput::class,
    'validators' => [
        ['name' => NotEmptyValidator::class],
    ],
], 'myInput');

$inputFilter->setData(['myInput' => 'Whatever']); // Exception thrown here.
assert($inputFilter->isValid() === false);

InputFilter->add() no longer accepts arrays

Bug Report

Q A
Version(s) ^2.16

Summary

We have our Classes that extend Laminas\InputFilter set up like this documentation:

Psalm shows InvalidArgument whereever we use $this->add() with an array of input specification in the way that is shown in documentation throughout the docs.

ERROR: InvalidArgument - module/MyAPI/src/MyAPI/V1/Rest/Reports/ReportsSearchFilter.php:48:13 - Argument 1 of MyAPI\V1\Rest\Reports\ReportsSearchFilter::add
expects Laminas\InputFilter\InputFilterInterface|Laminas\InputFilter\InputInterface|Traversable|type-alias(Laminas\InputFilter\InputFilterInterface::InputSpecification), array{filters: array{array{name: Laminas\Filter\StringToLower::class}}, name: "file_format", required: false, validators: array{array{name: Laminas\Validator\InArray::class, options: array{haystack: array{"csv", "xlsx", "pdf"}, strict: true}}}} provided

Current behavior

Psalm error throws InvalidArgument where we use InputFilter->add
because an array is no longer an expected parameter.

How to reproduce

  1. With laminas-inputfilter installed with a minimum version of 2.16

  2. create a class that extends InputFilter and add an input specification that is setup as an array
    class ReportsSearchFilter extends InputFilter { public function init(): void { $this->add( [ 'name' => 'account_id', 'required' => false, 'validators' => [ ['name' => Digits::class,] ], ] ); } }

  3. run psalm on the created class ReportsSearchFilter. I can confirm the invalid argument error is thrown in version 4.7, but probably before this version.

  4. You should see an Invalid Argument error in the psalm output

Expected behavior

I expected that $this->add([]); would accept an array. as input since an array is used in so many documentation examples.

In a commit, It looks like a new type was added to the DocBlock. At the same time InputSpecification was added as an input parament, array was removed from it.
see this commit

At first I thought that removing array was intentional, but the above referenced commit has WIP for a title, and none of the documentation indicates that array is no longer accepted input.

Roadmap for V3 and V4

Proposal of roadmap for next major versions.

V3:
V3 should silently fail if any deprecation feature is used. i.e. No file/method removal/rename is allowed.

  • Deprecate Continue If Empty & AllowEmpty
  • Silently ignore continue_if_empty / allow_empty options
  • Let Input validate unknown value (not-set) or know value.
  • Leverage InputFilter from apply complex rules for to determinate if input is valid/invalid
  • Add a resetX method for clear the class state

V4:
V4 does not (currently) restrict any bc break type.

  • Remove deprecated features
  • Fix class inheritance (subclasses must follow the api contract set by the parent) Affected: CollectionInputFilter, ArrayInput and FileInput
  • Make classes stateless
  • Adapted for zend-validator v3

Originally posted by @Maks3w at zendframework/zend-inputfilter#39

Feature/required validator

These allows manage the required message like any other ValidatorInterface element.

Note: While you can add the validator manually the flag setRequired must be set too

  $input = new Input();
  $input->setRequired(true);empty value instead *not set*.
  $input->getValidatorChain()->attach(
      new Zend\InputFilter\Validator\Required(),
      true                             // break chain on failure

  );
  $inputSpecification = [
    'required'   => true,
    'validators' => [
      [
        'break_chain_on_failure' => true,
        'name'                   => 'Zend\\InputFilter\\Validator\\Required',
      ],
    ],
  ];

Note: setRequired(false) may not be enough and you will need remove the validator from the chain.


Originally posted by @Maks3w at zendframework/zend-inputfilter#62

Static analysis tools may not understand typehints using Psalm virtual types

For example (though this may be the only case of this issue in this project, I haven’t checked in detail yet) in InputFilterProviderInterface.php:17, the return type of InputFilterProviderInterface::getInputFilterSpecification() is specified as InputFilterSpecification|CollectionSpecification using the common @return annotation. These virtual types are in turn defined for Psalm in InputFilterInterface.php:38-47 (using @psalm-import-type and @psalm-type). Any tool that does not use Psalm typehints may (should?) fail to understand the return type of the method. For example, PHPStan thinks the type is never, so from its point of view, it’s impossible to implement the method (in a Form or Fieldset subclass, for example).

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Repository problems

These problems occurred while renovating this repository. View logs.

  • WARN: Use matchDepNames instead of matchPackageNames

Awaiting Schedule

These updates are awaiting their schedule. Click on a checkbox to get an update now.

  • Lock file maintenance

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

composer
composer.json
  • php ~8.1.0 || ~8.2.0 || ~8.3.0
  • laminas/laminas-filter ^2.19
  • laminas/laminas-servicemanager ^3.21.0
  • laminas/laminas-stdlib ^3.0
  • laminas/laminas-validator ^2.52
  • laminas/laminas-coding-standard ~2.5.0
  • phpunit/phpunit ^10.5.20
  • psalm/plugin-phpunit ^0.19.0
  • psr/http-message ^2.0
  • vimeo/psalm ^5.24.0
  • webmozart/assert ^1.11
github-actions
.github/workflows/continuous-integration.yml
.github/workflows/docs-build.yml
.github/workflows/release-on-milestone-closed.yml

  • Check this box to trigger a request for Renovate to run again on this repository

[BUG] Newly introduced string check for validation groups in BaseInputFilter is causing problems for CollectionFieldset with integers as Id's

Since 2.16.0 there's an added string check. This check throws an exception when applying a validation group that contains integers instead of strings. The problem will occur when using a CollectionFieldset with entities that have integers as identifiers.

// BaseInputFilter.php
protected function validateValidationGroup(array $inputs)
  {
      foreach ($inputs as $name) {
          if (! is_string($name) || ! array_key_exists($name, $this->inputs)) {
              throw new Exception\InvalidArgumentException(sprintf(
                  'setValidationGroup() expects a list of valid input names; "%s" was not found',
                  (string) $name
              ));
          }
      }
  }

Solution could be to either remove the !is_string() check or to add an additional is_int() check as well ! (is_string($name) || is_int($name))

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.