Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
Configuration entity properties should be protected. At the moment we determine which entities to export using a mix of reflection and hardcoding in the toArray() method. We can use schema to do this instead.
We have fixed the public access of ID many times, but it keeps creeping back in.
Proposed resolution
- Use configuration schema to determine which properties to export
- Remove unnecessary toArray implementations
- Change a config entity to have a protected ID property to prevent regressions
This solution has the beneficial side effect of ensuring the order or the root keys in the exported configuration matches its configuration schema.
Remaining tasks
N/A
User interface changes
N/A
API changes
N/A
Comment | File | Size | Author |
---|---|---|---|
#51 | 2256679.51.patch | 50.53 KB | alexpott |
#51 | 42-51-interdiff.txt | 2.18 KB | alexpott |
#42 | 2256679.42.patch | 47.93 KB | alexpott |
#42 | 40-42-interdiff.txt | 2.46 KB | alexpott |
#40 | 2256679.40.patch | 45.47 KB | alexpott |
Comments
Comment #1
tim.plunkettComment #4
tim.plunkett1: entity-2256679-1-PASS.patch queued for re-testing.
Comment #5
tim.plunkettComment #8
BerdirThis will affect the order of properties and move the id (almost) at the bottom, which is a bit weird. And it's what's causing all those import and diff fails, because default config needs to be updated to look the same as one written through the API...
Comment #9
tim.plunkettMehhhhh.
Comment #10
BerdirWorks for me :)
Comment #11
alexpott@dawehner and I wondered about why this wasn't being done on ConfigEntityBase and then @dawehner wondered if we couldn't use schema to do all this for us?
I'm having a look at doing this.
Comment #12
BerdirThis is how we do it right now, just look at how many classes subclass ConfigEntityBase::toArray() to do this?
Happy to look at using the schema/typed data for doing this, but there is no reason to block this issue on that?
Back to RTBC and assigning to @alexpott for feedback.
Comment #13
alexpottTo me this is totally related because have to do:
to protect the ID looks really odd.
Here's a patch exploring the idea of using config schema - I think it works out really nicely because now the order of properties is controlled by the schema. I've removed the date config entities toArray() method to show what is possible.
Comment #15
alexpottFixing tests - FilterFormats have an interesting property 'roles' that is only used during config install!
Comment #16
alexpottComment #17
tim.plunkettI think the recent changes are really cool, but are very much out of scope here...
If you want to come up with a better name for the issue and expand the scope, I guess there's nothing I can do about it.
Comment #18
alexpottWell the default toArray is assuming that config entity properties are public :)
Patch posted just to show how much code we can remove.
Comment #19
tim.plunkettWhat is the benefit of moving this out to another method, and using exceptions to communicate between the two?
Also, do you think we can add an @todo here to remove this? Ideally we'd never have public properties or properties without a schema.
Comment #20
alexpottGood point. Cleaned up the code too.
Comment #21
alexpottFor some reason duplicate uploads :)
Comment #22
alexpottUpdated issue summary to reflect the changes - I think that the changes to toArray() in the original patches on this issue make the further changes to use schema in toArray() in scope. The current solution is preferable rather that more and more custom implementations of toArray() when we already have this information to hand.
Comment #23
tim.plunkettIs it really just migration? There are two classes there, but migrate_drupal's entity extends migrate's entity, is it worth moving this hack to that class directly and making the API break now?
I think we should document why we're calling id() here (for entities with compound IDs like FieldConfig).
Right now this is forcibly added to all config entities, which isn't clean, but is reliable.
Now it relies on the schema to define dependencies.
This seems like a problem:
This isn't immediately clear to me why we need this now. The comment is fine, but can you shed some light on why we need this change?
Also, we still need a better issue title.
Comment #24
alexpottentityTypeId
is used ingetEntityType()
which is now called intoArray()
-entityTypeId
is set in the__construct()
buttoArray()
is called before__construct()
in__wakeup()
Comment #25
tim.plunkettI think we should fix up ConfigEntityBaseUnitTest::testToArray().
Not sure how that passed, honestly.
Comment #26
Gábor HojtsyI like the concept of the patch overall. It makes it even more useful to define schema for config entities otherwise you need to define the toArray() method too. On top of the already existing type-casting benefit.
Comment #27
alexpott@tim.plunkett not sure what you by
Comment #28
alexpottRerolled for PRS4
Comment #29
alexpottForgot to commit a little bit of the reroll.
Comment #32
tim.plunkettNo idea what I meant in #25 either, sorry. If this gets back to green, I think its good to go.
Comment #33
alexpott#2273631: Unify config entity schemas with a base schema type added the
config_entity
schema data type. Unfortunately this includedid<code> and <code>label
- these are not present on all config entities. Since we're now using schema in export this exposes this mistake. Schema's should not contain definitions for things that can never exist. Also block config entities do not have a label property.Comment #34
tim.plunkettWhile that somewhat diminishes the usefulness of the config_entity schema, it's still worth keeping around for the 4 other properties from ConfigEntityBase.
And this issue as a whole is still a big improvement.
+1
Comment #35
Gábor HojtsyYeah well, the practical application of the schema is so that any extra keys defined would not be an issue, except of course this application of the schema. If you look at eg. the mapping handler, it would look at the *data* and apply the schema to it, so it would just ignore extra schema elements defined. I think we should somehow figure out if we want to support optional elements or not because we are getting to be inconsistent. I think this issue is fine to get in, but we need to straighten optionality somehow.
Comment #37
alexpottStraight reroll... back to rtbc
Comment #38
vijaycs85Comment #40
alexpottSimple git reroll... back to rtbc.
Comment #42
alexpottFixed the new
FieldInstanceConfigEntityUnitTest::testToArray()
- which is why #40 failed. Setting back to rtbc since all changes were to the unit test.Comment #43
Gábor HojtsySo this is what makes the schema required to exactly match the list of properties and extra elements defined are not ignored. Why not check if there was such a property and just ignore the schema definition if there is none?
That would let us keep using the schema as not necessarily a 100% concrete match for the data. I brought up this issue with reyero and vijaycs85 in the multilingual meeting yesterday and they were concerned that this changes the expectation about the schema from a superset of what may be in the data to an exact match of what may be in the data.
Comment #44
vijaycs85My main concern around this is, we created schema with all possible config items in config entities (like views plugin) and we tried to cover all possible elements as data type. So even some of the elements not used, it will avoid duplication by placing in data type.
If we are moving them back to individual schema file, then we may need to make sure we don't break any, as core tests config entities may not cover all cases.
Comment #45
alexpott@vijaycs85 - all config entities are used by tests so if we were missing any of the properties we'd know pretty quickly - especially since we're using the schema to decide what properties to export. We have to be able to get a list of things to export - either from code, reflection, configuration schema or annotations. We have this information in schema.
This is the bit that really concerns me too - we need to be able to mark schema keys as optional otherwise we're not going to be able to use schema in all situations where they might be valuable.
Comment #46
Gábor Hojtsy@alexpott: well, assumptions in the typed config manager right now is that if something is defined in the schema but not in the data, then its ignored, see Mapping's parse() method. That assumption is a basic defining factor as to how people need to understand how what they provide in schema would behave. Your code here makes very different assumptions. I'm not saying either assumption is correct just that they contradict. I'm totally fine with either definition but with this patch we would have two different understandings of how a definition of schema applies.
Comment #47
Jose Reyero CreditAttribution: Jose Reyero commentedHi, having similar concerns a @Gábor and @vijaycs85, I want to add my 2 cents:
Do we really need to export/import NULL properties?
Can't we fix this by adding a schema 'required' property and if not required, just exporting the property if it is set? (that is already in TypedData definitions btw, so it is just adding it into the schema, not into D8)
- About @Gábor #46, right, but we need to add that having it in the data but not in the schema then it is ignored too (for Mappings), that may be a concern if any other module adds some properties to our entity object. (I'd like to fix that though).
Also thinking that by exporting / importing all properties without checking with isset(), we may end up with a different object to what we started from, with properties that were not set but end up set to null or 0 or '' (saved configuration is typed)
Overall I like this patch's idea a lot, just concerned about these details, and also about the restriction it imposes on schema definitions by working with different premises as generic config objects (not entities), that have a lot of optional properties...
Comment #48
alexpottWell we need to generate a list of properties to export - we can choose from:
For me the last choices are the best and actually given that the inheritance of config_entity schema type is messing with the ordering of the keys anyway perhaps a property annotation is the best way to go because then we control ordering very simply - through the order of the properties on the class.
Making properties protected on config entities is important because without them we have no api and no way to change things once D8 is released. If everyone is accessing properties through a method we have a chance to produce backwardly compatible code and change things under the bonnet.
Comment #49
Jose Reyero CreditAttribution: Jose Reyero commentedAgree with making properties protected being a priority, let's commit this first and discuss about further schema options later.
The only change this introduces from the config schema perspective is: 'schema for config entities must exactly match the data' which is manageable for any future validation, etc.. scenario.
Comment #50
alexpottRerolling for the CommentType config entity.
Comment #51
alexpottPutting back to rtbc since the CommentType changes are a conversion to the new method. They also show the importance of making everything protected asap.
Comment #52
BerdirHonestly, that's not really true because it's a config entity and the properties of a config entity is part of the config schema which we can't change I thought?
Anyway, I agree that the schema should not contain additional elements, because there are for example ideas to be able to use config entities as typed data by relying on the schema, that would not be reliably possible if there are things in there that do not actually exist.
Comment #53
Jose Reyero CreditAttribution: Jose Reyero commentedHey @Berdir,
That sounds interesting, could you point me to any issue, please?
Comment #55
catchThis looks great and cleans things up a lot. Committed/pushed to 8.x, thanks!
Comment #56
Berdir@Jose: The idea is that with #2002138: Use an adapter for supporting typed data on ContentEntities, the same could be done for config entities, by reading the typed data definition in from the schema and then implementing it on top of it. There's no issue yet for it I think.
Comment #57
Gábor HojtsyAdded this to the schema docs at https://drupal.org/node/1905070 as another use case:
See diff at https://drupal.org/node/1905070/revisions/view/7276615/7351805
Comment #58
tim.plunkettAnyone calling parent::toArray without a schema is in for a rude surprise (SchemaIncompleteException). This needs a change notice.
Comment #59
Gábor HojtsyAdded https://drupal.org/node/2288297.
Comment #61
yched CreditAttribution: yched commentedFeedback welcome in #1977206: Default serialization of ConfigEntities - see #26 over there (and #27 for why that patch would be worthwhile)
In short : ConfigEntityBase::toArray() now doesn't work for freshly created entities that don't have an id() yet.
entity_create('entity_type', $values)->toArray()
fails with a "config schema not found" exception.The config schema system has no way to know the name of the schema definition entry for a given entity type ('filter.format.*', or 'field.instance.*.*.*', with the right number of '*' parts). It only guesses by trial and error from an actual config name like field.instance.foo.bar.baz, but there is no way to get the schema for an entity that can't provide a valid config name yet.
Arguably that's a bug ? EntityInterface::toArray() states "Returns an array of all property values". Nothing in there says the entity needs to be in this or that state ?
Comment #62
Gábor HojtsyBased on discussion on last week's CMI meeting, I opened #2361539: Config export key order is not predictable for sequences, add orderby property to config schema to take this to the next level.