-
Notifications
You must be signed in to change notification settings - Fork 824
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
ENH Use FieldValidators for FormField validation #11449
ENH Use FieldValidators for FormField validation #11449
Conversation
cb45d46
to
e733757
Compare
e733757
to
aaba479
Compare
fc9d6db
to
bd8e82d
Compare
687480e
to
b596697
Compare
Have updated SingleSelectField and MultiSelectField to do casting string to int in use getValueForValidation() instead of setSubmittedValue(). This means that the internal value of the field stays and a numeric string
Have update FormField::setSubmittedValue() to alter blank strings to null
Note: in the PRs current state they now give "Must be an integer" validation messages The validation message comes from IntFieldValidator, which TextField and NumericField do not have, though DBInt does. The issue here is that it's above the max size of a signed 64 bit integer which is 9223372036854775807. DBInt has logic in setValue() to cast numeric string to int, however in the case of huge numbers it cannot, so it retains the value a numeric string, hence why it fails validation. Instead of failing to casting if we throw an InvalidArgumentException we just end up with a server error toast which is bad, and, throwing ValidationException in DBInt::setValue() is just wrong. The alternative would be to "truncate" the value to the max PHP int size, but that just defeats the whole purpose of all this validation work. So I don't really know what we can really do here to improve UX. While the message isn't great, it is enforcing data integrity by preventing saving a value to the database which cannot be stored.
Have added created NumericNonStringFieldValidator and moved the 'is_string() && is_numeric() to it, and gotten DBInt / DBDouble to extend that. NumericField uses the NumericStringFieldValidator so it does allow string values
These are all out of scope as this is existing behaviour. The exceptions are coming from DBDate/DBTime::setValue()
Have updated FieldValidationTrait to remove the subfield portion of the name so that the validation message now shows on the composite field
MoneyField is weird to begin with in that the currency field can either be a DropDownField (two or more allowed currencies) a HiddenField (one allowed currency) or a TextField (zero allowed currencies). The issue you had is that when there's only one allowed currency, it becomes a HiddenField. I've updated setValue() to swap out the currency field to a TextField if the currency being set is not in the allowed value list. This isn't ideal and I've rather do this in the MoneyField constructor, but when the form is rendering the value is set via setValue(), rather than as a contructor argument.
Out of scope as these are existing issues, e.g.
|
b596697
to
042bdc6
Compare
0753fe4
to
04e357a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still not done: #11449 (comment)
Numeric field problem
DBInt
with its default scaffolded form (NumericField
) and a value of "99999999999999999999999999999999999999999999999999999999999999999999" now says "Must be a string" as well as "Must be numeric"
It must not be a string, and it is numeric so these error messages are clearly wrong.
Regarding the "Must be numeric" part of this which I mentioned last review, you said
The issue here is that it's above the max size of a signed 64 bit integer which is 9223372036854775807. DBInt has logic in setValue() to cast numeric string to int, however in the case of huge numbers it cannot, so it retains the value a numeric string, hence why it fails validation.
One option to provide a more accurate validation message would be to check:
- Is the original value a numeric string? (
is_numeric('99999999999999999999999999999999999999999999999999999999999999999999')
will returntrue
even though it's larger than the int that can be represented by PHP) - Does casting the value to int result in a value different to the original? (e.g.
(int)$val == $val
will returntrue
if the value can be represented as a PHP int, butfalse
if it cannot)
Still not resolved from previous review
With MoneyField if I enter too many characters the validation message appears at the top of the page, instead of under the relevant form field.
With MoneyField if I enter an invalid currency amount the validation message appears at the top of the page, instead of under the relevant form field.
04e357a
to
220c8e4
Compare
It's following the standard pattern of Update: have changed the
I've added "manual" validation to NumericField to check if It'll now simply give a validation message of "Invalid number", which is the same message if you enter "fish".
As noted here, that was previously resolved, currently works as it should
Even though the PR has added the validation, that's an existing issue. This is currently happened because of the newly added In order for this to show in the correct location |
dc73e81
to
a2c8366
Compare
I don't understand how having the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, didn't start a review before adding comments.
Unresolved conversations:
a2c8366
to
e49e249
Compare
There's a merge conflict |
e49e249
to
1f5f34c
Compare
Updated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Issue #11422