Problem
- The
$format_idparameter tocheck_markup()is optional currently, even though calling code should always know the text format in which the user input has been created. - The
$langcodeparameter defaults to an empty string, even though there is a language code for denoting unspecified language.
Proposed solution
-
Make
$format_idrequired. Still allow to pass NULL to use the fallback format in edge-case scenarios. -
Make
$langcodedefault toLanguageInterface::LANGCODE_NOT_SPECIFIED, so text is always processed with a proper language code.
Spin-off from #569238: Make check_markup() not cache by default:
Discussion revealed that all code totally has to pass a $langcode to check_markup(), so all filters can safely rely on it. Aforementioned issue also contained a patch that tried to fix the invocations we have in core to pass the proper language code for filtered nodes, comments, and all that.
We want to drop the default of '' for the $langcode argument for check_markup(), because implementations should _always_ pass a language code.
| Task | Novice task? | Contributor instructions | Complete? |
|---|---|---|---|
| Implement proposed work | Novice | ||
| Should the issue summary be updated? Form opinion | Novice | Instructions | |
| Doublecheck the change record for the API changes | Novice | Instructions | |
| Review patch to ensure that it fixes the issue, stays within scope, is properly documented, and follows coding standards | Novice | Instructions |
| Comment | File | Size | Author |
|---|---|---|---|
| #58 | 601074-58.patch | 12.07 KB | rpayanm |
Comments
Comment #1
sunThis is quite a challenge to solve, because we have many places (for example comments), where we do not have context (such as in http://api.drupal.org/api/function/comment_submit/7), and then again, even if we would have the context of the node, then translatable fields make it a bit harder to reliably determine the language of the node (since we should assume that a comment is written in the same language of the content that is displayed and commented on -- unless we display a language selector for comments ;).
Comment #2
sunThe overall question boils down to: If there is no direct language context (like for comments), should we take over the language from the "parent" object (here: node)?
Note: I'm fully aware that another issue in the queue adds language context to comments, so please take the question in an abstracted way.
Comment #3
nedjoFor context, passing language to filters was introduced in #319788: Pass language information to filters.
sun, could you expand? Why? Is passing a code like FIELD_LANGUAGE_NONE an option when the language isn't known?
Some objects that we check markup for just don't have a language, even that of a parent. Blocks would be one: block_block_view(). So it's hard to see how we would pass a meaningful language code in every case.
Comment #4
sunThese were the changes from that other patch:
If we would subtract comments from that (assuming that #605630: Comment language administration UI gets committed), then it would boil down to:
- Body of custom blocks (which only have a language through the i18n contrib module currently, unless #430886: Make all blocks fieldable entities is committed)
- Profile module textareas (which may take over the user's preferred language setting)
- User signature (attached to comments) (which may take over the user's preferred language setting)
This review is powered by Dreditor.
Comment #5
sun.core commentedBlargh.
Comment #6
pasqualleComment #7
wim leersNow that #2217877: Text filters should be able to add #attached, #post_render_cache, and cache tags has landed, this will actually be quite trivial fix.
Comment #8
cs_shadow commentedAt all places, where
check_markup()is called without a $langcode, are those supposed to be fixed here only or that'll require a follow-up?Comment #9
wim leersSince there are only a dozen calls to
check_markup()left, I'd say it can and should happen in this issue.Comment #10
cs_shadow commentedCouple of things to notice:
check_markup()has changed. Now$langcodeappears before$format_id, which is still optional while$langcodeis required. Since its an API change, it may require a change notice.check_markup()was called without a language code, in calls tocheck_markup()an empty string is used currently.Comment #13
wim leersThis should be
Drupal\Core\Language::LANGCODE_NOT_SPECIFIED. Also elsewhere where the empty string is used.Comment #14
sunCan we keep the current order of arguments to
check_markup(), please?I almost forgot that the format is still optional to
check_markup(). Making it optional was one of the worst ideas ever. User input is entered with and for a selected text format, it must be filtered and formatted with the same format. You need to know the format to use, or the necessary filter rules won't be applied. If you don't, then the result ofcheck_markup()will be useless garbage.Instead, we should change the signature to make the format required. If necessary, we may allow to pass FALSE to resemble the currently automated fallback format behavior. But the argument should be required.
Comment #15
wim leers#14: I couldn't agree more! :)
Comment #16
wim leersIn fact, I was writing a tweet to you just now, sun, to ask you about precisely that :D
Comment #17
cs_shadow commented@Wim: In cases where langcode is not specified, should i include Drupal\Core\Language or use the fully qualified name for LANGCODE_NOT_SPECIFIED?
Comment #18
cs_shadow commentedComment #19
cs_shadow commentedChanges from patch in #10:
1. Order of parameters retained.
2. Made $format_id required.
3. Pass NULL in places where $format_id was not passed earlier.
4. Pass LanguageInterface::LANGCODE_NOT_SPECIFIED in places where $langcode was either not specified earlier or empty string was used.
Comment #20
sunHm. According to the issue summary (…which happens to have been authored by a former self, though I can't remember), the main intention of the original change proposal appears to be that
check_markup()should not have to deal with a$langcodethat may be an empty string, but instead, always operate on a defined language code.This issue was created long before the language system was improved for D8. Technically, we do not necessarily have to force all callers to pass an explicit language. Thanks to those improvements, today, we could simply change the default value:
The required nature of
$format_idis crystal clear to me, but$langcodelooks & feels pretty optional to me. So:If a caller forgets to pass a language, What Could Possibly Go Wrong?™
Comment #22
cs_shadow commentedOK, now I'm a bit confused about what we're trying to do here. From what I understand if any format_id is not specified, same way as text in the fallback format. And that's precisely why this test is in place: Drupal\filter\Tests\FilterNoFormatTest.
On the other hand, there's no such test in place for default langcode. Something is wrong here.
Comment #23
sunYes, the changes to
$format_idin the latest patch look fine to me. The functionality is still the same, we're just making the parameter required. Therefore, all existing tests still apply (and have been adjusted correctly, upon a cursory look).I guess there is probably no explicit test coverage for passing/omitting a language yet. (AFAIK, we don't have a filter implementation in core that would use or rely on the language. We only have a dummy test filter implementation that simply dumps all filter context variables into the resulting content.)
I'm still not sure whether we need to make the
$langcodeparameter required, or simply make it default toLanguageInterface::LANGCODE_NOT_SPECIFIED. It sounds perfectly acceptable to me to not pass a language code intocheck_markup()— input filters will simply produce language-agnostic output. If you expected language-aware output, then you should pass an explicit language code.In any case, the effective change to HEAD is that
$langcodecan no longer be an empty string, but instead, it is always a language code.In short, I think we should move forward with the signature in #20; i.e., make
$format_idrequired + change the default value of$langcode.Comment #24
wim leers+1
Adjusting title accordingly.
Comment #25
cs_shadow commentedSomeone needs to rewrite the issue summary what we really want (refer to @sun's comment in #23).
Comment #26
cs_shadow commentedPatch with following changes:
1. Function changed as per #20.
2. Removed
LanguageInterface::LANGCODE_NOT_SPECIFIEDfrom calls tocheck_markup()where it was not required.Let's see if testbot agrees.
Comment #27
cs_shadow commentedComment #29
cs_shadow commentedUploading the interdiff in correct format.
Comment #30
sunThanks! Looks great - only some small nits:
Let's keep the 2nd + 3rd sentence of the @param description, but adjust it to state:
If NULL, the fallback format is used; see filter_fallback_format().
The default value should reference the fully-qualified LanguageInterface constant name instead of its internal value.
Updated the issue summary.
Comment #31
cs_shadow commentedFixed the issues in #30.
Comment #32
cs_shadow commentedComment #33
cs_shadow commented@sun: Is anything else required here?
Comment #34
sunThere's no validation for whether the passed language code is a valid language code, and the expected behavior is undefined, and thus no test is added here.
IMO that's fine, since it is not Filter module's job to perform such a validation - the
$langcodeis just simply forwarded into the filter process.Comment #35
alexpottWe need a change record for this one.
Comment #36
cs_shadow commentedDrafted change record: https://www.drupal.org/node/2305883
Comment #37
tim.plunkettI don't understand what is accomplished here. Because of the move to '#type' => 'processed_text', filter_pre_render_text() still allows for a NULL $format_id, and we don't save any code.
Comment #38
wim leers#37: It's indeed possible to still set the format ID to
NULLif you really want to; but the public API should really force you to set an actual format. That's what this is about.However, if you're saying that the default of
'#format' => NULLshould be removed fromfilter_element_info(), then I agree. And if we do that, we'll also want to remove this fromfilter_pre_render_text():And perhaps instead of that, we'll want to throw an exception if
'#format'is not set.Comment #39
tim.plunkettI think we should do both of the things mentioned in #38, that's what I had in mind.
Comment #40
roderikTagging Amsterdam sprint.
filter_pre_render_text() was moved in commit 2c1fe04, but it still seems that the equivalent code block should be removed from core/modules/filter/src/Element/ProcessedText.php (where the code was moved to).
For (an) experienced Drupal/PHP coder but novice contributor(s):
- understand the issue generally
- check what is mentioned in #38/#39
- check my assumption
- do the work
- review the work
- check if this makes changes to the Change Record draft necessary.
Comment #41
roderik(Fix wrong paste of 'contributor tasks' table in summary)
Comment #42
hctomWe will have a look at this...
Comment #43
rupertj commentedHere's a patch that implements the previous patch #31, plus Wim's comments in #38. hctom is working on tests.
Comment #44
hctomHere is a patch that implements previous patches #31 and #43 and adds more changes:
check_plain($string, NULL)butcheck_plain($string, filter_fallback_format())Comment #45
rupertj commentedAttaching interdiff
Comment #46
wim leersCan you re-upload the patch in #44? Testbot is not detecting it because you attached new files while setting the status to NR. Thanks :)
Comment #47
rupertj commentedHere you go.
Comment #49
hctomComment #50
hctomAfter doing a rebase I recreated the patch of #44. See this comment for all applied changes.
Comment #52
wim leersA
Format ID is not setexception is thrown, so the test coverage is uncovering another case wherecheck_markup()is being called with$format_id = NULL:)Should be an easy fix!
Comment #53
hctomUnfortunately this is not such an easy fix, because there are several tests that rely on
#format = NULL(e.g. Drupal\text\Tests\TextWithSummaryItemTest). So I now only additionally addedfilter_fallback_format()to all dynamic#formatvalues and would like to hand over the the checking of the other tests to people who are more deep into the materia, because I do not want to supersede those tests by eventually making the wrong changes to them.Attached you can find a patch containing all my recent changes as well as of course all changes from #31, #43 and #44.
Comment #54
hctomAttached you can find 2 interdiffs. Hope these help?!
Comment #55
hctomComment #56
k4v commentedComment #58
rpayanmre-rolled
Comment #60
Scionar commentedComment #61
Scionar commentedComment #62
disasm commentedI am removing the Novice tag from this issue because there are no easy action items for this task.
I’m using this documentation as a source: https://www.drupal.org/core-mentoring/novice-tasks#avoid
Comment #75
quietone commentedThis was an issue at a bugsmash group triage. After reading the comments and looking at the patch and the existing code, this appear to still be relevant. This does need an Issue Summary update. And it needs tests, see #52 and #53.