Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Validator] Propagate embedded groups for collection validator #25888

Closed
wants to merge 1 commit into from
Closed

[Validator] Propagate embedded groups for collection validator #25888

wants to merge 1 commit into from

Conversation

blazarecki
Copy link

Q A
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #17675
License MIT
Doc PR no

This PR fix the issue describe in #17675
This PR is related to #17696

@hhamon
Copy link
Contributor

hhamon commented Jan 23, 2018

/propage/propagate/ in your commit message :)

@xabbuh xabbuh added this to the 2.7 milestone Jan 23, 2018
@@ -44,12 +44,12 @@ public function validate($value, Constraint $constraint)
$validator = $context->getValidator()->inContext($context);

foreach ($value as $key => $element) {
$validator->atPath('['.$key.']')->validate($element, $constraint->constraints);
$validator->atPath('['.$key.']')->validate($element, $constraint->constraints, $constraint->groups);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be $context->getGroup() too?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To give more context: This implementation suffers the same implications as discussed in #23480 (comment).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Composite constraint is special, All and Collection inherit it.
The rules are explained here https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Validator/Constraints/Composite.php#L34-L48, we need to not break them.
So I tend to agree with @xabbuh that we should not just rely on the groups public property of nested constraints to resolve any issue.

@@ -60,10 +60,10 @@ public function validate($value, Constraint $constraint)
$context->getValidator()
->inContext($context)
->atPath('['.$field.']')
->validate($value[$field], $fieldConstraint->constraints);
->validate($value[$field], $fieldConstraint->constraints, $fieldConstraint->groups);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above

@backbone87
Copy link
Contributor

can we please close either #23480 or this one? both address the same problem and propose the same fixing strategy.

Using $contraint->groups is wrong. You need to use $context->getGroup(), because that is the group that is actually validated in the current call of the contraints validator.
The following produces a violation with this PR, but it should not:

$contraint = new Collection([
  'fields' => [
    'key' => new Length(['min' => 6, groups => ['b']]),
  ],
  'groups' => ['a', 'b'],
]);
$validator->validate([ 'key' => 'value' ], $contraint, 'a');

From my point of view we have a 2 possibilities:

  1. Deprecate/disallow validation groups in nested contraints, because they dont work correctly and document the use case presented in [Validator] All validation groups are not used on embedded constraints in a collection constraint #17675 and [Validator] Incorrect collection validation with different groups #23479 to use multiple Collection and All constraints (something like here [Validator] All validation groups are not used on embedded constraints in a collection constraint #17675 (comment) but with groups moved to the composite contraint)
  2. Disable caching for composite contraints (and optionally deprecate/disallow validation groups on composite contraints)
  3. Change the caching strategy

@HeahDude
Copy link
Contributor

I'm not sure there is really an issue here, just a misusage while not being aware of https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Validator/Constraints/Composite.php#L34-L48 (documentation issue).

Actually #17675 (comment), could be written:

    /**
     * @Collection(
     *     fields={
     *          "foo" = {
     *              @NotBlank(groups={"foo"}),
     *              @Length(min="2", groups={"bar"}),
     *              @Length(min="4", groups={"baz"}),
     *          }
     *     },
     *    groups={"foo", "bar", "baz"}
     * )
     */

And this should be the way to go IMHO.

@backbone87
Copy link
Contributor

This doesnt work with grp sequences

@HeahDude
Copy link
Contributor

So this is what needs to be fixed :). Could you please update your tests here @blazarecki?

@blazarecki
Copy link
Author

Yes I'll do that.

@backbone87
Copy link
Contributor

backbone87 commented Jan 25, 2018

@blazarecki imho there is nothing wrong with grp sequences. the possible fix path are described in my comment above. Despite the comment in https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Validator/Constraints/Composite.php#L34 different grps for composite contraint and nested constraints just dont work.

If we dont want to change anything, then my proposed solution 1 is a good way.
If we want to support grps on nested contraints correctly, then contraints must be able to opt out of caching (my solution 2). Maybe with a marker interface or a contraint setting (a setting that is decided at dev time of the contraint). This also requires, that a contraint, that does not get cached, never does any validation of its own, but depends for the decision "pass" or "not pass" entirely and only on its nested contraints.

@fabpot fabpot modified the milestones: 2.7, 2.8 May 28, 2018
@fabpot
Copy link
Member

fabpot commented May 28, 2018

@HeahDude As you started to work on this one (at least commenting on it) I need your help for the next steps (related to #23480 as well)?

@artursvonda
Copy link
Contributor

Any help needed with this one? Comments seem to be addressed and tests passing.

@blazarecki
Copy link
Author

@artursvonda tell me if I need to change something.

@artursvonda
Copy link
Contributor

Just wanted to bump up the ticket since comments already seem to be addressed. @fabpot @HeahDude ?

Copy link
Contributor

@HeahDude HeahDude left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As said in my previous comment, there is no issue to fix as is.

Tests must be adapted to check if group sequences fail in some way as @backbone87 claimed.
Otherwise we can close here.

@@ -44,12 +44,12 @@ public function validate($value, Constraint $constraint)
$validator = $context->getValidator()->inContext($context);

foreach ($value as $key => $element) {
$validator->atPath('['.$key.']')->validate($element, $constraint->constraints);
$validator->atPath('['.$key.']')->validate($element, $constraint->constraints, array($context->getGroup()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only subsets are allowed on traversable node. This would be a broken feature not a bug fix.

new Range(array('min' => 1, 'groups' => 'bar')),
),
),
'groups' => 'foo',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is wrong and breaks BC. Groups should be array('foo, 'bar') here, and the test would be green already, without the changes introduced in this PR.

array(array('foo'), array('foo', 'bar'), array('foo', 'bar')),
array(array('foo'), array('bar'), array('foo', 'bar')),
array(array('foo'), array('foo'), array('foo', 'bar')),
array(array('foo'), array('foo'), array('foo')),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're passing foo and bar for every case of collection groups above, but not here, while there is no bar group on any entry.
Are there some cases actually failing before your changes?

),
),
)
));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is no group set on the collection contraint, group on entry should never be validated (since it won't ever be a subset).

new Range(array('min' => 5, 'minMessage' => 'Group bar', 'groups' => 'bar')),
),
)
));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

@Aliance
Copy link
Contributor

Aliance commented Aug 15, 2018

As said in my previous comment, there is no issue to fix as is.

@HeahDude so in my issue #23479 (and related pr #23480) there is no issue too, you think?

@xabbuh
Copy link
Member

xabbuh commented Dec 7, 2018

Thank you all for your input and working on this. This is finally going to be fixed in #29499.

@xabbuh xabbuh closed this Dec 7, 2018
stof added a commit that referenced this pull request Dec 8, 2018
This PR was merged into the 3.4 branch.

Discussion
----------

[Validator] Fixed grouped composite constraints

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #17675, #25888, #23480
| License       | MIT
| Doc PR        | ~

From Lisbon :). Thanks @stof, @xabbuh for your help to finally fix this old issue.

Commits
-------

b53d911 [Validator] Fixed grouped composite constraints
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants