Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Validator] Add constraint on unique elements collection(Assert\Unique) #26555

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

Merged
merged 2 commits into from
Mar 25, 2019

Conversation

zzenmate
Copy link

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? no
Fixed tickets #26535
License MIT
Doc PR symfony/symfony-docs#...

@zzenmate
Copy link
Author

zzenmate commented Mar 15, 2018

Please, review feature.
If realization constraint is ok I will write tests and doc for this feature.

@zzenmate zzenmate changed the title [Validator] Add UniqueCollection constraint and validator [Validator] Add constraint on unique elements collection(Assert\UniqueCollection) Mar 15, 2018
return;
}

if (!is_array($value) && !($value instanceof \Traversable && $value instanceof \ArrayAccess)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Scrap ($value instanceof \Traversable && $value instanceof \ArrayAccess) and replace with !$value instanceof \IteratorAggregate. It's apparently interface of Traversable highest up in a chain which guarantees iterator is rewindable


$collectionElements = [];
foreach ($value as $element) {
if (in_array($element, $collectionElements)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

third argument to true is important here to avoid obscure bugs https://3v4l.org/9QGNo

public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof UniqueCollection) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\UniqueCollection');
Copy link
Contributor

Choose a reason for hiding this comment

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

We can use ::class now

*
* @author Yevgeniy Zholkevskiy <[email protected]>
*/
class UniqueCollection extends Constraint
Copy link
Contributor

Choose a reason for hiding this comment

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

Symfony constraints don't tend to add such suffix. See e.g. constraint "All". Should be just Unique. Would be in line with #9888 as well.

@nicolas-grekas nicolas-grekas added this to the 4.1 milestone Mar 16, 2018
@zzenmate zzenmate changed the title [Validator] Add constraint on unique elements collection(Assert\UniqueCollection) [Validator] Add constraint on unique elements collection(Assert\Unique) Mar 16, 2018
@ostrolucky
Copy link
Contributor

Would wait for a symfony team member to confirm, but I think this is pretty straight forward and feature should be accepted.

status: needs review

return;
}

if (!$value instanceof \IteratorAggregate) {
Copy link
Contributor

Choose a reason for hiding this comment

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

is_array part must stay, I wanted to change second part of condition only. This won't work with arrays now.

@nicolas-grekas
Copy link
Member

@zzenmate please check fabbot's failure

Copy link
Contributor

@ogizanagi ogizanagi left a comment

Choose a reason for hiding this comment

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

Thanks for your contribution!

foreach ($value as $element) {
if (in_array($element, $collectionElements, true)) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ value }}', $this->formatValue($value))
Copy link
Contributor

Choose a reason for hiding this comment

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

Additionnally to fabbot reported issues, there is too much indentation here:

                $this->context->buildViolation($constraint->message)
-                              ->setParameter('{{ value }}', $this->formatValue($value))
-                              ->setCode(Unique::IS_NOT_UNIQUE)
-                   ->addViolation();
+                   ->setParameter('{{ value }}', $this->formatValue($value))
+                   ->setCode(Unique::IS_NOT_UNIQUE)
+                   ->addViolation();

return;
}

if (!is_array($value) && !$value instanceof \IteratorAggregate) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I've seen @ostrolucky 's #26555 (comment), but actually, we don't need ArrayAccess here, right?
So !is_array($value) && !$value instanceof \Traversable would be enough.

Copy link
Contributor

Choose a reason for hiding this comment

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

I thought so too until recently. Apparently this is considered too unsafe, see #24577 (comment) and #25506

Copy link
Contributor

Choose a reason for hiding this comment

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

So, IIUC that's an issue we already have with AllValidator then?

Was it already raised somewhere and do we need to add a deprecation to warn about this issue if $value isn't implementing IteratorAggregate?

Copy link
Contributor

Choose a reason for hiding this comment

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

Dunno, what do you say @nicolas-grekas? I guess there should be an RFC to decide how to move forward in consistent way and let others to speak their mind about this.

Copy link
Member

Choose a reason for hiding this comment

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

I'd keep it as it is.

$collectionElements[] = $element;
}
}
}
Copy link
Member

Choose a reason for hiding this comment

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

missing newline at end of file

@zzenmate
Copy link
Author

status: needs review

Copy link
Contributor

@ostrolucky ostrolucky left a comment

Choose a reason for hiding this comment

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

