Sorry, meant to file this a month ago when I hit this prepping for a D8 demo, but ran into it again tonight whilst prepping for a NEW demo, so am filing it now. :) https://github.com/webchickenator/drupal8-demo/blob/master/cmi.sh is the script I use, which goes against stable alphas, but I've also verified this problem against HEAD.
When you do a config override on site A, say, uncommenting the $config['system.site']['name'] = 'My Drupal site';
line to force-set the site name, and then save something else on the page like, say, the site slogan, the YAML file gets updated with both the changed slogan and the site name, like so:
uuid: f46df212-f995-42e7-9400-da0d9f6626f0
-name: Site-Install
+name: 'Drupal 8 [Dev]'
mail: admin@example.com
-slogan: ''
+slogan: sdfsdf
page:
403: ''
404: ''
Expected behaviour: Only slogan would change.
We need tests for this.
Comment | File | Size | Author |
---|---|---|---|
#24 | config-2239065-24.patch | 56.12 KB | tim.plunkett |
#24 | interdiff.txt | 578 bytes | tim.plunkett |
#11 | config-2239065-11-PASS.patch | 49.96 KB | tim.plunkett |
#11 | config-2239065-11-FAIL.patch | 2.2 KB | tim.plunkett |
#11 | interdiff.txt | 2.26 KB | tim.plunkett |
Comments
Comment #1
catchThis is closely related to #1934152: FormBase::config() and ConfigFormBase::config() work entirely differently, may result in unexpected side effects.
Comment #2
webchickNote that in alpha11 this seems to have gotten somewhat worse. The site name override is showing up in the diff even when I change a totally unrelated page like user permissions.
Comment #3
tim.plunkettOh my.
Working on this.
Comment #4
tim.plunkett#2098119: Replace config context system with baked-in locale support and single-event based overrides broke this.
Basically, we used to set up the override protection on $this->configFactory directly, now its in the helper $this->config() method.
Making $this->configFactory protected will prevent any forms from making this mistake again.
Something is wrong with my test, the FAIL should fail in 2 places but fails in the wrong place... Will have to look into that.
Comment #7
tim.plunkettComment #8
dawehnerIt should be clearly documented somewhere that you need this behavior in every place you deal with config load/save. +1 to make the code easier, especially because it removes the possibility to do evil things in the constructor.
Comment #10
tim.plunkettThanks @dawehner! I do think the fix is correct, but it appears my test needs some more work. Once I get them passing/failing as expected, I'll ask for another final review.
What's interesting is that the fails are displayed twice by testbot, I'm not sure why it would be run twice...
Comment #11
tim.plunkettOkay, using $GLOBALS in web test doesn't work, so I need to write out the settings directly.
Rearranging the test a bit.
No other changes.
Comment #12
tim.plunkettOpened #2251915: Overridden config entity bleeds through to admin forms for config entities, that was never a fixed problem, while this issue is a regression.
Comment #14
neclimdulKinda sucks that we have to pull it off the container like that in config() but that's the way we've got the API setup. Good fix.
Comment #15
alexpottThe change looks great.
I think we should be documentation why we are changing the scope from private to protected here. Obvious the whole point of the ConfigTranslationFormBase is to aid in the creation of configuration overrides and the default FormBase override handling because of that.
Comment #16
Gábor HojtsyI think it makes total sense that we access config through the same accessor designed to avoid overrides. Indeed #1934152: FormBase::config() and ConfigFormBase::config() work entirely differently, may result in unexpected side effects is where the global overrides applicability is in question where people argued the global overrides should apply all the time and their appearance is a feature not a bug in this case. That needs to be figured out there. Its a critical in its own right.
Comment #17
tim.plunkettWe don't need to mark it protected, just to redeclare it in the class as private. PHP--
Added some comments.
Thanks for the insight @Gábor Hojtsy, that helps a lot.
Comment #18
alexpottDoesn't doing this break the
BaseForm::config()
function for classes that extendConfigTranslationFormBase
?Comment #19
alexpottOops meant to leave at needs review
Comment #20
tim.plunkettNeither ConfigTranslationAddForm nor ConfigTranslationEditForm need it, just like none of the other subclasses of FormBase/ConfigFormBase need it. Only the classes that access it directly to handle config loading need to specify it, and that's just FormBase, ConfigFormBase, and ConfigTranslationFormBase.
Comment #22
tim.plunkettExcept, it turns out we were just getting lucky, and private won't work at all for us:
http://3v4l.org/ij3dS
Back to the drawing board.
Comment #23
tim.plunkettFormBase has setters and getters for each service, in addition to helper methods. Except there is no configFactory() method.
Using that allows us to bypass all of the private nonsense in subclasses.
I don't know why I didn't think of this before, much cleaner.
Comment #24
tim.plunkettAfter further discussion, added a comment to configFactory() to deter usage.
Comment #25
neclimdulAwesome, I don't think there is anything better we can do. Looks good to me and I _think_ this addresses alex's concerns so going to bump it back to RTBC under the assumption that the doc change won't cause testbot to fail.
Comment #26
webchickProbably best for Alex to sign off on this. Thanks so much for taking it on!
Comment #28
tim.plunkett24: config-2239065-24.patch queued for re-testing.
Comment #29
tim.plunkettRandom fail, back to RTBC.
Comment #30
alexpottWell the advantage of the private approach was that classes that extend FormBase never had a config factory to play with - but with this approach they do using $this->configFactory() - it is going to be an easy mistake to make.
Comment #31
tim.plunkettWell the private approach didn't actually work except due to coincidence.
In HEAD they have $this->configFactory, here they have $this->configFactory(), but with docs, and we've fixed all of core. I don't see how we can truly lock this down without supporting the needs of ConfigFormBase and ConfigTranslationFormBase.
Comment #32
alexpottCommitted def5707 and pushed to 8.x. Thanks!
Removed the unnecessary use of the word bleed :) and improved the test description.
Comment #34
Gábor HojtsyYay, superb! Tagging for D8MI since this has profound lessons on how to write config forms for multilingual compatibility, so makes it easier to back-reference.
Comment #35
Gábor HojtsyBTW updated https://drupal.org/node/1934152#comment-8732445 with the potentially bad side effects of this issue, depending on what you use global overrides for -- good stuff to discuss :)
Comment #36
XanoThis broke our attempts at #2208115: Add DependencySerializationTrait.
Comment #37
Gábor HojtsyXano: but this is fixed? Is the fix causing issues?!
Comment #38
XanoThe fix causes problems for #2208115: Add DependencySerializationTrait, yes. I'm not sure whether we want to follow-up on the config factory fix, or if we should change the approach the trait takes, so I just linked the other issue here instead of opening a follow-up already.
Comment #39
tim.plunkettThis is a critical bug fix. private properties are part of the language.
It's a shame they broke the attempt to use a trait for serialization, but that is really inconsequential compared to this bug.