updated as of comment #18
Problem/Motivation
The language.negotiation
config values have helper methods to get and set their values that are used in both runtime and editing configuration. This means that overrides can bleed into stored configuration.
language_negotiation_url_prefixes()
language_negotiation_url_prefixes_update()
language_negotiation_url_prefixes_save()
language_negotiation_url_domains()
language_negotiation_url_domains_save()
Proposed resolution
Per comment #4, the helper methods listed above should not be used to set config. Instead, config for language negotiation should be set directly using editable config factories. Also, per #7.2, the following two functions should be removed, as they are not necessary:
language_negotiation_url_domains_save()
language_negotiation_url_prefixes_save()
Remaining tasks
Task | Novice task? | Contributor instructions | Complete? |
---|---|---|---|
Update the issue summary | Instructions | ||
Add automated tests | Instructions |
User interface changes
None.
API changes
The following 2 global functions are removed:
language_negotiation_url_domains_save()
language_negotiation_url_prefixes_save()
Use ConfigFactory::getEditable() instead.
Comment | File | Size | Author |
---|---|---|---|
#31 | 2403229-lng-leak-31.patch | 8.61 KB | penyaskito |
Comments
Comment #1
Gábor HojtsyComment #2
andypostlanguage_negotiation_url_prefixes()
language_negotiation_url_prefixes_update()
language_negotiation_url_prefixes_save()
language_negotiation_url_domains()
language_negotiation_url_domains_save()
Comment #3
andypostSuppose all this API functions doc-blocks should be updated to point about "careful usage because of overrides"
Also there's 2 @todo in code for that issue
Comment #4
Gábor HojtsyAt least they should not be used in setting config. The functions to set may go away. The forms (should) ensure to load editable config and save back to it.
Comment #5
andypostSuppose we should remove all
*save()
andlanguage_negotiation_url_prefixes_update()
Also it looks that this config should have no overrides because it's language independent (no reason to translate a list of domains or url prefixes) so site-wide
Patch adds comments and initial usage clean-up while I skimmed code
Comment #6
andypostUsage:
language_negotiation_url_prefixes_update()
1) new language saved
\Drupal\language\Entity\ConfigurableLanguage::postSave()
2) site default language changed
\Drupal\language\EventSubscriber\ConfigSubscriber::onConfigSave
language_negotiation_url_prefixes_save()
language_configurable_language_delete
and from update abovelanguage_negotiation_url_domains_save()
when configurable language added or deletedComment #7
Gábor HojtsyThere may still be other overrides based on domain or organic group or whatever other condition, overrides are not necessarily language specific only. The getters should still return possibly overridden data.
These look great. IMHO we should remove the save functions entirely to avoid overridden data saved.
Comment #8
andypostReverted getters.
Removed the save functions, thinking to remove
language_negotiation_url_prefixes_update()
The rest of usage is
Also looks that
language_configurable_language_insert()
&language_configurable_language_delete()
could be moved to\Drupal\language\Entity\ConfigurableLanguage::postSave
andpostDelete()
methodsComment #9
Gábor HojtsyThe proposed changes all look great now. AFAIS language_negotiation_url_prefixes_update() may still very well leak overrides in. Although you fixed how it saves now, it still gets its source data from language_negotiation_url_prefixes(). It should either be removed or at least get its data from the editable configuration.
No concerns with the patch other than that.
Comment #10
andypostHere's re-roll and clean-up - no reason to set default language when the same, but maybe it's for separate issue too?
@Gabor no, it uses editable now but maybe we really should get prefixes after override?
is fine?
Comment #11
Gábor HojtsyRight this looks good, sorry for not figuring it out from the diff earlier.
This change is not even remotely related to config overrides.
So #8 looks like a good patch but the changes in #10 are too much for this scope AFAIS. Wanna post it again? :)
Comment #12
andypostYep, so here's a re-roll of #8
I see no way to add tests for that
Also filed #2462729: Move ConfigurableLanguage hook implementations in language module to the entity
Comment #13
Gábor HojtsyAs for tests, I think the test can set $GLOBAL['config'] value for language.negotiation to something custom and call the language_negotiation_url_prefixes_update() function and assert that the override did not end up in config.
As for testing the forms, you can save a language override (it does not matter that you override things that are otherwise not translatable) and call the form to observe the values are not used. That would also prove that NegotiationUrlForm is not yet immune to overrides, language_negotiation_url_prefixes() and language_negotiation_url_domains() are still used in the buildform (just found while looking at the code to suggest tests).
Marking as needs work for fixing the use of language_negotiation_url_prefixes() and language_negotiation_url_domains() in NegotiationUrlForm and for tests.
Comment #14
andypostFixed usage in form, will try tests
Comment #15
Gábor HojtsyAmazing, thanks! Sending to testbot.
Comment #16
Gábor HojtsyBack to needs work for lack of new tests then.
Comment #17
YesCT CreditAttribution: YesCT commentedComment #18
YesCT CreditAttribution: YesCT commentedadded templates to issue summary.
Comment #19
robertdbailey CreditAttribution: robertdbailey at Lingotek commentedSaw this one sitting idle for a while, so I updated issue summary (proposed resolution) according to what appears to be happening in the patch.
Comment #20
robertdbailey CreditAttribution: robertdbailey at Lingotek commentedComment #21
robertdbailey CreditAttribution: robertdbailey at Lingotek commentedFor the tests, I could use some help in documenting some steps to reproduce:
For setting and then checking the global config value for language negotiation, I'm trying things like this:
$GLOBALS['config']['language.negotiation'] = array('url.prefixes' => array('en' => 'whatever'));
language_negotiation_url_prefixes_update();
dpm(\Drupal::config('language.negotiation')->get('url.prefixes'));
I think I need a different data type to initialize the language-negotiation global config variable. I haven't been able to see the way to make runtime changes also modify stored configuration.
Comment #22
Gábor Hojtsy@robertdbailey: you can write a test that puts that to settings.php on install and then invokes the URL of NegotiationUrlForm to verify that those overrides don't show up there anymore. Without the patch if there is some kind of override for language settings, that will show up in the form (and get saved back when you hit save on the form). There is no UI to reproduce the bug because language.negotiation config values are not translatable and the only UI to edit config overrides in core is for languages. What you can also do in the test is to add a foreign language, set an override in that language of language.negotiation and then access the language URL settings page in that language, and check the overrides are not applied.
Comment #23
robertdbailey CreditAttribution: robertdbailey at Lingotek commentedcreated tests for checking English language.negotiation overrides and then Spanish language.negotiation overrides. Please review.
Comment #25
vijaycs85Tests in #23 looks good (though it's missing second part of @Gábor Hojtsy suggestion in #22) and the main fix has been in review since #14. I think this is good to go.
Comment #26
robertdbailey CreditAttribution: robertdbailey at Lingotek commentedThanks for reviewing, @vijaycs85! I've updated the tests to include the second part of #22. Please review.
Comment #27
robertdbailey CreditAttribution: robertdbailey at Lingotek commentedPatches from #25 did not seem to be queued properly for testing. Retrying as #26.
Comment #29
alexpottThis change looks excellent. I think the removal of the
language_negotiation_url_*_save()
methods is acceptable - forms and other APIs should be interacting directly with the configuration object here.I think we should be deprecating both of these methods and scheduling them for removal in Drupal 9, since people really should just load the configuration from config.
Comment #30
Gábor HojtsyAgreed with @alexpott.
Comment #31
penyaskitoDeprecating both
language_negotiation_url_prefixes()
andlanguage_negotiation_url_domains()
.I'm wondering if we should do the same with
language_negotiation_url_prefixes_update()
Comment #32
Gábor HojtsyThere is no use of language_negotiation_url_prefixes_update() in core, only one mention in comments. Not sure we can deprecate it though unless we have some other place where its implemented. The ConfigSubscriber::onConfigSave() (where a copy of its code resides) in language is not a reusable place. I don't think moving that around would be in scope for this issue anyway. Let's get this in then.
Comment #33
penyaskito@Gábor: There is one use of
language_negotiation_url_prefixes_update()
inConfigurableLanguage::postSave
. But yeah, we can leave that for a follow-up anyway.Comment #34
alexpottIt's great to have this fixed. Nice work everyone. This issue addresses a major bug and is allowed per https://www.drupal.org/core/beta-changes. Committed 52e5d45 and pushed to 8.0.x. Thanks!
I don't think a CR is necessary for the two functions that should be removed.
Comment #36
andypostThis follow-up still needed
Comment #37
Gábor HojtsyAmazing, thanks all!
Comment #38
penyaskito@andypost Thanks for the reminder, created #2548079: Move language negotiation prefix logic update to ConfigurableLanguage.