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

Fix value annotation in isValid method for Regex validator. #179

Closed
wants to merge 4 commits into from

Conversation

h3nnry
Copy link

@h3nnry h3nnry commented Feb 23, 2023

Changed annotation for parameter value in isValid method for Regex validator, from string to string|numerical as long as this method accepts also integer and float parameters.

@h3nnry h3nnry force-pushed the fix-regex-validator-annotation branch from 5be4d5f to 2da3eae Compare February 23, 2023 13:13
src/Regex.php Outdated Show resolved Hide resolved
@@ -107,7 +107,7 @@ public function setPattern($pattern)
/**
* Returns true if and only if $value matches against the pattern option
*
* @param string $value
* @param string|numeric $value
Copy link
Member

Choose a reason for hiding this comment

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

If we accept non-string values, a string cast is probably needed for acceptable conversions

Copy link
Author

Choose a reason for hiding this comment

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

added.

Copy link
Member

Choose a reason for hiding this comment

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

IMO, isValid() should always accept mixed as per the interface.

Copy link
Author

@h3nnry h3nnry Mar 3, 2023

Choose a reason for hiding this comment

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

In my opinion better to avoid mixed type.

@h3nnry h3nnry force-pushed the fix-regex-validator-annotation branch from af716b8 to cee7dc0 Compare February 23, 2023 19:08
Comment on lines +120 to +122
if (is_int($value) || is_float($value)) {
$value = (string) $value;
}
Copy link
Member

Choose a reason for hiding this comment

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

Since new logic was added, we should have a test covering this scenario?

Copy link
Author

Choose a reason for hiding this comment

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

added

Copy link
Member

@internalsystemerror internalsystemerror Mar 2, 2023

Choose a reason for hiding this comment

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

I have reservations against allowing floats for the same reasons it was removed from moneyphp (I believe by @Ocramius), and as was discussed here: moneyphp/money#650.

It would then be the responsibility of the user to handle that casting.

$regExValidator->isValid((string)$value);

Maybe there needs to be a ToString filter for use with laminas/laminas-inputfilter?

Although not as immediately important as with a package named money, since this is for validation I could see some users unknowingly making a mistake. Thoughts? Is this an overreaction?

Copy link
Member

Choose a reason for hiding this comment

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

Ooooh, that is a good point! A floating point number may indeed cast to something unexpected 🤔

Copy link
Member

Choose a reason for hiding this comment

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

@internalsystemerror

Maybe there needs to be a ToString filter…

See: laminas/laminas-filter#98

Copy link
Author

Choose a reason for hiding this comment

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

In my opinion it's user who need to avoid scientific notation, and if he's ok with it it need to created the correct pattern.

Copy link
Member

Choose a reason for hiding this comment

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

A (string) cast of a float value may lead to the scientific notation regardless.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah - I get that concern, but there's already an implicit cast to string during preg_match anyhow. I think the only way to "fix" this is to reject int|float up-front and I don't think we can get away with that due to existing behaviour.

Perhaps a note should be added to remove the int|float checks for the next major and fail non-string input, making it the callers responsibility to cast if necessary, leaving the current implementation broken in the same predictable way.

My understanding is that this patch does nothing to change the existing behaviour, i.e:

preg_match('/^\d{1}\.\d{2}$/', 0.01); // 1
preg_match('/^\d{1}\.\d{2}$/', '0.01'); // 1
preg_match('/^\d{1}\.\d{2}$/', 35 + -34.99); // 0
preg_match('/^\d{1}\.\d{2}$/', '35' + '-34.99'); // 0

Copy link
Member

@internalsystemerror internalsystemerror Mar 3, 2023

Choose a reason for hiding this comment

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

If it's currently broken because there is no parameter type hint then I don't think we can "fix" it. But we CAN prevent people from making the mistake if they're intending to use static analysis.

I was thinking we use @param string|int instead of @param string|int|float more than any specific handling using is_float. Though now that consider I @gsteel's position, I guess validators will always be required to accept a value of mixed type, so should it be throwing an error (by setting a parameter type hint in a future major), or should it just be returning false?

If the latter then it should stay as mixed and then if(!is_string($value) && !is_int($value)) { return false; }?

Copy link
Member

Choose a reason for hiding this comment

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

Beware that the interface does indeed say mixed:

* @param mixed $value
* @return bool
* @throws Exception\RuntimeException If validation of $value is impossible.
*/
public function isValid($value);

@h3nnry h3nnry force-pushed the fix-regex-validator-annotation branch from 9868322 to d79db66 Compare March 2, 2023 16:59
Copy link
Member

@Ocramius Ocramius left a comment

Choose a reason for hiding this comment

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

LGTM, although asking for another review by others.

Copy link
Member

@internalsystemerror internalsystemerror left a comment

Choose a reason for hiding this comment

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

#179 (comment) is my only reservation. But if people think that's overcautious then I'm happy to approve.

@@ -107,7 +107,7 @@ public function setPattern($pattern)
/**
* Returns true if and only if $value matches against the pattern option
*
* @param string $value
* @param string|numeric $value
Copy link
Member

Choose a reason for hiding this comment

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

IMO, isValid() should always accept mixed as per the interface.

Comment on lines +120 to +122
if (is_int($value) || is_float($value)) {
$value = (string) $value;
}
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we can restrict the input type of the validator beyond mixed to begin with, so I think that the string cast is necessary to preserve existing behaviour. In hind-sight, the first conditional should have failed on any non-string value, but as it doesn't, at least the cast prevents int|float reaching preg_match

test/RegexTest.php Outdated Show resolved Hide resolved
@gsteel gsteel assigned Ocramius and unassigned gsteel Mar 3, 2023
@gsteel gsteel removed this from the 2.31.0 milestone May 19, 2023
@gsteel gsteel mentioned this pull request Jun 21, 2024
@gsteel
Copy link
Member

gsteel commented Jun 25, 2024

Thanks for your work here @h3nnry - #280 has been merged into 3.0.x, so I think this PR is no longer relevant.

@gsteel gsteel closed this Jun 25, 2024
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.

5 participants