Problem/Motivation
I have a text_long entity field and when I submit the entity form through AJAX it generates different result then submitting it normally.
The value of this text input field contains at the end :
normal submit - "\r\n"
ajax submit - "\n".
This is a problem and a serious one because there is no workaround and if you do stuff in a submit for an ajax call like building the entity and calling $entity->hasTranslationChanges() then this will return TRUE even if there aren't any changes and this will happen simply because ajax generates different values.
The real problem relies in jquery-form, as it is not ensuring that new lines are encoded as CRLF pairs like browsers are doing it.
jQuery has added support a while ago for this, but jquery-form hasn't adopted it yet. I've opened a pull request about this - https://github.com/jquery-form/form/pull/516
However we still have to figure out how we should ensure that new lines are encoded as CRLF pairs in Drupal. Is it fine to temporary adjust ajax.js or should we have an request subscriber or something like this processing the form values early in the boot process and ensuring new lines are presented as CRLF pairs?
Proposed resolution
Remaining tasks
User interface changes
API changes
Data model changes
Comment | File | Size | Author |
---|---|---|---|
#33 | 2856801-33.patch | 5.57 KB | kfritsche |
#23 | 2856801-23.patch | 5.46 KB | hchonov |
Comments
Comment #2
hchonovWhat I've discovered by setting a breakpoint in index.php is that when submitting normally the form at the end of the string value there is "\r\n" contained, but submitting it through Ajax there is only "\n" contained.
Comment #3
hchonovComment #4
hchonovI've found some related topics:
https://bugs.jquery.com/ticket/9007
https://bugs.jquery.com/ticket/6876
https://github.com/jquery/jquery/commit/eed3803c98bf5c074e40aad12f2e9143...
But it looks like that jquery isn't serializing our input otherwise it should've contained \r\n based on that commit. Unfortunately I am not that good with JS. Could probably someone help me out?
Comment #5
hchonovBased on the application/x-www-form-urlencoded specification all line breaks should be encoded as CRLF pairs. See the links from the previous comment about this.
Comment #6
hchonovoups wrong indentation ..
Comment #7
tstoecklerESLint complains about this, see https://dispatcher.drupalci.org/job/drupal_patches/3937/checkstyleResult/ :
Can't say anything about the patch itself, so leaving at needs review for now, but a re-roll should fix the above.
Comment #8
hchonovSo the real problem relies in jquery-form, as it is not ensuring that new lines are encoded as CRLF pairs like browsers are doing it.
jQuery has added support a while ago for this, but jquery-form hasn't adopted it yet. I've opened a pull request about this - https://github.com/jquery-form/form/pull/516
However we still have to figure out how we should ensure that new lines are encoded as CRLF pairs in Drupal. Is it fine to temporary adjust ajax.js or should we have an request subscriber or something like this processing the form values early in the boot process and ensuring new lines are presented as CRLF pairs?
Comment #9
tstoecklerSo we already have the abstraction layer between
$form_state->getUserInput()
and$form_state->getValues()
so since problem seems to be limited to form submissions whether we could solve it in the Form API itself. If this is in fact limited to textareas, maybe we could even implement this logic in\Drupal\Core\Render\Element\Textarea::valueCallback()
. Then in$form_state->getUserInput()
we would still have the potentially inconsistent value but anything going through$form_state->getValues()
would have a properly normalized value. And it would still be pretty self-contained.Comment #10
hchonovSomething like this? I am fine with this if we are sure that this is the only place where new lines should be formatted with CRLF pairs.
Comment #11
hchonovWe have to use double quotes for the replacement "\r\n" :).
Comment #14
hchonovAnd we actually already have tests there, which had to be adjusted :).
Comment #15
hchonovComment #16
tstoecklerNice! To me this looks like a pretty nice fix, but this should be looked at by a Form API maintainer. Tagging accordingly. Although since this is in the ajax system component, I guess they might not see it?
One minor note on the patch, looks great otherwise:
Maybe we could document why we do this?
Comment #17
hchonovWhile the bug occurs in the ajax subsystem we are ensuring in the form subsystem that we fulfill the HTML specification for textarea form elements, so I think it is fine to move the bug report to the form subsystem.
Comment #18
hchonovComment #19
tstoecklerWow, that comment is awesome, thank you!!!
Comment #20
hchonovRe-roll only.
Comment #21
tstoecklerLooked at this again after a while. The fix is really nice and self-contained and comes with test coverage, so I think it's good to go from my point of view. Subsystem maintainer review wouldn't hurt, but since this doesn't actually touch FormBuilder or anything of the sort I think the risk here is very limited.
Comment #23
hchonovRe-roll after #2863996: Convert web tests to browser tests for ckeditor module, therefore I think it is fine to put the status back to RTBC as set by @tstoeckler in #21.
Comment #24
hchonovHmm .. I've forgotten to put the status back to RTBC.
Comment #26
tacituseu CreditAttribution: tacituseu commentedUnrelated failure
Comment #28
tacituseu CreditAttribution: tacituseu commentedComment #29
tstoecklerI asked @hchonov about why we do the
?: $input
fallback.tl;dr: It makes sense, thus, leaving at RTBC.
Details:
He pointed me to the PHP documentation which says that
NULL
will be returned .So I thought that in case of an error, it would probably be good to fail explicitly (which in this case would be returning
NULL
as the form value) instead of just using the unprocessed string so that one becomes aware of the error and can fix it.@hchonov then pointed me to https://bugs.php.net/bug.php?id=70110 (see #2792877: Symfony YAML parser fails on some strings when running PHP 7 for more information), which could result in such an error leading
preg_replace()
to returnNULL
. In this edge case, where PCRE JIT compilation is on, and someone posts a string which reveals this bug into a textarea, it is presumably better to simply submit the text without normalized newlines into the database instead of failing.This is exactly what the fallback achieves. If someone does want the newlines to be normalized they can turn PCRE JIT compilation off.Comment #30
alexpottThis got fixed upstream https://github.com/jquery-form/form/pull/516 - perhaps we should just pull that it and not have to do this on all text submitted in textareas.
Plus the text in #29 that explains:
the ternary should also be in the code - if we are going to do this.
Comment #32
tstoecklerYeah, I agree with #30 that that is the better fix. Talked to @hchonov (a while back) and he agreed, as well.
I do think it's worth to keep this open for reference, though, until we have upgraded jquery form. So marking postponed on #2899141: jQuery Form Plugin update to latest stable release. Once that is in, this can go straight to "closed (duplicate)".
Comment #33
kfritscheI know its postponed, but we still need and use it, therefore rerolled #23
Just in case some one runs in here ;)
Comment #35
tstoecklerComment #36
tstoecklerPer #32