This test suite is IMO too noisy. Check e.g. RegexValidatorTest to learn how to utilize dataProviders to shrink this.

@zzenmate
Copy link
Author

@ostrolucky Thank you for your advice! I have done it.
status: needs review

}

if (!is_array($value) && !$value instanceof \IteratorAggregate) {
throw new UnexpectedTypeException($value, 'IteratorAggregate');
Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry but I think we should not throw here, to avoid issues like this one #26463

@nicolas-grekas nicolas-grekas modified the milestones: 4.1, next Apr 20, 2018
Copy link
Member

@xabbuh xabbuh left a comment

Choose a reason for hiding this comment

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

with a minor comment

*/
class Unique extends Constraint
{
const IS_NOT_UNIQUE = '7911c98d-b845-4da0-94b7-a8dac36bc55a';
Copy link
Member

Choose a reason for hiding this comment

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

public const

return;
}

if (!is_array($value) && !$value instanceof \IteratorAggregate) {
Copy link
Member

Choose a reason for hiding this comment

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

I'd keep it as it is.

@xabbuh
Copy link
Member

xabbuh commented Sep 24, 2018

oh, please also mention the new constraint in the changelog of the component

@nicolas-grekas
Copy link
Member

Friendly ping @zzenmate, could you please add an entry in the changelog file of the component?

@nicolas-grekas
Copy link
Member

And create a doc issue/PR also please?

@nicolas-grekas nicolas-grekas force-pushed the unique-collection-constraint branch from ad8e7d4 to bfa3278 Compare March 13, 2019 15:46
@nicolas-grekas nicolas-grekas force-pushed the unique-collection-constraint branch from bfa3278 to d0eb13e Compare March 13, 2019 15:48
@nicolas-grekas
Copy link
Member

nicolas-grekas commented Mar 13, 2019

Rebased, ready.

@fabpot
Copy link
Member

fabpot commented Mar 25, 2019

Thank you @zzenmate.

@fabpot fabpot merged commit d0eb13e into symfony:master Mar 25, 2019
fabpot added a commit that referenced this pull request Mar 25, 2019
…on(Assert\Unique) (zenmate, nicolas-grekas)

This PR was merged into the 4.3-dev branch.

Discussion
----------

[Validator] Add constraint on unique elements collection(Assert\Unique)

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | no    <!-- please add some, will be required by reviewers -->
| Fixed tickets | #26535
| License       | MIT
| Doc PR        | symfony/symfony-docs#... <!-- required for new features -->

<!--
Write a short README entry for your feature/bugfix here (replace this comment block.)
This will help people understand your PR and can be used as a start of the Doc PR.
Additionally:
 - Bug fixes must be submitted against the lowest branch where they apply
   (lowest branches are regularly merged to upper ones so they get the fixes too).
 - Features and deprecations must be submitted against the master branch.
-->

Commits
-------

d0eb13e Rebase and update to latest CS
fc66683 Add UniqueCollection constraint and validator
@fabpot
Copy link
Member

fabpot commented Mar 25, 2019

Translation added in e863621. Typo in the error message fixed in e3d42a9.

}

if (!\is_array($value) && !$value instanceof \IteratorAggregate) {
throw new UnexpectedValueException($value, 'array|IteratorAggregate');
Copy link
Contributor

Choose a reason for hiding this comment

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

why not iterable?

Copy link
Contributor

Choose a reason for hiding this comment

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

see review chain

Copy link
Contributor

Choose a reason for hiding this comment

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

I thought so too until recently. Apparently this is considered too unsafe, see #24577 (comment) and #25506

?

was it a blocker for this PR?

Copy link
Contributor

Choose a reason for hiding this comment

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

i can pass a broken/unrewindbable iterator as aggregate just as easy. But i cant pass a working iterator/iterable directly. That's poor DX IMHO.

Copy link
Contributor

Choose a reason for hiding this comment

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

Consequencies of this validator being applied on non-rewindable iterators are much bigger than in #25506 so yes (generally, after validator validates the data, data is processed)

*
* @author Yevgeniy Zholkevskiy <[email protected]>
*/
class Unique extends Constraint
Copy link
Contributor

Choose a reason for hiding this comment

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

UniqueCollection?

@nicolas-grekas nicolas-grekas modified the milestones: next, 4.3 Apr 30, 2019
@fabpot fabpot mentioned this pull request May 9, 2019
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.