Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input...
Let's add native #pattern FAPI property to provide easy validation Form API fields. Browsers could also use this property to perform client-side validation, but we should ensure it is performed server-side as well.
Comment | File | Size | Author |
---|---|---|---|
#63 | 1174766-html5-pattern-63.patch | 8.41 KB | Niklas Fiekas |
#63 | 1174766-html5-pattern-63-interdiff.txt | 593 bytes | Niklas Fiekas |
#61 | 1174766-html5-pattern-61.patch | 8.41 KB | Niklas Fiekas |
#61 | 1174766-html5-pattern-61-interdiff.txt | 3.2 KB | Niklas Fiekas |
#58 | 1174766-html5-pattern-57.patch | 7.43 KB | Niklas Fiekas |
Comments
Comment #1
Dave ReidComment #2
Dave ReidComment #3
ericduran CreditAttribution: ericduran commentedComment #5
ericduran CreditAttribution: ericduran commentedOoops.
Comment #6
ericduran CreditAttribution: ericduran commentedComment #7
ericduran CreditAttribution: ericduran commentedFixing title.
Comment #8
Everett Zufelt CreditAttribution: Everett Zufelt commentedLooks good, noticed one typo:
+function element_validate_patten($element, &$form_state) {
I assume you wanted element_validate_pattern. This needs to be corrected in two places.
Comment #9
ericduran CreditAttribution: ericduran commentedComment #10
aspilicious CreditAttribution: aspilicious commented"ValidateS" in case this needs a reroll :)
Powered by Dreditor.
Comment #11
ericduran CreditAttribution: ericduran commentedComment #12
Dave Reid1. Do we know why we're using mb_ereg vs preg? From the specs, the JavaScript Pattern production is PERL-based, and for PHP that is the preg* functions.
2. I thought ereg() was deprecated? mb_ereg() is not? That's odd.
3. Should pattern match the value from beginning to end? If so we may need to add boundries to the regex expression.
Comment #13
aspilicious CreditAttribution: aspilicious commented1)
Thats for eric :)
2)
deprecated: http://php.net/manual/en/function.ereg.php
not deprectaed: http://php.net/manual/en/function.mb-ereg.php
3)
"This implies that the regular expression language used for this attribute is the same as that used in JavaScript, except that the pattern attribute must match the entire value, not just any subset (somewhat as if it implied a ^(?: at the start of the pattern and a )$ at the end)."
Yes it should match the entire value
Comment #14
ericduran CreditAttribution: ericduran commented1. Yea, I tried to figure out which one would be closest to the js one -- clearly I #failed.
2. I also found it weird that it wasn't deprecated :-/
3. I think that should probably be left up to the pattern
I'll rerolled a patch with @daves feedback.
Comment #15
ericduran CreditAttribution: ericduran commentedNote, my comment on #14 was a cross post with #13. So I didn't see that comment before replying. FYI.
Comment #16
yched CreditAttribution: yched commentedSubscribe.
Once this is in, we'll want to integrate this to Field API text widgets.
Comment #17
attiks CreditAttribution: attiks commentedsubscribing for #1239910: META: tracking other issues about validation
Comment #18
Jelle_Smissing # before element_validate
22 days to next Drupal core point release.
Comment #19
ericduran CreditAttribution: ericduran commentedUpdating tag
Comment #20
JacineI'm pretty sure this will need tests (?), so tagging for that and cleaning up tags.
Also, here's a handy little site with a bunch of examples to test with (for those of us that are regex stupid):
http://html5pattern.com/
Comment #21
Niklas Fiekas CreditAttribution: Niklas Fiekas commentedAdded testcase, fixed #18 and one more typo.
Remarks:
Comment #22
ericduran CreditAttribution: ericduran commentedyea, the patten process should be added to the other elements.
Also as mention in other comments we should switch to using preg_match.
That looks like all that's needed :)
Comment #23
Niklas Fiekas CreditAttribution: Niklas Fiekas commentedUsing preg_match, added support for tel type element, fixed typo.
Comment #24
ericduran CreditAttribution: ericduran commentedSo the thing that's weird is that webkit browser do this to the pattern:
Which is similar to what @Niklas Fiekas has except they added the Parentheses my guess is for some cases we haven't figure out yet not sure. Any comments welcome.
We'll see what the test says. These are the kinds of issues that makes me which something like qunit was in core ;-)
Comment #25
sun#attributes][title or #description. The element is also barely usable for sighted users without explanation of what exactly can be entered or not. The 'title' only appears as tooltip on hover (and hence, not at all for users on touch devices). In turn, I guess we want to recommend a short user input value syntax pointer in #description, preferred over #attributes][title, but suggest the latter for special scenarios where no #description is possible (compact layout/design, floating input elements, tables, etc).
1) "#process callback for #pattern form element property."
2) "#element_validate callback for #pattern form element property."
Please also add @see pointers between the two.
Stale copypasted phpDoc.
s/element_/form_/
We need to decide what happens if there is a 'pattern' in #attributes already.
To me it looks like we want to use
!isset($element['#attributes']['pattern'])
as an additional pre-condition in this #process callback. That is, because this condition would mean that the element only wants a browser-based validation, without server-side validation.The validate callback should not check whether #pattern is set. If it's invoked, then either the #process callback or something else added it.
No need for this.
1) Use preg_match() instead.
2) As stated and referenced in #13 the actual #pattern value needs to be wrapped:
Furthermore, we need to decide whether to use
preg_quote($element['#pattern'])
here, or whether we require code to supply properly escaped/quoted regular expressions already. (I guess the latter)The user-facing error message could be improved à la
"%name field contains invalid characters."
Replace with:
'access callback' => TRUE
Can be removed.
1) No need for t() here.
2) Rename the submit button to 'Submit'.
This only touches #type textfield?
Comment #26
Niklas Fiekas CreditAttribution: Niklas Fiekas commentedThank you sun.
Comment #27
sunoink! :) I meant to correct the stale phpDoc @params, not remove them. ;)
The second condition needs to be ANDed to the first. If there's a 'pattern' attribute already, then we can only assume it's different to the one in #pattern, and thus, the server-side validation won't pass.
No punctuation in @see
Needs a type-agnostic match:
ugh, this doesn't look right to me.
The html5 spec needs to define the escape character for the regular expression somewhere. If it's not defined, then it's a typically a slash.
But that merely means that modules need to properly escape their regexes. The enforced escaping here makes the most simple expressions invalid; e.g.
'\d+'
becomes'\\d+'
Just use the code of my previous comment, please.
Please remove t() here.
Super-minor: We usually specify #type in elements first.
Comment #28
Niklas Fiekas CreditAttribution: Niklas Fiekas commented:)
I am not sure how to fix the doxygen thing. What was stale about the old comments?
And:
That's not entirely true, because we're talking about the forward slash.
\d
stays\d
and the test verifies that. The point is that/
is in no way special to the browser, because no/
prefix is used. We make it special by doing that and must escape it correctly.What we need:
str_replace(array('\/', '/'), array('/', '\/'), $pattern)
would do that pre-escaping, normalizing \/ to / and then escaping all / to \/.Comment #29
Niklas Fiekas CreditAttribution: Niklas Fiekas commentedTalked with sun in IRC. Using generic form element instead of the c&p form action container now. Pattern escaping should be fine, as well.
Comment #30
sun+++ b/core/includes/form.inc
@@ -3119,6 +3119,59 @@ function form_process_actions($element, &$form_state) {
+ // The browser expects the slash (/) unescaped, but we need it escaped for
+ // preg_match. Aditionally the whole string must match, so we have to
+ // enclose the pattern in ^ and $. We don't have to escape those two
+ // characters, because the browser expects them to be escaped as well.
+ $pattern = '/^(?:' . str_replace(array('\/', '/'), array('/', '\/'), $element['#pattern']) . ')$/';
The str_replace() is what preg_quote() is for.
This also means we can heavily shorten that very long comment.
Comment #31
Niklas Fiekas CreditAttribution: Niklas Fiekas commentedNo, as discussed in IRC:
Comment #32
sunHm. That manual, partial escaping of forwardslashes is still debatable.
While I can see the point of wanting to do the str_replace(), programmers don't really know whether their string is going to be PCRE-quoted afterwards, or whether they're responsible for that in the string they're supplying. It's a custom mixture of both, which is a bit weird.
Let's wait for feedback and reviews from others.
Comment #33
Niklas Fiekas CreditAttribution: Niklas Fiekas commentedSo ... it's like that:
<input pattern="..." />
. That is a Perl-Regex. It must match the whole string, not a part.preg_match()
. Because it must match the whole string we must enclose it in^(?:
and)$
. Any problems?preg_match()
forces us to decide for one magic pattern delimiter to enclose the string in. Which one do we choose?/
), that character is now a special character - and it is not special in the browser. Because the browser must not usepreg_match()
or a delimiter. So that's the reason why we must escape this one character, nothing else.This is what I am trying to explain in the comment. We can probably reword that to make it clearer.
Comment #34
sunSpec: http://www.w3.org/TR/html5/common-input-element-attributes.html#the-patt...
Filed issue: https://www.w3.org/Bugs/Public/show_bug.cgi?id=15904
Comment #35
Niklas Fiekas CreditAttribution: Niklas Fiekas commentedActually it's quite clear, isn't it?
It's just Perl-regexes that we have.
\
for escaping. No new special role for any other character.foo/bar
matches foo/bar./
isn't a special character (just for preg_match(), if we use it as a delimiter).foo\/bar
matches foo/bar, just likefoo\!bar
is the same asfoo!bar
.Comment #36
cosmicdreams CreditAttribution: cosmicdreams commenteda bit lost with this issue: what more needs to be done?
Comment #37
Dave ReidBased on http://html5pattern.com/ it seems that '\' is the control character and I think we should expect people should be writing PRCE expressions and not un-escaped patterns.
Comment #38
Dave ReidI hate the W3C. I wish they could clarify the standard to show that the pattern should be in PRCE form which works for both JavaScript and for PHP.
Comment #39
Dave ReidRelated StackOverflow question: http://stackoverflow.com/questions/9526814/
Comment #40
ericduran CreditAttribution: ericduran commentedI actually don't think is that bad.
We just needed to find a character that would work. I took chx answer and added it to this patch.
The only differences is
instead of
Uploading here for review.
Also should probable add a test with some random characters.
I which UTF-8 was allowed so we could use a snowman -> ☃
Comment #41
Damien Tournoud CreditAttribution: Damien Tournoud commentedHTML5 explicitly states:
and ECMA-262 explicitly states (in the description of
new Regexp()
:So in HTML5 and ECMA-262, there is no such thing as a "unescaped pattern". The pattern is always escaped, and the escape character is always
/
.So as far as I know there is no magic necessary...
'/' . $element['#pattern'] . '/'
is correct. Also, it is *not* correct to add the^
prefix and the$
suffix to the regular expression.What HTML5 says is that:
Which means that we should
preg_match()
on the value and check if the match is equal to the value.Comment #42
Damien Tournoud CreditAttribution: Damien Tournoud commentedSo, supposing that browsers do the right thing and accept
pattern="a\/b"
, there is no reason to care that some of them also accept the brokenpattern="a/b"
. The escaped pattern is more restrictive, so there is no issue in enforcing it in Drupal.Comment #43
Niklas Fiekas CreditAttribution: Niklas Fiekas commentedThe paragraph says what browser should do in their implementation, not what users of the API should do. P is basically the user input, S is what is stored internally, here:
Before that:
If you follow along the syntax tree described before that, you will see that P here can very well be valid with a forward slash.
I.e. if the user gives you
''
then store it as'(?:)'
, if the user gives you'foo/something'
then store it as'foo\/something'
. So that you can later safely use it in the/
-delimiter syntax.Needs review for more discussion.
Comment #44
Damien Tournoud CreditAttribution: Damien Tournoud commentedIndeed, I read that part wrong. So the content of
pattern=
is the Pattern parameter of the Regexp object, so it is not escaped. We do need to escape it following the procedure outlined in the spec.The rest of #41 holds.
Comment #45
Damien Tournoud CreditAttribution: Damien Tournoud commentedAn alternative would be to use bracket-style delimiters that do not actually need escaping.
Back to needs work for this and the full-match described in #41.
Comment #46
Niklas Fiekas CreditAttribution: Niklas Fiekas commentedThanks to @sun for bringing this up. Thanks to @Davereid for talking about this in IRC, to @Damien Tournoud for finding the related paragraph in ECMA and suggesting bracket-style delimiters - I didn't even know about them. They are awesome here. To @xjm for fixing the docs and the error message. To @chx for discussing whether the brackets around the pattern are needed.
Also: #1174620: Add new HTML5 FAPI element: email got in. Yay! Adding pattern support there, too.
Comment #47
Niklas Fiekas CreditAttribution: Niklas Fiekas commented#46: 1174766-html5-pattern-46.patch queued for re-testing.
Comment #49
Niklas Fiekas CreditAttribution: Niklas Fiekas commentedReroll + added pattern support for URLs, since the URL widget got in: #1174630: Add new HTML5 FAPI element: url.
Comment #51
Niklas Fiekas CreditAttribution: Niklas Fiekas commentedDries forgot to commit some files of #1479652: Convert image style config filenames/keys from plural to singular, breaking HEAD. Retesting after jhodgdon reverted that.
git apply --index
++#49: 1174766-html5-pattern-49.patch queued for re-testing.
Comment #52
Niklas Fiekas CreditAttribution: Niklas Fiekas commentedReroll because of #1309394: Process #autocomplete_path for all form elements; remove custom/duplicated code from theme_textfield().
Comment #53
cosmicdreams CreditAttribution: cosmicdreams commentedPatch from #52 looks good. I just have one question:
What is supposed to happen if
$element['#attributes']['pattern'] is set
? Is form_process_pattern supposed to be recursive? Seems like everything blows up in that case.Comment #54
Niklas Fiekas CreditAttribution: Niklas Fiekas commented@cosmicdreams: Mhh ... no, I am not sure what you mean. Here is testcoverage for that: If #attributes => pattern is given, only client side validation will be performed (if the browser supports it) and #pattern will be ignored.
Comment #55
Niklas Fiekas CreditAttribution: Niklas Fiekas commented#54: 1174766-html5-pattern-54.patch queued for re-testing.
Comment #57
Niklas Fiekas CreditAttribution: Niklas Fiekas commentedRerolled because of #1299424: Allow one module per directory and move system tests to core/modules/system.
Comment #58
Niklas Fiekas CreditAttribution: Niklas Fiekas commentedComment #59
sunLooks good to go for me. Thanks for the hard work here, guys!
Comment #60
ericduran CreditAttribution: ericduran commentedThis is almost perfect. The one thing I can see that's missing is the password element. It also supports the pattern attribute. I know core would probably never use it but I just needed it for a project :)
After that this should be good to go.
Comment #61
Niklas Fiekas CreditAttribution: Niklas Fiekas commentedThanks. Yes ... valid point. Should we add it to password_confirm, too? If yes: Only to the first element, or to both?
Comment #63
Niklas Fiekas CreditAttribution: Niklas Fiekas commentedComment #64
ericduran CreditAttribution: ericduran commentedSweet, nice work everyone :)
Comment #65
catchThanks folks. Committed/pushed to 8.x.
Comment #67
Dave ReidFor anyone interested in the very late follow-up for field widgets: #1942914: Add support for #pattern to relevant Field API widgets. Apologies in advance for the ping on a closed issue. *slaps hand*
Comment #68
jibranI went ahead and created the change notice http://drupal.org/node/1953036. IMHO it required change notice.
Sorry for the noise.
Comment #69
amateescu CreditAttribution: amateescu commentedThe change notice looks fine to me.