Skip to content
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

Add isRawAttribute to entity config #34388

Merged
merged 12 commits into from
Sep 3, 2021
Merged

Conversation

adamziel
Copy link
Contributor

@adamziel adamziel commented Aug 30, 2021

Description

Solves #34335

As seen in #34335, core-data always assumes that entity records fields with a raw attribute are always "flattened" by getRawEntityRecord.

This behavior is useful for posts: content.raw in a post or a page refers to HTML with block markup as opposed to content.rendered which is the HTML without block markup.

Unfortunately, for other entity records such as widgets, this behavior is undesired.

To remedy the problem, this PR adds an explicit entity configuration field called rawAttributes which may be used to specify which fields should be treated as block markup HTML.

The downside of this approach is a BC break so I wonder if a safer solution here would be to do a "denylist" instead of an "allowlist" (e.g. nonRawAttributes).

How has this been tested?

  • Confirm the tests are green
  • Create a new post, save it, change the contents, save again, confirm everything worked as expected
  • Go to the widgets editor (/wp-admin/widgets.php), update a single widget, click "Update", confirm that the batch request only contained a single child request related to the updated widget (as opposed to one per widget).

Types of changes

New feature (non-breaking change which adds functionality)

@adamziel adamziel added the [Package] Core data /packages/core-data label Aug 30, 2021
@adamziel adamziel requested a review from nerrad as a code owner August 30, 2021 15:02
@adamziel adamziel self-assigned this Aug 30, 2021
@@ -373,6 +373,7 @@ export const saveEntityRecord = (
}
const entityIdKey = entity.key || DEFAULT_ENTITY_KEY;
const recordId = record[ entityIdKey ];
const rawAttributes = entity.rawAttributes || [];
Copy link
Contributor Author

@adamziel adamziel Aug 30, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have to keep doing || [] and rawAttributes.includes( key ) so maybe wonder a selector like isRawAttribute( state, kind, name, attributeName ) would be more convenient here.

@github-actions
Copy link

github-actions bot commented Aug 30, 2021

Size Change: -2.05 kB (0%)

Total Size: 1.04 MB

