Skip to content
This repository was archived by the owner on Jan 30, 2020. It is now read-only.

Missing required failure message for CollectionInputFilter #94

Closed
Maks3w opened this issue Feb 12, 2016 · 10 comments
Closed

Missing required failure message for CollectionInputFilter #94

Maks3w opened this issue Feb 12, 2016 · 10 comments

Comments

@Maks3w
Copy link
Member

Maks3w commented Feb 12, 2016

CollectionInputFilter fails without error message when is required but data is empty or not set.

@n3vrax
Copy link

n3vrax commented Jul 18, 2017

Is this fixed? Using the latest version, and it seems indeed that the collection input filter does not have some sort of default message when required is true and an empty array is given. Need to extend the input filter for now.

@tigran-m-dev
Copy link

Issue is still exists. @weierophinney can you confirm this?

@tigran-m-dev
Copy link

Any updates on this? Problem still exists.

@weierophinney
Copy link
Member

Please provide us with a minimal coffee sample that demonstrates the issue; right now, we'd be doing guess work.

@tigran-m-dev
Copy link

Example Input Filter

$factory     = new \Zend\InputFilter\Factory();
$inputFilter = $factory->createInputFilter(
[
    'collection-element' => [
		'type'         => \Zend\InputFilter\CollectionInputFilter::class,
		'required'     => true,
		'input_filter' => [
			'type'  => [
				'required'     => true,
				'validators' => [
					[
						'name'    => \Zend\Validator\Between::class,
						'options' => [
							'min' => 50,
							'max' => 100,
						],
					],
				],
			],
			'price' => [
				'required'     => true,
				'validators' => [
					[
						'name'    => \Zend\Validator\Between::class,
						'options' => [
							'min' => 50,
							'max' => 100,
						],
					],
				],
			],
		],
	],
]
);

First Try, when you have a problem with empty error message

$inputFilter->setData([]);
var_dump($inputFilter->isValid());
var_dump($inputFilter->getMessages());

Second Try with Valid error messages if provided some data

$inputFilter->setData([
	'collection-element' => [
		0 => [

		],
	],
]);
var_dump($inputFilter->isValid());
var_dump($inputFilter->getMessages());

@froschdesign
Copy link
Member

froschdesign commented Dec 5, 2017

Output is:

First try

boolean false

array (size=1)
  'collection-element' => 
    array (size=0)
      empty

Second try

boolean false

array (size=1)
  'collection-element' => 
    array (size=1)
      0 => 
        array (size=2)
          'type' => 
            array (size=1)
              'isEmpty' => string 'Value is required and can't be empty' (length=36)
          'price' => 
            array (size=1)
              'isEmpty' => string 'Value is required and can't be empty' (length=36)

@froschdesign
Copy link
Member

No error message is generated.

Compare the Input class and the CollectionInputFilter class in this case:

if (! $hasValue && $required) {
if ($this->errorMessage === null) {
$this->errorMessage = $this->prepareRequiredValidationFailureMessage();
}
return false;
}

public function isValid($context = null)
{
$this->collectionMessages = [];
$inputFilter = $this->getInputFilter();
$valid = true;
if ($this->getCount() < 1) {
if ($this->isRequired) {
$valid = false;
}
}
if (count($this->data) < $this->getCount()) {
$valid = false;
}
if (! $this->data) {
$this->clearValues();
$this->clearRawValues();
return $valid;
}
foreach ($this->data as $key => $data) {
$inputFilter->setData($data);
if (null !== $this->validationGroup) {
$inputFilter->setValidationGroup($this->validationGroup[$key]);
}
if ($inputFilter->isValid()) {
$this->validInputs[$key] = $inputFilter->getValidInput();
} else {
$valid = false;
$this->collectionMessages[$key] = $inputFilter->getMessages();
$this->invalidInputs[$key] = $inputFilter->getInvalidInput();
}
$this->collectionValues[$key] = $inputFilter->getValues();
$this->collectionRawValues[$key] = $inputFilter->getRawValues();
}
return $valid;

@tigran-m-dev
Copy link

Do you have any updates related this issue?

@weierophinney
Copy link
Member

@developer-devPHP No, no updates at this time.

We actually need to address this by getting some feedback first.

InputFilters do not have a concept of required/optional by default. We tacked it on to the CollectionInputFilter (and, for the 2.8.0 release, the OptionalInputFilter, which allows marking an input filter as optional, vs. required, meaning it can validate if the data set is empty). However, when we did, the only thing we had it affect is whether or not an empty set is valid. In the case that we have an empty set, there is currently no mechanism to provide a message why.

Normally, if data is present, getMessages() will return a nested set of messages, one for each data set:

0 => [
    'foo' => [ /* array of messages */]
],
1 => [
    'bar' => [ /* array of mesages */ ]
],
/* etc. */

The problem area is that the each element of the above array is expected to be an array of key/messages pairs. How, exactly, do we represent a message indicating that a data set was empty in a way that is either consistent in structure, or easily differentiated from the existing structure?

Some thoughts off the top of my head:

  • Use the same format, but use a "meta key", such as __required__:
    [
        0 => [
            '__required__' => [ /* 'values are "required", but none present' messages */ ],
        ],
    ]
  • Use a string value for the set:
    [
        0 => 'Some error message here',
    ],

We need to choose one, but I need input from users as to which one to choose.

Additionally, we need:

  • A default message to display when a collection is required.
  • A mechanism for setting a custom "required" message.
  • Updates to the factories to allow setting that message.

If anybody would like to tackle this, I'd appreciate the help.

@ruzann
Copy link
Contributor

ruzann commented Jul 18, 2018

I have a solution for this. Please have a look into pull request #170

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants