-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Recursively step through edits to track individually changed post meta #10827
Conversation
I think I ran into this with #10204 (comment) too. |
Want to get some much more knowledgeable eyes on this, since it will involve changes to the way edits are handled. I'm curious about broader impacts it might have. |
Instead of always considering Exemple: A plugin can call If our intention in the first call is to replace the customProperty value entirely, how do we know it? how does a potential selector called Maybe the solution is to reshape the reducer of
which also mean we need a corresponding cc @aduth as you're the most familiar with how we deal with edits. |
It's an interesting one 🙂 Should it really matter if we send redundant data? I don't really understand why the REST API should return an error response for noop (re #10204 (comment)). It does have an interesting impact on #7409 / #10844, where we'd roughly use a simple To the idea of reshaping edits: It might serve this case better, but I expect would also have a negative impact on performance of hot-path selectors like Looking at the current implementation, it's not clear to me why we should need to be doing anything at all in |
REST API design question: Is it safe to assume that any values of type |
For your consideration, I've pushed a couple commits to the branch, the result of explorations considered in #10827 (comment) . Namely:
|
@aduth How do you address the ambiguity raised here #10827 (comment) Where you don't really know what to return from . |
I think this relates to #10827 (comment) . If we assume if the value is an object, we know to merge edits as partial to what's current saved value. This may not actually be happening (yet) if one calls |
We can assume the edits are partial for "meta" because that's Core but can we assume it for all post object properties. I think users can register custom properties there. |
I don't know the answer to this. It is a requirement for my proposal to work, yes, and also the intention of the question raised in #10827 (comment) . |
To be honest, I think this is a bug. I have it on my personal todo list to open a Trac ticket for it. |
The same sort of thing also occurs in the new autosave endpoint, during whose development I'd also raised some contest toward. |
Alternatively, maybe it's fine to have a manually curated list of properties for which we want to enable this merging behavior? As a constant in one of the store files. |
This is the design intent, yes. As always we may have missed areas where we are internally inconsistent but core REST API endpoints should handle incomplete PUT's as partial updates without affecting unrelated existing data. |
Discussed today in Slack (link requires registration): https://wordpress.slack.com/archives/C02RQC26G/p1541094531087100 If we can assume nested values should always be treated as partial updates, then this branch should be considered complete and ready for review in its current state. |
This should be tested :) Assumptions can be dangerous. |
f37925c
to
7b6bccd
Compare
I've rebased to resolve conflicts with other recent pull requests which have touched I started to look at how and where the REST API treats objects, first and foremost for the posts endpoint as it's the one relevant here (though establishing a general pattern could be useful too). With the controllers overloaded support of content fields ( For now, I might see to limiting this to a subset of known properties (meta). |
Also, while the implementation here has treated updates as deeply recursive, this is not in-fact supported in the meta fields updates (top-level key only). |
The latest commit 40a96ee significantly scales back the extent of the changes here to simply perform a shallow merge on whitelisted post properties ( |
Is it important for RC? We need to decide today whether is ready or punt it. |
I think we should land this PR. It's a pretty glaring issue for any custom block development using post meta. |
I haven't fully tested it though, so I don't know @aduth's decision to hold on it initially. |
This is and has been ready for a final review. Technically I could approve it myself, but the most recent revision is almost entirely of my authoring. ¯\_(ツ)_/¯ |
Given that it has a set of unit tests which ensure it works as intended, I would be personally fine to have @aduth giving 👍 to this PR. Can someone confirm it solves the issue? |
@@ -264,7 +281,7 @@ export const editor = flow( [ | |||
( key ) => getPostRawValue( action.post[ key ] ); | |||
|
|||
return reduce( state, ( result, value, key ) => { | |||
if ( value !== getCanonicalValue( key ) ) { | |||
if ( ! isEqual( value, getCanonicalValue( key ) ) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Granting there's one odd edge case for which this doesn't cover: If updates are applied, individual keys won't be unset unless all meta values are now equal with their new canonical values. e.g.
{ type: 'EDIT_POST', edits: { meta: { a: 1, b: 2 } } }
// { edits: { meta: { a: 1, b: 2 } } }
{ type: 'UPDATE_POST', edits: { meta: { a: 1 } } }
// { edits: { meta: { a: 1, b: 2 } } }
{ type: 'UPDATE_POST', edits: { meta: { a: 1, b: 2 } } }
// { edits: {} }
In practice, I don't think this would ever occur (UPDATE_POST
is called on save with all edited values assumed as being the new canonical), and the impact being that it would continue to save edited values which had already been saved before.
The alternative would be an implementation which would individually unset keys and remove the top-level key once empty.
I can confirm the branch in its current form solves the issue as described in #6505. I can't approve it though because I'm technically the original PR author, even though it's totally changed from that point. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's merge it in its current form. My prior noted caveat can be considered separately as an enhancement (I'll create an issue).
See #12065 |
I suspect this PR broke plugins doing related #12289 |
Description
First off, this may be a terrible idea. 😄
In #6505 we noticed that all post meta gets sent any time there is change to any post meta. This has the effect of saving the default value for each registered meta when only one of them is changed.
The reason for this is two part:
state
parameter to the reducer.
edits
vsstate
and replaces the entire object if they are different. Since the full object of registered meta is sent as thestate
, the full object would be replaced if there was a change to any one meta value. This also means that when edits are tracked, it treats the full meta object as edited, even when only one meta value is actually changed.My solution here is to pass only the changed meta values as state when edited in a block, then in the reducer, recursively step down into any edited objects.
This has the effect of tracking changes to individual meta values in edit, but also means that only changed meta values are sent via the REST API when a post is saved.
I considered just making an exception for meta in the edits reducer, but I thought it would be better to keep it generic, so that any attribute that used object stores could be granularly updated and actual edits more accurately tracked.
How has this been tested?
Checklist: