Problem/Motivation
As shown in #2350821: Sort views displays by display name and #2350537: Enforce order of display of components in config export shows that even though #2256679: Use config schema to determine which config entity properties to export regardless of whether they are public or protected made use of config schema to export the top level keys, for lower levels we still rely on the data provided as-is. The problem is most acute for sequences where we need to sort by key or value. If the sequence is not sorted then the order in which things are configured can produce different configuration even though they result in exactly the same functional effects.
Proposed resolution
The current patch (#39) adds the ability to define an orderby
key in the config schema definition.
Examples:
user.role.*:
// ... other config schema key definitions
permissions:
type: sequence
label: 'Permissions'
orderby: value
sequence:
type: string
label: 'Permission'
workflow.type_settings.content_moderation:
type: mapping
mapping:
states:
type: sequence
label: 'Additional state configuration for content moderation'
orderby: key
sequence:
type: mapping
label: 'States'
mapping:
published:
type: boolean
label: 'Is published'
default_revision:
type: boolean
label: 'Is default revision'
Remaining tasks
Agree. Do it.
User interface changes
None. Diffs of config changes will be much more reliable.
API changes
None.
Comment | File | Size | Author |
---|---|---|---|
#70 | interdiff-2361539-67-70.txt | 967 bytes | himanshu-dixit |
#70 | 2361539-70.patch | 8.27 KB | himanshu-dixit |
#67 | 2361539-66.patch | 8.17 KB | alexpott |
#67 | 66-66-interdiff.txt | 736 bytes | alexpott |
#60 | 2361539-60.patch | 7.87 KB | alexpott |
Comments
Comment #1
Gábor HojtsyComment #2
alexpottComment #3
webflo CreditAttribution: webflo commentedClosed #2352705: [META] Introduce explicit order in config files in favor of this issue.
Comment #4
webflo CreditAttribution: webflo commented#2227731: Normalize configuration data during config writes is required to sort top level schema keys.
Comment #5
yukare CreditAttribution: yukare commentedWhat we do when the order of itens is important and must not change ?
Comment #6
k4v CreditAttribution: k4v commentedFor user role permissions we have a patch: https://www.drupal.org/node/2409129
Comment #7
webflo CreditAttribution: webflo commentedFirst attempt.
Comment #11
webflo CreditAttribution: webflo commentedComment #13
webflo CreditAttribution: webflo commentedComment #14
webflo CreditAttribution: webflo commentedComment #16
webflo CreditAttribution: webflo commentedComment #17
webflo CreditAttribution: webflo commentedComment #19
webflo CreditAttribution: webflo commentedComment #21
jhedstromComment #22
AjitSRerolling
Comment #24
AjitSRerolling again.
Comment #26
AjitSCorrected.
Comment #27
AjitSComment #29
deepakaryan1988Removing sprint weekend tag!!
As suggested by @YesCT
Comment #30
YesCT CreditAttribution: YesCT commented@deepakaryan1988 The tag was added January 17, 2015 during the actual global sprint weekend. See https://groups.drupal.org/node/447258
Please leave the tag on issues that were actually worked on during that event.
I think you might have confused a message from May about the sprint weekend tag, that it should not be added to events from May. The tag is for issues worked on during https://groups.drupal.org/node/447258 by people attending sprint weekend sprints.
Comment #31
deepakaryan1988@YesCT sorry for this!
Comment #33
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedComment #34
jonathanshawSurely this should be Needs Work as there is no patch passing tests?
Comment #35
tim.plunkettYou can always mark it needs work yourself.
And don't call me Shirley.
Comment #38
xjmThis came up again in #2850601: ContentModeration workflow type plugin incorrectly preserves bundle keys on sorting and does not sort entity types. I think this is one of the most common kinds of bugs in config implementations and very easy to get wrong. And even after it's fixed, fixing it still can require upgrade paths and add noise to people's config diffs. So definitely agree that this is a major bug.
Comment #39
alexpottHere's an approach that is more storage focused but less of an API change than @webflo's previous work. This is entirely additive.
Comment #40
alexpottRe-scoping the issue to just deal with sequences - will file a followup to tackle Mapping. This is much more complex because we probably should follow the order as defined by schema - BUT this could result in massive change. Luckily root keys in config entity schema already do this (i think).
Comment #41
alexpottComment #42
alexpottComment #43
alexpottAdded follow-up for maps #2852557: Config export key order is not predictable, use config schema to order keys for maps
Comment #44
alexpottAdded CR https://www.drupal.org/node/2852566
Comment #45
alexpottSome more test coverage just to ensure we don't mess anything up when the sequence contains something different from scalar values.
Comment #46
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedHaving this is for sequences is a huge step forward. Test coverage looks good.
Comment #47
alexpottI'm not convinced about setting this default here. In D9 we should pick a default - either key or value (probably value) but supporting none seems unnecessary. All config sequences should be sorted. We might need to add more complex sorts - ie by a value in a mapping contained with the sequence but
none
is not really an option.Array access to data definition is deprecated - let's add a getter to the Sequence class.
Comment #48
alexpottThinking about how we can avoid using the ArrayAccess BC layer - some related issues: #1928868: Typed config incorrectly implements Typed Data interfaces and #2350597: Extract a common DataContainerInterface for lists and complex data
Comment #49
alexpottAddressing #47 and #48. As far as I can see this approach does not cause any issues the issues linked in #48.
Comment #50
alexpottFiled a followup to use
orderby
in all of core - #2855675: Add orderby key to all sequences in coreComment #51
dawehnerUsing the additional class makes sense. Its a way for a better future.
Comment #52
quietone CreditAttribution: quietone as a volunteer commenteds/do//
Comment #53
alexpottFixed #52 - thanks @quietone
Comment #54
xjmI did a double-take at this hunk, but of course SequenceDataDefinition is extending ListDataDefinition, so all fine there.
"Either" can't be used with a list of three things. For that matter, the sentence does not have a subject or a verb. I can fix this on commit. This would work:
I hadn't actually expected a value sort would be supported, but it sounds from the issue comments that there are usecases for that. I also briefly asked myself (as I do with any integer or string parameter values with special meaning) whether these should be constants, but since they also are string values that get added to the schemata, it's clearer to just use the strings.
This doesn't follow our verb-first standard, but I checked and the class it's extending from doesn't either, so eh.
Pretty sure our standards require an empty line after a break statement. I can fix this on commit.
Tests.
Ah, interesting. So this would be to avoid the scenario where in that Workflow issue some serial keys got saved to the config weirdly?
Ah wow. Not only does the value sort not preserve serial keys, it does not preserve any keys at all, even strings keys. I did not expect that. (Edit: removed nonsensical sentence; the patch uses plain old
sort()
). Anyway, I think we definitely need to document that because otherwise this could lead to data loss if people don't realize the value sort is intended to not preserve keys.NW for last point; nits could be fixed too.
Comment #55
xjmBased on point 7, I'd rewrite point 2 as:
This issue reminded me of why I'd come to avoid using
sort()
. The PHP docs say:I realized I don't actually know if that means "unexpected, but consistent" or "possibly non-deterministic". I'd hope the former, in which case I guess it may not matter because what does matter regardless is that the order is consistent. But given that a schema can be mixed data types with various depths of mappings or flat mixed arrays together in the same, is this a concern?
Edit: Maybe a couple more test cases where the data types are mixed?
Comment #56
tameeshb CreditAttribution: tameeshb at Google Summer of Code commentedChanges from:
#54.2,.4,.5
Comment #57
tameeshb CreditAttribution: tameeshb at Google Summer of Code commentedComment #58
himanshu-dixit CreditAttribution: himanshu-dixit as a volunteer commentedHere is the new patch, but still we need more test cases.
NR for other things.
Comment #59
himanshu-dixit CreditAttribution: himanshu-dixit as a volunteer commentedSorry, NW was set before i submitted the post :( Setting it to NR
Comment #60
alexpottRe value sorting and not preserving keys. This behaviour is vital. If we preserved keys then we'd get lots and lots of arrays where the numeric keys had been converted to strings and the order in which you configured things would matter. Basically breaking the entire point of this change. Unfortunately PHP does not make it easy to determine when an array is associative or not. I considered added a non destructive value sort but rejected this as over-engineering. If you care about the keys do a key sort. If you have a true non-associative array do a value sort.
Also we sequences we're lucky re the type thing - we are guaranteed that all the values are of the same type because it is defined in the sequence and enforced in \Drupal\Core\Config\StorableConfigBase::castValue() before we do any sorting - so fortunately we don't have to worry about that. And I don't think we need more tests because we can't actually mix the data types.
Re #54.3 Maybe we need to fix our coding standard - verbs just don't work for 90% of our class doc blocks. Classes tend to be nouns.
I realised we can do without the method duplication on Sequence and SequenceDataDefinition.
@himanshu-dixit sorry I didn't build on your patch but it also made a breaking change to core/config/schema/core.data_types.schema.yml #54.1 wasn't saying the change was wrong - just that it was surprising to @xjm.
Comment #61
alexpottUpdated the CR to be more explicit about the associative / non-associative thing.
Comment #62
alexpottWhen this is committed we need to update https://www.drupal.org/docs/8/api/configuration-api/configuration-schema... and we probably ought to create a whole new page about sorting of configuration since it is a key topic wrt to reliable and sane config deployments.
Comment #63
xjmCan we add that to the docs (inline and/or docblock)? It's helpful information.
Comment #65
xjmFor #63, I meant maybe an inline comment actually directly above the
sort()
in the switch statement, since that's the kind of thing people might scan codebases for and try to "fix" etc. Not sure if it's worth mentioning in the docblock itself really.Comment #66
xjmLet's file a followup docs issue also for #62.
Comment #67
alexpottI discussed the possibility of making the
orderby
a callback where it'd perform a sort by calling the callback. Originally I thought we might just do this for everything so orderBy should take values ofsort
andksort
but I think there is still value in doing the simple declarative thing in schema. This means that an alternative system can validate config without having a running code base.Not sorting callbacks means that if you have advanced cases like
module_config_sort()
I think these have to remain in code. Which, in turn, means we might have to reconsider the 'none' option. Or perhaps call it something other than 'none'. But we can defer these choices till we try to do #2855675: Add orderby key to all sequences in core because that'll highlight these issues. We know we're not wrong by implementingvalue
andkey
sorts and it is nice that people don't have to think about which PHP sort function to call.
Comment #68
himanshu-dixit CreditAttribution: himanshu-dixit as a volunteer commentedThis looks really good now.
Comment #69
xjmThe word "Fortunately" is unnecessary and "we" did not do anything. I'd say instead:
I can update that on commit, but won't probably commit until tomorrow. @himanshu-dixit, maybe you could make that update as well? I think it's okay to leave it RTBC if you agree with the change since it's a small clarification rather than new documentation.
Comment #70
himanshu-dixit CreditAttribution: himanshu-dixit as a volunteer commentedHere is the new patch updating documentation.
Comment #71
tameeshb CreditAttribution: tameeshb at Google Summer of Code commentedRTBC+
Comment #72
xjmThe docs followup issue for #62 did not seem to exist yet, so I filed #2857879: Update Configuration system documentation on sorting.
Comment #73
xjm@yukare, regarding:
In that case your implementation should explicitly enforce the ordering that is correct on save. Followups for this might add support for custom orderby callbacks as well, but for now, it's best to pass in
NULL
so there is no sorting by theSequenceDataDefiniton
and make sure your config is saved in a consistent order that will not accidentally change.As an API addition, this goes into the development branch, so committed to 8.4.x. I also published the CR. Thanks everyone!
Comment #75
himanshu-dixit CreditAttribution: himanshu-dixit as a volunteer and at Google Summer of Code commentedAttributing the contribution to GSoC.
Comment #76
Wim LeersI was coming here to ask why the behavior for non-primitive sequences was not defined. Because neither the CR nor the IS explain this. But I'm happy to see that there appears to be test coverage for that case :)
(Coming from #2874633: [PP-1] Update CDN module for Drupal 8.4.x: 'orderby' in config schema for sequences.)
Comment #77
Wim LeersActually, there is an important question that is not answered by the CR or the IS, at least not AFAICT. Quoting #2874633-5: [PP-1] Update CDN module for Drupal 8.4.x: 'orderby' in config schema for sequences:
Reopening this issue to get an answer to that question documented in the CR, because more modules will struggle with that.
Comment #78
alexpott@Wim Leers hmmm this is a good question. Actually in this instance the best practice is to have a weight key and sort by something that does not change. This means that if things are re-ordered when you review the config change the only thing you have to review is the weight key changes. However maybe we need to add "in the order added" type of "sort" so at least the current behaviour of cdn could be documented and we could document that this is bad practice and recommend ways of fixing it.
Comment #79
Wim Leers+1 to both of those.
Comment #80
Wim LeersBy the way, an example of exactly the same problem/requirement can be found in
ckeditor.schema.yml
: the Toolbar configuration mapping contains a sequence of rows, which contains a sequence of buttons groups, which contains a sequence of buttons. None of them have "weight" or "priority"; the order is relevant there, too.So this is not a problem that's exclusive to contrib. And probably there are even more like these in other places in core.
Comment #81
Wim LeersMoved #76—#80 into a follow-up issue: #2885368: Config export key order for sequences: "orderby" does not support cases where the order actually matters.
Comment #83
catchComment #84
Amber Himes MatzWas there a changelog created for this change? Also, I'm not seeing anything about an 'orderby' key in this documentation page: https://www.drupal.org/docs/8/api/configuration-api/configuration-schema...
Would someone familiar with this issue and its solution at the very least update the documentation page?
I see the property is already in use by the content_moderation module in /content_moderation/config/schema/content_moderation.schema.yml and it should be documented.