Closed (works as designed)
Project:
Drupal core
Version:
11.x-dev
Component:
configuration entity system
Priority:
Normal
Category:
Task
Assigned:
Unassigned
Reporter:
Created:
22 Jan 2015 at 01:59 UTC
Updated:
21 Apr 2025 at 06:30 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
bojanz commentedInitial prototype. Fixes NodeType as an example.
third_party_settings need to be changed at all places at once, so I've kept them as it is right now.
Comment #2
tim.plunkettWhy not just skip the manipulation of $values?
Something like this:
You could leave these out
Comment #4
tim.plunkettThis failed first because of missing commas here.
Then it failed because not every exported value will be in $config_mapping.
I included my suggestions from #3.
I also included unit tests (which required a bit of rejiggering of ConfigEntityBaseUnitTest).
Finally, I removed the dual typing of config_mapping in EntityTypeInterface. We'll be served just as well by an empty array.
-------
One last thought I had, which I didn't touch: this isn't really config_mapping, but config_key_mapping. Thoughts on renaming it?
Comment #6
bojanz commentedBig thanks, Tim. Wasn't expecting anyone to see my 3AM experiment before I woke up :)
This now looks much cleaner. I agree that config_key_mapping sounds better, we can make the switch in the next patch.
I'm working on the test fails.
EDIT:
So, we opened pandora's box by using an external service in a constructor. The amount of tests that need fixing is non-trivial.
We need to move the mapping from __construct to avoid it.
Comment #7
bojanz commentedThanks to alexpott for helping me figure out what was wrong with the tests.
This one should be green. Moved the mapping logic from __construct() to preCreate(), fixed the tests to make sense.
Changing the annotation key is still TODO.
Do we want to handle additional conversions here? ConfigTest, Editor, CommentType should all be as trivial as NodeType.
Comment #8
bojanz commentedReverted a toArray() change from the previous patch that would have caused an issue if the id key is a mapped property.
Killed a kitten by fixing the "$display_submtited" variable name.
Comment #10
tim.plunkettSince this isn't implemented on the base classes, none of the entity classes overriding it call parent::, so this won't run. Not many config entities override it, but View certainly does.
Comment #12
bojanz commentedI've confirmed to Tim on IRC that no config entity other than Views implements preCreate(), and the Views one does call the parent.
New patch:
NodeTypeForm was still setting the snake_case keys, and expecting them to be reflected on the entity.
I've introduced a ConfigEntityForm (resolving a @todo in the process) that now does the required key mapping.
Question: What should be done with the now empty EntityForm::copyFormValuesToEntity?
Let's see what the test bot says.
EDIT: I forgot that emptying EntityForm::copyFormValuesToEntity would break unconverted config entity forms. Putting it back as soon as I confirm there are no remaining test fails.
Comment #14
yched commentedConfigEntityForm::copyFormValuesToEntity() : $entity or $this->entity ?
Although : if the snake_case properties are only for config records, while runtime objects have camelCase properties, then the forms should manipulate the camelCase properties ?
I.e you'd have
'#default_value' => $entity->myProperty
$form['myProperty']
$form_state['values']['myProperty']
rather than 'my_property' ?
Meaning, no mapping logic in the form, only on "save to a config record" ?
Comment #15
bojanz commentedThe entity/$this->entity inconsistency was there in the parent, I just copied it over.
As for camelCase in the form keys, I didn't think I could get away with that. Let's give it a shot.
Comment #16
yched commentedMore accurately, #2016679: Expand Entity Type interfaces to provide methods, protect the properties is about moving all properties to protected with getters, and the generic get() / set(), so my snippet in #14 would rather be something like :
Doesn't change much - either the form uses the camelCase properties and you can do the generic "assign form values into the object" as above, or the form uses snake_case properties and we need to use the mapping.
Yeah, camelCase entries in $form would look a bit uncommon, and not sure what kind of HTML attributes they would produce ('id', 'name'...), maybe that's not ideal.
But with the mapping (current patch) we'd have :
- entity load: map snake to camel (config record to $entity properties)
- form build : map back camel to snake ($entity properties to $form structure) - but that step will more likely be a series of explicit "$form['snake_case'] = array(...$entity->get('camelCase')...)", that needs to comply to the mapping without actually using the mapping.
- form submit : map snake to camel ($form_values to $entity properties)
- entity save : map back camel to snake ($entity properties to config record)
That's a hell of a dance... :-/
It also makes the mapping be not a "config mapping", but a "mapping for places where we'd prefer to have camelCase (object properties) and places where we'd prefer to have snake_case (config records, form structures)".
Comment #17
yched commentedOn a different topic, it looks weird that mapping is done in toArray() but mapping back is done in preCreate() :
when loading an existing entity from config, preCreate() doesn't run , only __consruct() does, right ?
So I'm not sure how loading could work with the current patch ?
There's currently a (ok, unwritten :-)) contract that toArray() produces values that are valid for passing back to __construct().
That's what config entity loading from CMI records relies on.
That's also the base for the serialization logic implementend in EntityDisplayBase (and that #1977206: Default serialization of ConfigEntities tries to generalize to all config entities) - basically: serialize to toArray(), unserialize by passing those values back into __construct($values_from_to_array).
If toArray() maps camelCase -> snake_case, but mapping back is done in preCreate(), then it looks like this contract is broken ?
More generally: toArray() advertizes itself as a generic "dump to an array" mechanism, that happens to be used, among other things, for config record generation. By baking a "camelCase to snake_case" mapping in there, we confiscate it a bit for CMI business logic.
I guess it's not completely unreasonable to state that "the official array dump shape of a ConfigEntity" is one with camel_case keys. Not sure of the exact consequences outside of CMI, though.
Comment #18
bojanz commentedThank you, yched. I've tried to address your feedback in the new patch.
Changes:
- Reverted the #12 changes completely, made the NodeTypeForm keys camelCase where needed.
This looks a bit inconsistent, but conceptually it's cleaner than the automated mapping.
- Renamed the annotation key to "config_key_mapping".
- Made ConfigEntityBase::toArray() return camelCase keys (per #17).
- Moved the mapping logic from preCreate to config storage.
- Fixed test fails.
So, the latest approach means:
- Config entities declare camelCase properties and snake_case config keys.
- Config entity forms use camelCase keys, to match the manipulated property.
- entity_create() expects camelCase keys, and ConfigEntityBase::toArray() returns camelCase keys.
- The config entity storage maps the snake_case keys to camelCase keys (and back) when the config entities are being loaded/saved.
All this trouble so that we can avoid having camelCase config keys :)
Comment #21
anavarreComment #22
bojanz commentedLet's hold off on the reroll, #2432791: Skip Config::save schema validation of config data for trusted data has a chance of making the main part of this patch unnecessary.
Comment #23
berdir@bojanz: Anything left to do here after #2432791: Skip Config::save schema validation of config data for trusted data?
Comment #24
neetu morwani commentedComment #26
googletorp commentedFix merge error in last patch.
Comment #28
bojanz commentedThe patch needs to be reworked to account for #2432791: Skip Config::save schema validation of config data for trusted data which introduced a config_export key, as documented in https://www.drupal.org/node/2481909.
The problem is that core is only using the config_export key on export, not on import, so we've been unable to implement the functionality in contrib.
So, we need to prove that with a failing test and then take it from there, merging in other parts of the current patch.
Comment #29
LKS90 commentedAlright, here are two patches: One adds a test to ConfigEntityStorageTest which tests the camelCase to snake_case conversion in core (which is working), the second one does the same for flag, the tests will break because camelCase/snake_case import is not yet supported for contrib modules.
I don't know if the flags tests will even be run/if the patch "applies", but we can do manual testing I guess?
Comment #30
ajitsComment #33
ajitsPatch was not applying.
Comment #34
arla commentedI think that is not the test you are looking for (*jedi hand gesture*). The critical part is that the value is read from protected_property in the DB, and then set to $entity->protected_property but it should be set to $entity->protectedProperty. So something like
assertEqual($entity->protectedProperty, ‘TEST’)would make more sense imho.Comment #35
LKS90 commentedHere is a new patch, which fails for the new getProtectedProperty() method. It is NULL instead of TEST. So something is really wrong there.
I left the toArray stuff in (the test method could use a renaming) and added a line which tests the camelCasing for toArray, which we seem to want according to #18:
That seems to work.
entity_create still uses snake_case, when I switch to camelCase, all three tests fail.
That doesn't seem to work. I added two tests: one which returns the property as defined in code. That one fails, strangely. And another one which returns the property witch snake_casing. That actually works, even though there is no property in the code, the import messes it up.
Comment #36
LKS90 commentedForgot the interdiff, sorry!
Comment #38
tim.plunkettComment #42
jacobsanford@LKS90's patch in #35 no longer applied to 8.4.x. A reroll with no further modifications is attached in case this issue still needs to go forward.
Comment #54
ayush.khare commentedReroll of #42 for 10.1.x
Comment #55
pooja saraah commentedFixed Failed Commands on #54
Attached patch against Drupal 10.1.x
Attached interdiff
Comment #57
quietone commentedThis is a proposal implementing an idea in another issue, #1832630: Decide on coding standard for configuration keys of ConfigEntities. I've just closed that as outdated, so it makes sense to do that to this one as well.