Problem/Motivation

In #2339151: Conditions / context system does not allow for multiple configurable contexts, eg. language types both @EclipseGc and myself found that the language negotiation form does not save values immediately. One needs to go back to the form and save it again to get settings to actually save.

Steps to reproduce:

- Enable content translation module
- On admin/config/regional/language/detection check content language negotiation to be customized
- Actually customize settings, eg. disable URL negotiation, enable session
- Observe page coming back but settings are only partially saved (session not enabled)
- Any further change will save all changes, above only happens for the first change

Proposed resolution

- Fix it
- Add tests

Remaining tasks

Contributor tasks needed
Task Novice task? Contributor instructions Complete?
Create a patch Instructions
Add automated tests Instructions
Add steps to reproduce the issue Instructions (done)
Review patch to ensure that it fixes the issue, stays within scope, is properly documented, and follows coding standards Instructions

User interface changes

Form will not lie about saved setings.

API changes

None.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

YesCT’s picture

Issue summary: View changes
YesCT’s picture

Issue summary: View changes
Gábor Hojtsy’s picture

Status: Active » Needs review
FileSize
2.15 KB

These tests should expose the problem. Let's see if they do.

Status: Needs review » Needs work

The last submitted patch, 3: 2364171-tests.patch, failed testing.

Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
0 bytes
1.62 KB

Parenthesis needs to be at the right place.

Gábor Hojtsy’s picture

FileSize
0 bytes

A non zero byte roll of what 5 should have been lol.

Gábor Hojtsy’s picture

FileSize
2.15 KB

This issue will be a great one to show to pepole why they should not be afraid that they post silly patches :D Paying more attention++

The last submitted patch, 6: 2364171-tests-6.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 7: 2364171-tests-6.patch, failed testing.

Gábor Hojtsy’s picture

Now fails for the right thing. We can work on fixing the bug.

penyaskito’s picture

core/modules/language/src/LanguageNegotiator.php:

  function saveConfiguration($type, $enabled_methods) {
    $definitions = $this->getNegotiationMethods();
    $default_types = $this->languageManager->getLanguageTypes();
    [...]

$default_types contains only language_interface yet.

Gábor Hojtsy’s picture

Should call languageManager::reset() then before invoking this one I would guess. Or this one should invoke it I guess.

Gábor Hojtsy’s picture

@penyaskito said in IRC this solved the issue but the test is not confirming it.

[3:58pm] GaborHojtsy: penyaskito: I suspected this may be cached in the TESTING system so even resetting the language managet in the TESTED system would not be enough
[3:58pm] GaborHojtsy: penyaskito: so my theory is the patch/fix needs to reset language manager and the test needs to reset config factory, just a theory though
penyaskito’s picture

Status: Needs work » Needs review
FileSize
1.17 KB
2.17 KB
2.74 KB

Ok, gotcha.

I'm not sure if this is what we expect, but this is how language.types.yml looks like after saving some config:

all:                                                                                                                                                                     
  - language_interface
  - language_content
  - language_url
configurable:
  - language_interface
  - language_content
negotiation:
  language_content:
    enabled:
      language-url: -8
      language-user: -4
      language-browser: -2
      language-selected: 12
    method_weights:
      language-url: -8
      language-session: -6
      language-user: -4
      language-browser: -2
      language-interface: 9
      language-selected: 12
  language_url:
    enabled:
      language-url: 0
      language-url-fallback: 1
  language_interface:
    enabled:
      language-url: -8
      language-browser: -2
      language-selected: 12
    method_weights:
      language-url: -8
      language-session: -6
      language-user: -4
      language-browser: -2
      language-user-admin: 10
      language-selected: 12

The test is checking with in_array, but should use array_key_exists.

The last submitted patch, 14: 2364171-language-negotiation.only-test-14.patch, failed testing.

Gábor Hojtsy’s picture

Status: Needs review » Needs work

Looks great! Only one thing:

+++ b/core/modules/language/src/LanguageNegotiator.php
@@ -264,6 +264,7 @@ public function isNegotiationMethodEnabled($method_id, $type = NULL) {
+    $this->languageManager->reset();

Let's add a comment. Something like "Configurable language types might have changed. Reset the cache."

penyaskito’s picture

Status: Needs work » Needs review
FileSize
663 bytes
2.82 KB

Sure, done that.

Gábor Hojtsy’s picture

Status: Needs review » Reviewed & tested by the community

Looks great!

catch’s picture

+++ b/core/modules/language/src/LanguageNegotiator.php
@@ -264,6 +264,8 @@ public function isNegotiationMethodEnabled($method_id, $type = NULL) {
+    // As configurable language types might have changed, we reset the cache.
+    $this->languageManager->reset();

Why doesn't the code that changes the configurable language types reset this cache?

Gábor Hojtsy’s picture

Status: Reviewed & tested by the community » Needs work

That's a great suggestion. That would be in NegotiationConfigureForm::submitForm(), right before the first $this->negotiator->updateConfiguration() is called.

penyaskito’s picture

Status: Needs work » Reviewed & tested by the community

We are already resetting the language manager (even clearing the negotiator manager cache) on purgeConfiguration() and updateConfiguration()... so why not in saveConfiguration()? Otherwise, the form will know too much about the language manager, and even can cause issues if reproducing this via API.

alexpott’s picture

I agree with @penyaskito putting the cache clear on the form layer feels wrong - having it in LanguageNegotiator::saveConfiguration() feels right - if anything calls that API, Drush, form this will reset the language manager and the configuration we change the system as expected once saved.

alexpott’s picture

Assigned: Unassigned » catch

@penyaskito wanted to assign this to @catch

catch’s picture

Status: Reviewed & tested by the community » Fixed

Something is still niggling but it's not concrete, and I agree this shouldn't be done in the form, so this seems OK.

Committed/pushed to 8.0.x, thanks!

  • catch committed 104f1dc on 8.0.x
    Issue #2364171 by Gábor Hojtsy, penyaskito: Fixed Enabling and...
Gábor Hojtsy’s picture

Issue tags: -sprint

Yay, thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.