Filename Size Change
build/block-editor/index.min.js 119 kB +232 B (0%)
build/block-library/blocks/gallery/editor-rtl.css 925 B +46 B (+5%) 🔍
build/block-library/blocks/gallery/editor.css 929 B +53 B (+6%) 🔍
build/block-library/common-rtl.css 853 B -437 B (-34%) 🎉
build/block-library/common.css 849 B -439 B (-34%) 🎉
build/block-library/editor-rtl.css 9.52 kB -410 B (-4%)
build/block-library/editor.css 9.51 kB -411 B (-4%)
build/block-library/index.min.js 150 kB -35 B (0%)
build/block-library/style-rtl.css 10.2 kB -437 B (-4%)
build/block-library/style.css 10.2 kB -435 B (-4%)
build/blocks/index.min.js 46.9 kB -18 B (0%)
build/components/index.min.js 209 kB +6 B (0%)
build/components/style-rtl.css 15.8 kB +35 B (0%)
build/components/style.css 15.8 kB +33 B (0%)
build/core-data/index.min.js 12.4 kB +38 B (0%)
build/edit-navigation/index.min.js 13.6 kB +2 B (0%)
build/edit-post/index.min.js 29 kB +35 B (0%)
build/edit-site/index.min.js 26.3 kB +101 B (0%)
build/edit-widgets/index.min.js 16 kB -1 B (0%)
build/rich-text/index.min.js 10.6 kB -8 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 931 B
build/admin-manifest/index.min.js 1.09 kB
build/annotations/index.min.js 2.7 kB
build/api-fetch/index.min.js 2.19 kB
build/autop/index.min.js 2.08 kB
build/blob/index.min.js 459 B
build/block-directory/index.min.js 6.2 kB
build/block-directory/style-rtl.css 1.01 kB
build/block-directory/style.css 1.01 kB
build/block-editor/default-editor-styles-rtl.css 378 B
build/block-editor/default-editor-styles.css 378 B
build/block-editor/style-rtl.css 13.8 kB
build/block-editor/style.css 13.8 kB
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 65 B
build/block-library/blocks/archives/style.css 65 B
build/block-library/blocks/audio/editor-rtl.css 58 B
build/block-library/blocks/audio/editor.css 58 B
build/block-library/blocks/audio/style-rtl.css 111 B
build/block-library/blocks/audio/style.css 111 B
build/block-library/blocks/audio/theme-rtl.css 125 B
build/block-library/blocks/audio/theme.css 125 B
build/block-library/blocks/block/editor-rtl.css 161 B
build/block-library/blocks/block/editor.css 161 B
build/block-library/blocks/button/editor-rtl.css 474 B
build/block-library/blocks/button/editor.css 474 B
build/block-library/blocks/button/style-rtl.css 600 B
build/block-library/blocks/button/style.css 600 B
build/block-library/blocks/buttons/editor-rtl.css 315 B
build/block-library/blocks/buttons/editor.css 315 B
build/block-library/blocks/buttons/style-rtl.css 370 B
build/block-library/blocks/buttons/style.css 370 B
build/block-library/blocks/calendar/style-rtl.css 207 B
build/block-library/blocks/calendar/style.css 207 B
build/block-library/blocks/categories/editor-rtl.css 84 B
build/block-library/blocks/categories/editor.css 83 B
build/block-library/blocks/categories/style-rtl.css 79 B
build/block-library/blocks/categories/style.css 79 B
build/block-library/blocks/code/style-rtl.css 90 B
build/block-library/blocks/code/style.css 90 B
build/block-library/blocks/code/theme-rtl.css 131 B
build/block-library/blocks/code/theme.css 131 B
build/block-library/blocks/columns/editor-rtl.css 194 B
build/block-library/blocks/columns/editor.css 193 B
build/block-library/blocks/columns/style-rtl.css 474 B
build/block-library/blocks/columns/style.css 475 B
build/block-library/blocks/cover/editor-rtl.css 666 B
build/block-library/blocks/cover/editor.css 670 B
build/block-library/blocks/cover/style-rtl.css 1.23 kB
build/block-library/blocks/cover/style.css 1.23 kB
build/block-library/blocks/embed/editor-rtl.css 488 B
build/block-library/blocks/embed/editor.css 488 B
build/block-library/blocks/embed/style-rtl.css 417 B
build/block-library/blocks/embed/style.css 417 B
build/block-library/blocks/embed/theme-rtl.css 124 B
build/block-library/blocks/embed/theme.css 124 B
build/block-library/blocks/file/editor-rtl.css 300 B
build/block-library/blocks/file/editor.css 300 B
build/block-library/blocks/file/style-rtl.css 255 B
build/block-library/blocks/file/style.css 255 B
build/block-library/blocks/file/view.min.js 322 B
build/block-library/blocks/freeform/editor-rtl.css 2.44 kB
build/block-library/blocks/freeform/editor.css 2.44 kB
build/block-library/blocks/gallery/style-rtl.css 1.61 kB
build/block-library/blocks/gallery/style.css 1.61 kB
build/block-library/blocks/gallery/theme-rtl.css 122 B
build/block-library/blocks/gallery/theme.css 122 B
build/block-library/blocks/group/editor-rtl.css 159 B
build/block-library/blocks/group/editor.css 159 B
build/block-library/blocks/group/style-rtl.css 57 B
build/block-library/blocks/group/style.css 57 B
build/block-library/blocks/group/theme-rtl.css 70 B
build/block-library/blocks/group/theme.css 70 B
build/block-library/blocks/heading/style-rtl.css 114 B
build/block-library/blocks/heading/style.css 114 B
build/block-library/blocks/home-link/style-rtl.css 247 B
build/block-library/blocks/home-link/style.css 247 B
build/block-library/blocks/html/editor-rtl.css 283 B
build/block-library/blocks/html/editor.css 284 B
build/block-library/blocks/image/editor-rtl.css 728 B
build/block-library/blocks/image/editor.css 728 B
build/block-library/blocks/image/style-rtl.css 482 B
build/block-library/blocks/image/style.css 487 B
build/block-library/blocks/image/theme-rtl.css 124 B
build/block-library/blocks/image/theme.css 124 B
build/block-library/blocks/latest-comments/style-rtl.css 284 B
build/block-library/blocks/latest-comments/style.css 284 B
build/block-library/blocks/latest-posts/editor-rtl.css 137 B
build/block-library/blocks/latest-posts/editor.css 137 B
build/block-library/blocks/latest-posts/style-rtl.css 528 B
build/block-library/blocks/latest-posts/style.css 527 B
build/block-library/blocks/list/style-rtl.css 94 B
build/block-library/blocks/list/style.css 94 B
build/block-library/blocks/media-text/editor-rtl.css 266 B
build/block-library/blocks/media-text/editor.css 263 B
build/block-library/blocks/media-text/style-rtl.css 488 B
build/block-library/blocks/media-text/style.css 485 B
build/block-library/blocks/more/editor-rtl.css 431 B
build/block-library/blocks/more/editor.css 431 B
build/block-library/blocks/navigation-link/editor-rtl.css 489 B
build/block-library/blocks/navigation-link/editor.css 488 B
build/block-library/blocks/navigation-link/style-rtl.css 94 B
build/block-library/blocks/navigation-link/style.css 94 B
build/block-library/blocks/navigation/editor-rtl.css 1.72 kB
build/block-library/blocks/navigation/editor.css 1.72 kB
build/block-library/blocks/navigation/style-rtl.css 1.42 kB
build/block-library/blocks/navigation/style.css 1.41 kB
build/block-library/blocks/navigation/view.min.js 2.52 kB
build/block-library/blocks/nextpage/editor-rtl.css 395 B
build/block-library/blocks/nextpage/editor.css 395 B
build/block-library/blocks/page-list/editor-rtl.css 310 B
build/block-library/blocks/page-list/editor.css 310 B
build/block-library/blocks/page-list/style-rtl.css 241 B
build/block-library/blocks/page-list/style.css 241 B
build/block-library/blocks/paragraph/editor-rtl.css 157 B
build/block-library/blocks/paragraph/editor.css 157 B
build/block-library/blocks/paragraph/style-rtl.css 261 B
build/block-library/blocks/paragraph/style.css 261 B
build/block-library/blocks/post-author/editor-rtl.css 210 B
build/block-library/blocks/post-author/editor.css 210 B
build/block-library/blocks/post-author/style-rtl.css 182 B
build/block-library/blocks/post-author/style.css 181 B
build/block-library/blocks/post-comments-form/style-rtl.css 140 B
build/block-library/blocks/post-comments-form/style.css 140 B
build/block-library/blocks/post-comments/style-rtl.css 360 B
build/block-library/blocks/post-comments/style.css 359 B
build/block-library/blocks/post-content/editor-rtl.css 138 B
build/block-library/blocks/post-content/editor.css 138 B
build/block-library/blocks/post-excerpt/editor-rtl.css 73 B
build/block-library/blocks/post-excerpt/editor.css 73 B
build/block-library/blocks/post-excerpt/style-rtl.css 69 B
build/block-library/blocks/post-excerpt/style.css 69 B
build/block-library/blocks/post-featured-image/editor-rtl.css 398 B
build/block-library/blocks/post-featured-image/editor.css 398 B
build/block-library/blocks/post-featured-image/style-rtl.css 143 B
build/block-library/blocks/post-featured-image/style.css 143 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 378 B
build/block-library/blocks/post-template/style.css 379 B
build/block-library/blocks/post-terms/style-rtl.css 73 B
build/block-library/blocks/post-terms/style.css 73 B
build/block-library/blocks/post-title/style-rtl.css 60 B
build/block-library/blocks/post-title/style.css 60 B
build/block-library/blocks/preformatted/style-rtl.css 103 B
build/block-library/blocks/preformatted/style.css 103 B
build/block-library/blocks/pullquote/editor-rtl.css 198 B
build/block-library/blocks/pullquote/editor.css 198 B
build/block-library/blocks/pullquote/style-rtl.css 378 B
build/block-library/blocks/pullquote/style.css 378 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B
build/block-library/blocks/query-pagination/editor-rtl.css 270 B
build/block-library/blocks/query-pagination/editor.css 262 B
build/block-library/blocks/query-pagination/style-rtl.css 168 B
build/block-library/blocks/query-pagination/style.css 168 B
build/block-library/blocks/query-title/editor-rtl.css 85 B
build/block-library/blocks/query-title/editor.css 85 B
build/block-library/blocks/query/editor-rtl.css 131 B
build/block-library/blocks/query/editor.css 132 B
build/block-library/blocks/quote/style-rtl.css 187 B
build/block-library/blocks/quote/style.css 187 B
build/block-library/blocks/quote/theme-rtl.css 220 B
build/block-library/blocks/quote/theme.css 222 B
build/block-library/blocks/rss/editor-rtl.css 202 B
build/block-library/blocks/rss/editor.css 204 B
build/block-library/blocks/rss/style-rtl.css 289 B
build/block-library/blocks/rss/style.css 288 B
build/block-library/blocks/search/editor-rtl.css 165 B
build/block-library/blocks/search/editor.css 165 B
build/block-library/blocks/search/style-rtl.css 374 B
build/block-library/blocks/search/style.css 375 B
build/block-library/blocks/search/theme-rtl.css 64 B
build/block-library/blocks/search/theme.css 64 B
build/block-library/blocks/separator/editor-rtl.css 99 B
build/block-library/blocks/separator/editor.css 99 B
build/block-library/blocks/separator/style-rtl.css 250 B
build/block-library/blocks/separator/style.css 250 B
build/block-library/blocks/separator/theme-rtl.css 172 B
build/block-library/blocks/separator/theme.css 172 B
build/block-library/blocks/shortcode/editor-rtl.css 474 B
build/block-library/blocks/shortcode/editor.css 474 B
build/block-library/blocks/site-logo/editor-rtl.css 462 B
build/block-library/blocks/site-logo/editor.css 464 B
build/block-library/blocks/site-logo/style-rtl.css 153 B
build/block-library/blocks/site-logo/style.css 153 B
build/block-library/blocks/site-tagline/editor-rtl.css 86 B
build/block-library/blocks/site-tagline/editor.css 86 B
build/block-library/blocks/site-title/editor-rtl.css 84 B
build/block-library/blocks/site-title/editor.css 84 B
build/block-library/blocks/social-link/editor-rtl.css 165 B
build/block-library/blocks/social-link/editor.css 165 B
build/block-library/blocks/social-links/editor-rtl.css 812 B
build/block-library/blocks/social-links/editor.css 811 B
build/block-library/blocks/social-links/style-rtl.css 1.33 kB
build/block-library/blocks/social-links/style.css 1.33 kB
build/block-library/blocks/spacer/editor-rtl.css 307 B
build/block-library/blocks/spacer/editor.css 307 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table/editor-rtl.css 471 B
build/block-library/blocks/table/editor.css 472 B
build/block-library/blocks/table/style-rtl.css 481 B
build/block-library/blocks/table/style.css 481 B
build/block-library/blocks/table/theme-rtl.css 188 B
build/block-library/blocks/table/theme.css 188 B
build/block-library/blocks/tag-cloud/style-rtl.css 146 B
build/block-library/blocks/tag-cloud/style.css 146 B
build/block-library/blocks/template-part/editor-rtl.css 636 B
build/block-library/blocks/template-part/editor.css 635 B
build/block-library/blocks/template-part/theme-rtl.css 101 B
build/block-library/blocks/template-part/theme.css 101 B
build/block-library/blocks/term-description/editor-rtl.css 90 B
build/block-library/blocks/term-description/editor.css 90 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 166 B
build/block-library/blocks/text-columns/style.css 166 B
build/block-library/blocks/verse/style-rtl.css 87 B
build/block-library/blocks/verse/style.css 87 B
build/block-library/blocks/video/editor-rtl.css 571 B
build/block-library/blocks/video/editor.css 572 B
build/block-library/blocks/video/style-rtl.css 173 B
build/block-library/blocks/video/style.css 173 B
build/block-library/blocks/video/theme-rtl.css 124 B
build/block-library/blocks/video/theme.css 124 B
build/block-library/reset-rtl.css 527 B
build/block-library/reset.css 527 B
build/block-library/theme-rtl.css 658 B
build/block-library/theme.css 663 B
build/block-serialization-default-parser/index.min.js 1.09 kB
build/block-serialization-spec-parser/index.min.js 2.79 kB
build/compose/index.min.js 10.2 kB
build/customize-widgets/index.min.js 11.1 kB
build/customize-widgets/style-rtl.css 1.5 kB
build/customize-widgets/style.css 1.49 kB
build/data-controls/index.min.js 614 B
build/data/index.min.js 7.1 kB
build/date/index.min.js 31.5 kB
build/deprecated/index.min.js 428 B
build/dom-ready/index.min.js 304 B
build/dom/index.min.js 4.53 kB
build/edit-navigation/style-rtl.css 3.14 kB
build/edit-navigation/style.css 3.14 kB
build/edit-post/classic-rtl.css 492 B
build/edit-post/classic.css 494 B
build/edit-post/style-rtl.css 7.2 kB
build/edit-post/style.css 7.19 kB
build/edit-site/style-rtl.css 5.07 kB
build/edit-site/style.css 5.07 kB
build/edit-widgets/style-rtl.css 4.06 kB
build/edit-widgets/style.css 4.06 kB
build/editor/index.min.js 37.6 kB
build/editor/style-rtl.css 3.74 kB
build/editor/style.css 3.73 kB
build/element/index.min.js 3.17 kB
build/escape-html/index.min.js 517 B
build/format-library/index.min.js 5.36 kB
build/format-library/style-rtl.css 668 B
build/format-library/style.css 669 B
build/hooks/index.min.js 1.55 kB
build/html-entities/index.min.js 424 B
build/i18n/index.min.js 3.6 kB
build/is-shallow-equal/index.min.js 501 B
build/keyboard-shortcuts/index.min.js 1.49 kB
build/keycodes/index.min.js 1.25 kB
build/list-reusable-blocks/index.min.js 1.85 kB
build/list-reusable-blocks/style-rtl.css 838 B
build/list-reusable-blocks/style.css 838 B
build/media-utils/index.min.js 2.88 kB
build/notices/index.min.js 845 B
build/nux/index.min.js 2.03 kB
build/nux/style-rtl.css 747 B
build/nux/style.css 743 B
build/plugins/index.min.js 1.83 kB
build/primitives/index.min.js 921 B
build/priority-queue/index.min.js 582 B
build/react-i18n/index.min.js 671 B
build/redux-routine/index.min.js 2.63 kB
build/reusable-blocks/index.min.js 2.28 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/server-side-render/index.min.js 1.32 kB
build/shortcode/index.min.js 1.48 kB
build/token-list/index.min.js 562 B
build/url/index.min.js 1.74 kB
build/viewport/index.min.js 1.02 kB
build/warning/index.min.js 248 B
build/widgets/index.min.js 6.37 kB
build/widgets/style-rtl.css 1.05 kB
build/widgets/style.css 1.05 kB
build/wordcount/index.min.js 1.04 kB

compressed-size-action

*
* @return {boolean} Is the attribute raw
*/
export function isRawAttribute( state, kind, name, attribute ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be a public selector?

Copy link
Contributor Author

@adamziel adamziel Aug 31, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer it to be private. The only reason why it's public is that saveEntityRecord needs to call it. How about we change the name to __unstableIsRawAttribute to fix the widgets bug, and then later remove it as a part of the larger refactoring discussed below?

Or did you just mean to remove it from core-data exports?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or did you just mean to remove it from core-data exports?

I think this is what @youknowriad meant. If we can avoid exporting it then I'd prefer that too 🙂

@noisysocks
Copy link
Member

noisysocks commented Aug 31, 2021

The downside of this approach is a BC break so I wonder if a safer solution here would be to do a "denylist" instead of an "allowlist" (e.g. nonRawAttributes).

Personally I think it would be okay to break backwards compatibility in this case but we should note it in CHANGELOG.md so that the major version of @wordpress/core-data is bumped.

@noisysocks
Copy link
Member

This is definitely better but it's all still a bit weird to me 😀

What's irking me is that getRawEntityRecord even exists in @wordpress/core-data. This concept of "raw" and this logic of running content = content.raw is very specific to only one kind of entity (posts). This whole setup is obviously confusing because mostly everyone in #34335 didn't even know what getRawEntityRecord is for 😅

The whole point of getRawEntityRecord, judging from getEditedEntityRecord, is that it transforms a REST API record into a record that is suitable for spreading edits onto.

export const getEditedEntityRecord = createSelector(
( state, kind, name, recordId ) => ( {
...getRawEntityRecord( state, kind, name, recordId ),
...getEntityRecordEdits( state, kind, name, recordId ),
} ),
( state ) => [ state.entities.data ]
);

So, I think:

  • getRawEntityRecord is not a great name. It should be something like getEntityRecordSuitableForApplyingEditsTo ...but not as verbose 😂 Obviously it's hard to rename a public selector at this point so maybe we can just document the purpose of this selector clearly in the doc comment.

  • This notion of a "raw" attribute should only exist in the post entity definition, not in any of the @wordpress/core-data selectors. So maybe we could have prepareEntityRecordForEdits (idk about the name) in the entity definition and the post entities provide an implementation which does the content = content.raw transformation.

    prepareEntityRecordForEdits( record ) {
        return { ...record, title: record.title.raw, content: record.content.raw };
    }

@adamziel
Copy link
Contributor Author

I am taking a deep dive here and will post a longer comment soon.

@adamziel
Copy link
Contributor Author

adamziel commented Aug 31, 2021

@noisysocks Good thinking! There are definitely some layers to peel here:

This PR already solves a real issue with widgets. I would like to get it merged, even if the selector would be called __unstableIsRawAttribute, and keep discussing a better overall structure.

Adding an API such as prepareEntityRecordForEdits would almost enable us to move the data shape juggling out of the core-data which is good. I'm saying almost, because of the custom reconciliation of API changes where [ 'title', 'excerpt', 'content' ] are all explicitly listed. I don't follow why the API data isn't prioritized over the "persistedRecord". Maybe we could just simplify that logic and be on our way to implementing prepareEntityRecordForEdits?

But if removing getRawEntityRecord is on the table because of how post-specific it is, then let's talk about going one step further. We could:

  1. Move most of the post-specific logic out of core-data
  2. Explore getting rid of data shape juggling entirely

Move most of the post-specific logic out of core-data

This comment says it all:

// Most of this autosave logic is very specific to posts.
// This is fine for now as it is the only supported autosave,
// but ideally this should all be handled in the back end,
// so the client just sends and receives objects.

Core-data hosts post-specific autosaving logic, data shape logic, API response reconciliation logic and so on. This could be a good opportunity to get more generic and move some of that logic to the server.

Explore getting rid of data shape juggling entirely

As for the raw/rendered logic, I wonder if we even have to evict it to another package. Maybe we don't need it at all?

The API returns data such as { id: 15, content: { raw: "abc", rendered: "<div>abc</div>" } } ("Full record").
getRawEntityRecord flattens that data to { id: 15, content: "abc" } ("Flattened record"), as it says, to "make rendering, comparisons, and joins with edits easier".

I wonder whether this "easier" part is still true. Maybe it would actually be easier to embrace the raw/rendered structure? Hiding it saves us a few characters here and there (.raw and { raw: value }) but it creates other problems. If we removed that logic:

  • We would have a single, consistent model of thinking about, processing, and storing entity records regardless of the specific entity kind (see "inconsistent storage" below).
  • We wouldn't need to implement entity record-specific logic such as the preparePostRecordForEdits mappers + API for registering them.
  • We could keep using the existing REST API which already supports both "flattened" and "full" format just fine.

Inconsistent storage

There is already some confusion even within core-data: Most of the time, we store the "Full record" format in the store, but on occasions we may store a "flattened record" instead, e.g. this action gets dispatched when autosaving a new post:

{
  type: 'RECEIVE_ITEMS',
  items: [
    {
      id: 144,
      status: 'draft',
      type: 'post',
      title: 'test',
      content: '<!-- wp:paragraph -->\n<p>first record</p>\n<!-- /wp:paragraph -->',
      // ...
    }
  ]
}

while this action gets dispatched after reloading the editor:

{
  type: 'RECEIVE_ITEMS',
  items: [
    {
      id: 144,
      status: 'draft',
      type: 'post',
      title: {
        raw: 'test',
        rendered: 'test'
      },
      content: {
        raw: '<!-- wp:paragraph -->\n<p>first record</p>\n<!-- /wp:paragraph -->',
        rendered: '\n<p>first record</p>\n',
        'protected': false,
        block_version: 1
      },
      // ...
    }
  ]
}

Also, I'm curious what @youknowriad thinks

@noisysocks
Copy link
Member

Love where your head is at! 👏

This PR already solves a real issue with widgets. I would like to get it merged, even if the selector would be called __unstableIsRawAttribute, and keep discussing a better overall structure.

Sounds good!

I wonder whether this "easier" part is still true. Maybe it would actually be easier to embrace the raw/rendered structure? Hiding it saves us a few characters here and there (.raw and { raw: value }) but it creates other problems.

I'm convinced!

It definitely seems that we've introduced a lot of complexity to the entire package in order to save a relatively trivial amount of complexity in getEditedEntityRecord (and the reducer?).

I suspect there may be a performance impact caused by switching from shallow object spread to deep object merge. Just need to check for performance regressions—no big deal.

@youknowriad
Copy link
Contributor

__unstableIsRawAttribute

Maybe we can just not export isRawAttribute.

I agree with you all that the dealing with these "raw" properties is not very well thought. It looks as if we try to adapt to the WP API to make edits work without much thoughts about it.

maybe an ideal scenario WP API is just an adapter for core-data to the WordPress API, and core-data's object structures have actual meaningful formats defined by the package itself (and potentially be inspired by WP's format).

