Problem/Motivation

- User translates the front page view to some language.
- User goes and changes the front page view, ie. makes it a table with fields instead of a node view.
- User DOES NOT update the translation manually.
- Now the translated version will use the translation still corresponding to the OLD structure of the view, so invalid residual pieces of row styles, etc. will show up.

May lead to all kinds of strange consequences. Also applies to other kinds of overrides.

Proposed resolution

When a configuration changes, overrides should be re-saved and only keys still overlapping with the original configuration should be kept. All other keys should be dropped. This may be applied to any kind of override.

Brought this to CMI meeting:

1. This is an API addition, not beta blocking.
2. Postponed on #2224887: Language configuration overrides should have their own storage since it implements override storage where save for overrides fires no events. Otherwise this is hard/impossible to implement because now language overrides are in general config and have events fired.
3. This could be implemented as a base class for overrides that would listen on save events and update its overrides.
4. Then language overrides would extend from this base class instead of just implementing interfaces.

Marked as beta target because this API addition would be nice to do before beta so modules can extend from that. Eg. domain module for its overrides.

Remaining tasks

Review. Commit.

User interface changes

None.

API changes

None, however overrides are now suggested to extend from ConfigFactoryOverrideBase.

Files: 
CommentFileSizeAuthor
#26 interdiff.txt4.8 KBGábor Hojtsy
#26 2268939-config-override-save-26.patch10.27 KBGábor Hojtsy
PASSED: [[SimpleTest]]: [PHP 5.4 MySQL] 74,333 pass(es). View
#24 interdiff.txt2.72 KBGábor Hojtsy
#24 2268939-config-override-save-24.patch10.29 KBGábor Hojtsy
PASSED: [[SimpleTest]]: [PHP 5.4 MySQL] 73,173 pass(es). View
#22 interdiff.txt1.78 KBGábor Hojtsy
#22 2268939-config-override-save-22.patch10.29 KBGábor Hojtsy
PASSED: [[SimpleTest]]: [PHP 5.4 MySQL] 73,497 pass(es). View
#19 interdiff.txt1.9 KBGábor Hojtsy
#19 2268939-config-override-save-19.patch10.27 KBGábor Hojtsy
PASSED: [[SimpleTest]]: [PHP 5.4 MySQL] 73,296 pass(es). View
#18 interdiff.txt3.15 KBGábor Hojtsy
#18 2268939-config-override-save-18.patch10.13 KBGábor Hojtsy
PASSED: [[SimpleTest]]: [PHP 5.4 MySQL] 73,306 pass(es). View
#17 interdiff.txt3 KBGábor Hojtsy
#17 2268939-config-override-save-17.patch9.4 KBGábor Hojtsy
PASSED: [[SimpleTest]]: [PHP 5.4 MySQL] 73,376 pass(es). View
#15 interdiff.txt957 bytesGábor Hojtsy
#15 2268939-config-override-save-15.patch7.73 KBGábor Hojtsy
FAILED: [[SimpleTest]]: [PHP 5.4 MySQL] 73,292 pass(es), 1 fail(s), and 0 exception(s). View
#13 interdiff.txt4.44 KBGábor Hojtsy
#13 2268939-config-override-save-13.patch7.73 KBGábor Hojtsy
FAILED: [[SimpleTest]]: [PHP 5.4 MySQL] 73,518 pass(es), 2 fail(s), and 0 exception(s). View
#11 2268939-config-override-save-11.patch8.21 KBGábor Hojtsy
FAILED: [[SimpleTest]]: [PHP 5.4 MySQL] 73,235 pass(es), 4 fail(s), and 0 exception(s). View
#11 interdiff.txt4.31 KBGábor Hojtsy
#9 2268939-diff-7-9.txt5.12 KBvijaycs85
#9 2268939-config-override-save-9.patch5.3 KBvijaycs85
PASSED: [[SimpleTest]]: [PHP 5.4 MySQL] 73,002 pass(es). View

Comments

Gábor Hojtsy’s picture

BTW this used to be #1966538: Translation is not updated for configuration, when the config changes but that was closed since it was about to cover other things which became outdated. Now its a "simple" structural question.

Gábor Hojtsy’s picture

Status: Active » Postponed
Issue tags: +beta target

Brought this to CMI meeting this week:

1. This is an API addition, not beta blocking.
2. Postponed on #2224887: Language configuration overrides should have their own storage since it implements override storage where save for overrides fires no events. Otherwise this is hard/impossible to implement because now language overrides are in general config and have events fired.
3. This could be implemented as a base class for overrides that would listen on save events and update its overrides.
4. Then language overrides would extend from this base class instead of just implementing interfaces.

Marked as beta target because this API addition would be nice to do before beta so modules can extend from that. Eg. domain module for its overrides.

Gábor Hojtsy’s picture

Gábor Hojtsy’s picture

Status: Postponed » Active
Gábor Hojtsy’s picture

Assigned: Unassigned » vijaycs85

vijaycs85 says he is working on this.

vijaycs85’s picture

Issue summary: View changes
vijaycs85’s picture

Status: Active » Needs review
FileSize
1.5 KB
PASSED: [[SimpleTest]]: [PHP 5.4 MySQL] 72,762 pass(es). View

Here is an update on the approach as per issue summary.

Note. Can't really use baseClass for the event as it is a static method for registering events.

alexpott’s picture

Issue tags: +Needs tests

We need to handle deletes and renames too. And we need tests.

vijaycs85’s picture

FileSize
5.3 KB
PASSED: [[SimpleTest]]: [PHP 5.4 MySQL] 73,002 pass(es). View
5.12 KB

Thanks for the review @alexpott. Here is an update. Still need to add test and make sure the code covers all functionalities mentioned in issue summary...

Gábor Hojtsy’s picture

Status: Needs review » Needs work

I don't see how this will react to config data changes, maybe I'm not clear on something getOverride() does to ensure this? The rename and delete reactions look complete though. Besides missing tests, I only found this minor issue:

+++ b/core/modules/language/src/Config/LanguageConfigFactoryOverride.php
@@ -208,9 +208,52 @@ public function addCollections(ConfigCollectionInfo $collection_info) {
+    $config_translation = $this->getOverride($language->getId(), $name);

Not indented properly.

Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
4.31 KB
8.21 KB
FAILED: [[SimpleTest]]: [PHP 5.4 MySQL] 73,235 pass(es), 4 fail(s), and 0 exception(s). View

Fixed the indent and a comment and added a start for some tests. Although locally untested :D

Status: Needs review » Needs work

The last submitted patch, 11: 2268939-config-override-save-11.patch, failed testing.

Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
7.73 KB
FAILED: [[SimpleTest]]: [PHP 5.4 MySQL] 73,518 pass(es), 2 fail(s), and 0 exception(s). View
4.44 KB

Decided to not modify the existing test because it deals with overrides for config not yet saved. Would have needed to modify it too much to be good for this other use case, so just added more test data for the new use case. Cleaner. Should theoretically have less fails, since we were testing things that were not appropriate for both scenarios when reusing the older test code.

Status: Needs review » Needs work

The last submitted patch, 13: 2268939-config-override-save-13.patch, failed testing.

Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
7.73 KB
FAILED: [[SimpleTest]]: [PHP 5.4 MySQL] 73,292 pass(es), 1 fail(s), and 0 exception(s). View
957 bytes

The first fail was due to bad test :) Was about ensuring the original data was removed. Fixed that. The other fail proves the language override is in fact not updated when the original data changes. :) Just as I theorised in #10.

Status: Needs review » Needs work

The last submitted patch, 15: 2268939-config-override-save-15.patch, failed testing.

Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
9.4 KB
PASSED: [[SimpleTest]]: [PHP 5.4 MySQL] 73,376 pass(es). View
3 KB

I think this is about the solution to the problem. As discussed before we need to filter the override based on the original config. I think we'll need this as utility methods, so added to ConfigFactoryOverrideBase.

Gábor Hojtsy’s picture

FileSize
10.13 KB
PASSED: [[SimpleTest]]: [PHP 5.4 MySQL] 73,306 pass(es). View
3.15 KB

Improved the test in two ways:

1. Made the override use a nested key element not on the top, so e can test that if that is removed in the data, the whole override container data structure is removed if empty.
2. Added a French override as well that uses less data and therefore disappear sooner, when it does not contain data anymore. Added tests for that.

Gábor Hojtsy’s picture

Issue summary: View changes
Issue tags: -Needs tests
FileSize
10.27 KB
PASSED: [[SimpleTest]]: [PHP 5.4 MySQL] 73,296 pass(es). View
1.9 KB

With improved type hinting and phpdoc. I consider this ready.

Gábor Hojtsy’s picture

Assigned: vijaycs85 » alexpott

I don't think either vijaycs85 or myself are qualified to RTBC this one, so assigning to alexpott.

Jose Reyero’s picture

Looks good to me, surprisingly simple and straight forward for what it does I'd say.

The only thing I don't get is using a base class + the actual implementation, that I don't know whether it can be reused for anything else and actually save any code somewhere..? It looks to me just too specific for this case.
Note the abstract class just gives us a few static methods that could be placed (and still be reused) anywhere else.

One minor issue / question:

+  public function onConfigSave(ConfigCrudEvent $event) {
+    $config = $event->getConfig();
+    $name = $config->getName();
+    foreach (\Drupal::languageManager()->getLanguages() as $language) {
+      $config_translation = $this->getOverride($language->getId(), $name);
+      static::filterOverride($config, $config_translation);
+    }
+  }

Wouldn't it make sense to check whether there's actually any overridden data before moving on to filtering / deleting / etc..?

Gábor Hojtsy’s picture

FileSize
10.29 KB
PASSED: [[SimpleTest]]: [PHP 5.4 MySQL] 73,497 pass(es). View
1.78 KB

Yeah it makes sense to check for new-ness of the override (whether it actually exists or was just created). Also using the same logic in the other places to ensure consistency.

As for the applicability of the base class I think there is good value in both unifying the event listener methods (this is done a lot in Drupal 8 elsewhere) and also the generic override filter methods are applicable regardless of the override itself, whether it is domain based or og based. So those modules can use the same base class and feed their overrides to the filter code. I originally thought we would go as far as to implement this even outside the concrete override classes and on the collection storage level, assuming all storages but the default storage are overrides, but that may or may not be a good assumption. Then we would not need to do custom code for each override type to enumerate its (possible) list of overrides for a key. This is the main thing I guess I would love to get feedback from alexpott as well :)

Jose Reyero’s picture

the generic override filter methods are applicable regardless of the override itself, whether it is domain based or og based.

Ok, this makes sense.

Gábor Hojtsy’s picture

FileSize
10.29 KB
PASSED: [[SimpleTest]]: [PHP 5.4 MySQL] 73,173 pass(es). View
2.72 KB

Making the utility methods protected instead of static based on in-audio meeting review with @alexpott.

alexpott’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/config/src/Tests/ConfigLanguageOverrideTest.php
    @@ -82,6 +82,55 @@ function testConfigLanguageOverride() {
    +    \Drupal::configFactory()->rename('config_test.overide', 'config_test.override');
    

    renaming from config_test.overide to config_test.override makes this test unnecessarily hard to grok. Lets rename from config_test.override to config_test.renamed_override.

    Also calling the object override is confusing... we're overriding the override :). Plus we're overriding a non existent thing.

  2. +++ b/core/modules/language/src/Config/LanguageConfigFactoryOverride.php
    @@ -9,7 +9,10 @@
     use Drupal\Core\Config\ConfigEvents;
    

    This is no longer used.

Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
10.27 KB
PASSED: [[SimpleTest]]: [PHP 5.4 MySQL] 74,333 pass(es). View
4.8 KB

1a. All right, I think overide => override was fun, but I can see how that may be confusing. Now renamed to 'foo' => 'bar' to make it clear. It does not name the original override then :D

1b. As for how the override was first before the config, that was to avoid needing to manually clear the config factory cache :D Now I moved the original before the overrides, and now clearing the cache, so we don't get the non-overridden version from the cache.

2. Removed.

alexpott’s picture

Status: Needs review » Reviewed & tested by the community

Awesome source. Nice to see this fixed and in a way that other configuration override implementations can benefit from.

alexpott’s picture

Assigned: alexpott » Unassigned

I rtbc'd it so I can't commit it :)

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.x, thanks!

  • catch committed 179c092 on 8.x
    Issue #2268939 by Gábor Hojtsy, vijaycs85: Fixed Config overrides not...
Gábor Hojtsy’s picture

Issue tags: -sprint

Amazing, thanks.

Status: Fixed » Closed (fixed)

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