So the questions to be asked:

  • What kind of format we want to expose to core-data's consumers?
  • How do we edit core-data's entities? editEntity({ title: { raw: "something" } }) or just. editEntity({ title: 'something' }) ?
  • What happens to the "rendered" property when the "raw" changes in the edited entity? should it return an error, match raw (we can't since it's generated server side), something else...

I'm happy for this PR to move forward to solve the widgets case, these "raw" properties sound indeed as a complex problem.

@adamziel
Copy link
Contributor Author

adamziel commented Sep 1, 2021

@youknowriad @noisysocks I turned isRawAttribute into an internal utility function unavailable outside of core-data so we should be good to merge this PR. Let's move the larger discussion into a new issue.

Mobile tests are acting up today on all PRs and commits so I think you can safely disregard them when reviewing.

As for the larger discussion, let's continue in #34449 and #34450.

@adamziel adamziel force-pushed the update/configurable-raw-fields branch from 37bad2e to 50a268e Compare September 2, 2021 10:38
…y similar, but is about including specific attributes regardless of their "raw-ness"
@adamziel adamziel force-pushed the update/configurable-raw-fields branch from f135792 to b28f032 Compare September 2, 2021 14:24
@adamziel adamziel merged commit 4dafc47 into trunk Sep 3, 2021
@adamziel adamziel deleted the update/configurable-raw-fields branch September 3, 2021 12:14
@github-actions github-actions bot added this to the Gutenberg 11.5 milestone Sep 3, 2021
@getsource getsource added the [Type] Enhancement A suggestion for improvement. label Sep 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Core data /packages/core-data [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants