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 template revision button #45215

Merged
merged 17 commits into from
Feb 8, 2023
Merged

Add template revision button #45215

merged 17 commits into from
Feb 8, 2023

Conversation

georgeh
Copy link
Contributor

@georgeh georgeh commented Oct 21, 2022

What?

Adds a button to templates and template parts to get to the revision compare screen

Why?

Closes #44503

How?

This adds a button to the site editor for Templates and Template Parts that links to the revision viewer for that template.

It adds 2 new fields to the REST response for /wp/v2/template/{theme}//{part} and /wp/v2/template-part/{theme}//{part} routes: 'revision_count' and latest_revision_id. The Posts REST controller uses the _links section to expose these and links to routes for the Revisions REST controller. I chose to add these to the body because the Revisions REST routes assume numeric IDs with /revisions at the end, and the existing template routes receive everything in their namespace. Adding /revisions routes for templates and template-parts would require complex RegExes that could potentially lead to a DoS attack. However if someone can get the routes on the Revisions REST controller to work with Template IDs, I would be happy to add them.

Testing Instructions

  1. Open the Site Editor
  2. Edit a Template or Template Part
  3. Save to create a custom template
  4. Make another change and save again, to create a second custom template
  5. Confirm that the revision button appears in the Template sidebar and links to the revision viewer

Screenshots or screencast

revisions-style-update.mp4

@georgeh georgeh force-pushed the add/template-revision-button branch from 0f824f5 to be22d83 Compare October 24, 2022 18:49
@github-actions
Copy link

github-actions bot commented Oct 24, 2022

Size Change: +600 B (0%)

Total Size: 1.32 MB

Filename Size Change
build/edit-site/index.min.js 64.8 kB +585 B (+1%)
build/edit-site/style-rtl.css 9.7 kB +7 B (0%)
build/edit-site/style.css 9.7 kB +8 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 993 B
build/annotations/index.min.js 2.78 kB
build/api-fetch/index.min.js 2.27 kB
build/autop/index.min.js 2.15 kB
build/blob/index.min.js 483 B
build/block-directory/index.min.js 7.2 kB
build/block-directory/style-rtl.css 1.04 kB
build/block-directory/style.css 1.04 kB
build/block-editor/content-rtl.css 4.11 kB
build/block-editor/content.css 4.1 kB
build/block-editor/default-editor-styles-rtl.css 403 B
build/block-editor/default-editor-styles.css 403 B
build/block-editor/index.min.js 192 kB
build/block-editor/style-rtl.css 14.4 kB
build/block-editor/style.css 14.4 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 90 B
build/block-library/blocks/archives/style.css 90 B
build/block-library/blocks/audio/editor-rtl.css 150 B
build/block-library/blocks/audio/editor.css 150 B
build/block-library/blocks/audio/style-rtl.css 122 B
build/block-library/blocks/audio/style.css 122 B
build/block-library/blocks/audio/theme-rtl.css 138 B
build/block-library/blocks/audio/theme.css 138 B
build/block-library/blocks/avatar/editor-rtl.css 116 B
build/block-library/blocks/avatar/editor.css 116 B
build/block-library/blocks/avatar/style-rtl.css 91 B
build/block-library/blocks/avatar/style.css 91 B
build/block-library/blocks/block/editor-rtl.css 305 B
build/block-library/blocks/block/editor.css 305 B
build/block-library/blocks/button/editor-rtl.css 587 B
build/block-library/blocks/button/editor.css 587 B
build/block-library/blocks/button/style-rtl.css 628 B
build/block-library/blocks/button/style.css 627 B
build/block-library/blocks/buttons/editor-rtl.css 337 B
build/block-library/blocks/buttons/editor.css 337 B
build/block-library/blocks/buttons/style-rtl.css 332 B
build/block-library/blocks/buttons/style.css 332 B
build/block-library/blocks/calendar/style-rtl.css 239 B
build/block-library/blocks/calendar/style.css 239 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 100 B
build/block-library/blocks/categories/style.css 100 B
build/block-library/blocks/code/editor-rtl.css 53 B
build/block-library/blocks/code/editor.css 53 B
build/block-library/blocks/code/style-rtl.css 121 B
build/block-library/blocks/code/style.css 121 B
build/block-library/blocks/code/theme-rtl.css 124 B
build/block-library/blocks/code/theme.css 124 B
build/block-library/blocks/columns/editor-rtl.css 108 B
build/block-library/blocks/columns/editor.css 108 B
build/block-library/blocks/columns/style-rtl.css 406 B
build/block-library/blocks/columns/style.css 406 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 125 B
build/block-library/blocks/comment-author-avatar/editor.css 125 B
build/block-library/blocks/comment-content/style-rtl.css 92 B
build/block-library/blocks/comment-content/style.css 92 B
build/block-library/blocks/comment-template/style-rtl.css 199 B
build/block-library/blocks/comment-template/style.css 198 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 123 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 222 B
build/block-library/blocks/comments-pagination/editor.css 209 B
build/block-library/blocks/comments-pagination/style-rtl.css 235 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/comments-title/editor-rtl.css 75 B
build/block-library/blocks/comments-title/editor.css 75 B
build/block-library/blocks/comments/editor-rtl.css 840 B
build/block-library/blocks/comments/editor.css 839 B
build/block-library/blocks/comments/style-rtl.css 637 B
build/block-library/blocks/comments/style.css 636 B
build/block-library/blocks/cover/editor-rtl.css 612 B
build/block-library/blocks/cover/editor.css 613 B
build/block-library/blocks/cover/style-rtl.css 1.57 kB
build/block-library/blocks/cover/style.css 1.56 kB
build/block-library/blocks/embed/editor-rtl.css 293 B
build/block-library/blocks/embed/editor.css 293 B
build/block-library/blocks/embed/style-rtl.css 410 B
build/block-library/blocks/embed/style.css 410 B
build/block-library/blocks/embed/theme-rtl.css 138 B
build/block-library/blocks/embed/theme.css 138 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 265 B
build/block-library/blocks/file/style.css 265 B
build/block-library/blocks/file/view.min.js 353 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/editor-rtl.css 984 B
build/block-library/blocks/gallery/editor.css 988 B
build/block-library/blocks/gallery/style-rtl.css 1.55 kB
build/block-library/blocks/gallery/style.css 1.55 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 654 B
build/block-library/blocks/group/editor.css 654 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 78 B
build/block-library/blocks/group/theme.css 78 B
build/block-library/blocks/heading/style-rtl.css 76 B
build/block-library/blocks/heading/style.css 76 B
build/block-library/blocks/html/editor-rtl.css 332 B
build/block-library/blocks/html/editor.css 333 B
build/block-library/blocks/image/editor-rtl.css 830 B
build/block-library/blocks/image/editor.css 829 B
build/block-library/blocks/image/style-rtl.css 652 B
build/block-library/blocks/image/style.css 652 B
build/block-library/blocks/image/theme-rtl.css 137 B
build/block-library/blocks/image/theme.css 137 B
build/block-library/blocks/latest-comments/style-rtl.css 298 B
build/block-library/blocks/latest-comments/style.css 298 B
build/block-library/blocks/latest-posts/editor-rtl.css 213 B
build/block-library/blocks/latest-posts/editor.css 212 B
build/block-library/blocks/latest-posts/style-rtl.css 478 B
build/block-library/blocks/latest-posts/style.css 478 B
build/block-library/blocks/list/style-rtl.css 88 B
build/block-library/blocks/list/style.css 88 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 507 B
build/block-library/blocks/media-text/style.css 505 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 716 B
build/block-library/blocks/navigation-link/editor.css 715 B
build/block-library/blocks/navigation-link/style-rtl.css 115 B
build/block-library/blocks/navigation-link/style.css 115 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 299 B
build/block-library/blocks/navigation-submenu/editor.css 299 B
build/block-library/blocks/navigation/editor-rtl.css 2.13 kB
build/block-library/blocks/navigation/editor.css 2.14 kB
build/block-library/blocks/navigation/style-rtl.css 2.22 kB
build/block-library/blocks/navigation/style.css 2.2 kB
build/block-library/blocks/navigation/view-modal.min.js 2.81 kB
build/block-library/blocks/navigation/view.min.js 447 B
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 376 B
build/block-library/blocks/page-list/editor.css 376 B
build/block-library/blocks/page-list/style-rtl.css 175 B
build/block-library/blocks/page-list/style.css 175 B
build/block-library/blocks/paragraph/editor-rtl.css 174 B
build/block-library/blocks/paragraph/editor.css 174 B
build/block-library/blocks/paragraph/style-rtl.css 279 B
build/block-library/blocks/paragraph/style.css 281 B
build/block-library/blocks/post-author/style-rtl.css 175 B
build/block-library/blocks/post-author/style.css 176 B
build/block-library/blocks/post-comments-form/editor-rtl.css 96 B
build/block-library/blocks/post-comments-form/editor.css 96 B
build/block-library/blocks/post-comments-form/style-rtl.css 501 B
build/block-library/blocks/post-comments-form/style.css 501 B
build/block-library/blocks/post-date/style-rtl.css 61 B
build/block-library/blocks/post-date/style.css 61 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 134 B
build/block-library/blocks/post-excerpt/style.css 134 B
build/block-library/blocks/post-featured-image/editor-rtl.css 586 B
build/block-library/blocks/post-featured-image/editor.css 584 B
build/block-library/blocks/post-featured-image/style-rtl.css 318 B
build/block-library/blocks/post-featured-image/style.css 318 B
build/block-library/blocks/post-navigation-link/style-rtl.css 153 B
build/block-library/blocks/post-navigation-link/style.css 153 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 282 B
build/block-library/blocks/post-template/style.css 282 B
build/block-library/blocks/post-terms/style-rtl.css 96 B
build/block-library/blocks/post-terms/style.css 96 B
build/block-library/blocks/post-title/style-rtl.css 100 B
build/block-library/blocks/post-title/style.css 100 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 135 B
build/block-library/blocks/pullquote/editor.css 135 B
build/block-library/blocks/pullquote/style-rtl.css 326 B
build/block-library/blocks/pullquote/style.css 325 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 221 B
build/block-library/blocks/query-pagination/editor.css 211 B
build/block-library/blocks/query-pagination/style-rtl.css 288 B
build/block-library/blocks/query-pagination/style.css 284 B
build/block-library/blocks/query-title/style-rtl.css 63 B
build/block-library/blocks/query-title/style.css 63 B
build/block-library/blocks/query/editor-rtl.css 458 B
build/block-library/blocks/query/editor.css 457 B
build/block-library/blocks/quote/style-rtl.css 213 B
build/block-library/blocks/quote/style.css 213 B
build/block-library/blocks/quote/theme-rtl.css 223 B
build/block-library/blocks/quote/theme.css 226 B
build/block-library/blocks/read-more/style-rtl.css 132 B
build/block-library/blocks/read-more/style.css 132 B
build/block-library/blocks/rss/editor-rtl.css 149 B
build/block-library/blocks/rss/editor.css 149 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 409 B
build/block-library/blocks/search/style.css 406 B
build/block-library/blocks/search/theme-rtl.css 114 B
build/block-library/blocks/search/theme.css 114 B
build/block-library/blocks/separator/editor-rtl.css 146 B
build/block-library/blocks/separator/editor.css 146 B
build/block-library/blocks/separator/style-rtl.css 234 B
build/block-library/blocks/separator/style.css 234 B
build/block-library/blocks/separator/theme-rtl.css 194 B
build/block-library/blocks/separator/theme.css 194 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 490 B
build/block-library/blocks/site-logo/editor.css 490 B
build/block-library/blocks/site-logo/style-rtl.css 203 B
build/block-library/blocks/site-logo/style.css 203 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 116 B
build/block-library/blocks/site-title/editor.css 116 B
build/block-library/blocks/site-title/style-rtl.css 57 B
build/block-library/blocks/site-title/style.css 57 B
build/block-library/blocks/social-link/editor-rtl.css 184 B
build/block-library/blocks/social-link/editor.css 184 B
build/block-library/blocks/social-links/editor-rtl.css 674 B
build/block-library/blocks/social-links/editor.css 673 B
build/block-library/blocks/social-links/style-rtl.css 1.4 kB
build/block-library/blocks/social-links/style.css 1.39 kB
build/block-library/blocks/spacer/editor-rtl.css 332 B
build/block-library/blocks/spacer/editor.css 332 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 433 B
build/block-library/blocks/table/editor.css 433 B
build/block-library/blocks/table/style-rtl.css 651 B
build/block-library/blocks/table/style.css 650 B
build/block-library/blocks/table/theme-rtl.css 157 B
build/block-library/blocks/table/theme.css 157 B
build/block-library/blocks/tag-cloud/style-rtl.css 251 B
build/block-library/blocks/tag-cloud/style.css 253 B
build/block-library/blocks/template-part/editor-rtl.css 404 B
build/block-library/blocks/template-part/editor.css 404 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/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 99 B
build/block-library/blocks/verse/style.css 99 B
build/block-library/blocks/video/editor-rtl.css 552 B
build/block-library/blocks/video/editor.css 555 B
build/block-library/blocks/video/style-rtl.css 179 B
build/block-library/blocks/video/style.css 179 B
build/block-library/blocks/video/theme-rtl.css 139 B
build/block-library/blocks/video/theme.css 139 B
build/block-library/classic-rtl.css 179 B
build/block-library/classic.css 179 B
build/block-library/common-rtl.css 1.11 kB
build/block-library/common.css 1.11 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/editor-rtl.css 11.6 kB
build/block-library/editor.css 11.6 kB
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/index.min.js 199 kB
build/block-library/reset-rtl.css 478 B
build/block-library/reset.css 478 B
build/block-library/style-rtl.css 12.6 kB
build/block-library/style.css 12.6 kB
build/block-library/theme-rtl.css 698 B
build/block-library/theme.css 703 B
build/block-serialization-default-parser/index.min.js 1.13 kB
build/block-serialization-spec-parser/index.min.js 2.83 kB
build/blocks/index.min.js 51 kB
build/components/index.min.js 204 kB
build/components/style-rtl.css 11.6 kB
build/components/style.css 11.7 kB
build/compose/index.min.js 12.3 kB
build/core-data/index.min.js 15.9 kB
build/customize-widgets/index.min.js 11.8 kB
build/customize-widgets/style-rtl.css 1.41 kB
build/customize-widgets/style.css 1.41 kB
build/data-controls/index.min.js 663 B
build/data/index.min.js 8.57 kB
build/date/index.min.js 32.1 kB
build/deprecated/index.min.js 518 B
build/dom-ready/index.min.js 336 B
build/dom/index.min.js 4.71 kB
build/edit-post/classic-rtl.css 571 B
build/edit-post/classic.css 571 B
build/edit-post/index.min.js 34.5 kB
build/edit-post/style-rtl.css 7.5 kB
build/edit-post/style.css 7.5 kB
build/edit-widgets/index.min.js 16.9 kB
build/edit-widgets/style-rtl.css 4.52 kB
build/edit-widgets/style.css 4.52 kB
build/editor/index.min.js 45.4 kB
build/editor/style-rtl.css 3.54 kB
build/editor/style.css 3.53 kB
build/element/index.min.js 4.93 kB
build/escape-html/index.min.js 548 B
build/experiments/index.min.js 938 B
build/format-library/index.min.js 7.26 kB
build/format-library/style-rtl.css 557 B
build/format-library/style.css 556 B
build/hooks/index.min.js 1.66 kB
build/html-entities/index.min.js 454 B
build/i18n/index.min.js 3.79 kB
build/is-shallow-equal/index.min.js 535 B
build/keyboard-shortcuts/index.min.js 1.79 kB
build/keycodes/index.min.js 1.92 kB
build/list-reusable-blocks/index.min.js 2.14 kB
build/list-reusable-blocks/style-rtl.css 865 B
build/list-reusable-blocks/style.css 865 B
build/media-utils/index.min.js 2.99 kB
build/notices/index.min.js 977 B
build/plugins/index.min.js 1.95 kB
build/preferences-persistence/index.min.js 2.23 kB
build/preferences/index.min.js 1.35 kB
build/primitives/index.min.js 960 B
build/priority-queue/index.min.js 1.52 kB
build/react-i18n/index.min.js 702 B
build/react-refresh-entry/index.min.js 8.44 kB
build/react-refresh-runtime/index.min.js 7.31 kB
build/redux-routine/index.min.js 2.75 kB
build/reusable-blocks/index.min.js 2.26 kB
build/reusable-blocks/style-rtl.css 265 B
build/reusable-blocks/style.css 265 B
build/rich-text/index.min.js 10.8 kB
build/server-side-render/index.min.js 2.09 kB
build/shortcode/index.min.js 1.52 kB
build/style-engine/index.min.js 1.53 kB
build/token-list/index.min.js 650 B
build/url/index.min.js 3.69 kB
build/vendors/inert-polyfill.min.js 2.48 kB
build/vendors/react-dom.min.js 41.8 kB
build/vendors/react.min.js 4.02 kB
build/viewport/index.min.js 1.09 kB
build/warning/index.min.js 280 B
build/widgets/index.min.js 7.31 kB
build/widgets/style-rtl.css 1.18 kB
build/widgets/style.css 1.18 kB
build/wordcount/index.min.js 1.06 kB

compressed-size-action

@georgeh
Copy link
Contributor Author

georgeh commented Oct 25, 2022

Thinking more about the REST routes in this, I think I can use the revisions REST controller, but only add the links when there are 2 or more custom versions of a template.

As a follow-up it would also be good to let the revision viewer load theme templates from the filesystem as a kind of revision 0

@georgeh
Copy link
Contributor Author

georgeh commented Oct 25, 2022

This button could probably use some design help too:

image

@georgeh georgeh added the Needs Design Needs design efforts. label Oct 25, 2022
@georgeh
Copy link
Contributor Author

georgeh commented Oct 25, 2022

Thinking more about the REST routes in this, I think I can use the revisions REST controller, but only add the links when there are 2 or more custom versions of a template.

No, it won't work with the routes as they are currently set up. I've learned this twice now so I'm writing it down here for the next time I attempt this.

WP_REST_Templates_Controller registers a route for

// The route.
sprintf(
	'/%s/(?P<id>%s%s)',
	$this->rest_base,
	// Matches theme's directory: `/themes/<subdirectory>/<theme>/` or `/themes/<theme>/`.
	// Excludes invalid directory name characters: `/:<>*?"|`.
	'([^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)',
	// Matches the template name.
	'[\/\w-]+'
)

which expands to something like /wp/v2/templates/twentytwentytwo//footer

WP_REST_Revisions_Controller registers a route for every post type that supports revisions for

// $this->rest_base = 'revisions'
'/' . $this->parent_base . '/(?P<parent>[\d]+)/' . $this->rest_base;
// ... and ....
'/' . $this->parent_base . '/(?P<parent>[\d]+)/' . $this->rest_base . '/(?P<id>[\d]+)',

which expands to something like /wp/v2/templates/123/revisions and /wp/v2/templates/123/revisions/456

Excluding routes that end in /revisions[/\d]* is difficult and has the potential to introduce a ReDoS vulnerability. Still, if someone has suggestions on how to make the routes on both of those classes compatible, I would love to use the same response format as posts.

Comment on lines 35 to 39

if ( rest_is_field_included( 'revision_count', $fields ) ) {
$data['revision_count'] = (int) $revisions['count'];
}

if ( rest_is_field_included( 'latest_revision_id', $fields ) ) {
$data['latest_revision_id'] = (int) $revisions['latest_id'];
}
Copy link
Member

Choose a reason for hiding this comment

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

Instead of adding the data like this, please add like other endpoints, like this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The other endpoints provide links to REST routes that provide revision information, which I inferred as the reason that they are in the _links section in the response. I've noted in the How section of my description and this comment that the REST routes for revisions are not compatible with the routes for templates, because template IDs are non-numeric and use slashes internally.

I chose not to put these in the _links section because of the difficulty getting the Revision REST controller routes to respond. Are you saying you'd still like to have these data in _links without URLs for other REST responses?

Copy link
Member

Choose a reason for hiding this comment

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

No, I would like to the revisions endpoints working.

Copy link
Member

Choose a reason for hiding this comment

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

There is no such idea of revisioned templates for file based templates. There will only ever work with ones stored in the database. As we check to see if there are WordPress id based templates. So this is really an issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What do you think about having a different URL structure for templates? Something like /wp/v2/revisions/template[_part]s/123/456? It seems like the revision controller could have a special case for the route for those post types to avoid conflicts.

Copy link
Member

Choose a reason for hiding this comment

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

There is already an existing endpoint that looks like this.

/wp/v2/templates/(?P<parent>[\\d]+)/revisions":

and

/wp/v2/templates/(?P<parent>[\\d]+)/revisions/(?P<id>[\\d]+)":

There is no need for a different endpoint / structure.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Those endpoints do exist, however the routes in WP_REST_Templates_Controller also match those URLs and so WP_REST_Revisions_Controller never sees requests for them. You can confirm this by making a request to those endpoints and seeing that the response is from the Templates controller: the error code is rest_template_not_found.

Here is the best solution I've been able to come up with to route /wp/v2/template-parts/18/revisions and /wp/v2/template-parts/123/revisions/456 to WP_REST_Revisions_Controller:

First, change the route for WP_REST_Templates_Controller::get_item to add (?<!revisions) at the end. This prevents the controller from matching requests for /wp/v2/template-parts/123/revisions. This fixes requests for /wp/v2/template-parts/18/revisions.

This regex will still attempt to match /wp/v2/template-parts/123/revisions/456 because that is indistinguishable from /wp/v2/template-parts/themedir/twentytwentythree/footer (we need to allow for theme dirs, and we have to accept a single slash between theme name and part). (?<!revisions) is a negative lookahead, and they must be fixed width so we can't add \d+ in there to match one-or-more digits.

We may be able to update the regex for the template routes to require at least one non-numeric character in theme and template names if we can guarantee no one is going to name a theme 2023 or a template part 1. If not, I put together this pseudocode that feels incredibly hacky, and not a solution I like, but it should allow us to have WP_REST_Templates_Controller intercept requests for /wp/v2/template-parts/123/revisions/456:

function wp_api_reroute_template_revision_requests( $dispatch_result, $request, $route, $handler ) {
	// Check if the request is for a template revision.
	if ( is_a( $handler['callback'][0], 'WP_REST_Templates_Controller', true ) ) {
		$post_type        = $handler['callback'][0]->getPostType();
		$post_type_object = get_post_type_object( $post_type );
		$post_base        = ! empty( $post_type_object->rest_base ) ? $post_type_object->rest_base : $post_type_object->name;

		// See if we have a request for get_item()
		if ( preg_match( '@/' . $post_base . '/(?P<parent>[\d]+)/revisions/(?P<id>[\d]+)$@',
		                 $request->get_route(),
						 $get_items_matches ) ) {
			$revision_controller = new WP_REST_Revisions_Controller( $post_type );
			return $revision_controller->get_item( $get_items_matches );
		}
	}
}
add_filter( 'rest_dispatch_request', 'wp_api_reroute_template_revision_requests', 10, 4 );

This feels very brittle and indirect, and not a particularly elegant solution, but it is a solution nonetheless.

@spacedmonkey I would appreciate your thoughts on the proposed solutions (don't link to revisions, change the URL structure for template revisions, intercept requests for revisions in a filter), and if you have any other ideas on ensuring that the Revision controller gets the requests instead of the Template controller. Thanks again for your work on this.

Copy link
Member

@spacedmonkey spacedmonkey left a comment

Choose a reason for hiding this comment

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

Good start but changes required.

@georgeh
Copy link
Contributor Author

georgeh commented Oct 26, 2022

Working on the revisions, thanks for the review @spacedmonkey. Also I opened #45290 as a possible follow-up to make template revisions clearer

@priethor
Copy link
Contributor

Does this PR provide an alternative to WordPress/wordpress-develop#3476, or does it depend on it?

@georgeh
Copy link
Contributor Author

georgeh commented Oct 26, 2022

Does this PR provide an alternative to WordPress/wordpress-develop#3476, or does it depend on it?

@priethor That was an earlier attempt on adding to the REST API and this is a better place for that change. I'll close that and we can merge the changes to core using the usual Gutenberg merge process.

@spacedmonkey
Copy link
Member

Thinking more about the REST routes in this, I think I can use the revisions REST controller, but only add the links when there are 2 or more custom versions of a template.

No, it won't work with the routes as they are currently set up. I've learned this twice now so I'm writing it down here for the next time I attempt this.

WP_REST_Templates_Controller registers a route for

// The route.
sprintf(
	'/%s/(?P<id>%s%s)',
	$this->rest_base,
	// Matches theme's directory: `/themes/<subdirectory>/<theme>/` or `/themes/<theme>/`.
	// Excludes invalid directory name characters: `/:<>*?"|`.
	'([^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)',
	// Matches the template name.
	'[\/\w-]+'
)

which expands to something like /wp/v2/templates/twentytwentytwo//footer

WP_REST_Revisions_Controller registers a route for every post type that supports revisions for

// $this->rest_base = 'revisions'
'/' . $this->parent_base . '/(?P<parent>[\d]+)/' . $this->rest_base;
// ... and ....
'/' . $this->parent_base . '/(?P<parent>[\d]+)/' . $this->rest_base . '/(?P<id>[\d]+)',

which expands to something like /wp/v2/templates/123/revisions and /wp/v2/templates/123/revisions/456

Excluding routes that end in /revisions[/\d]* is difficult and has the potential to introduce a ReDoS vulnerability. Still, if someone has suggestions on how to make the routes on both of those classes compatible, I would love to use the same response format as posts.

I have reported this issue upstream here - https://core.trac.wordpress.org/ticket/56922. It will hopefully be fixed in WordPress 6.2.

@georgeh
Copy link
Contributor Author

georgeh commented Oct 27, 2022

I have reported this issue upstream here - https://core.trac.wordpress.org/ticket/56922. It will hopefully be fixed in WordPress 6.2.

Thanks @spacedmonkey - I'll get this PR ready for when that gets fixed and hopefully we can backport the fix to this as well.

@spacedmonkey
Copy link
Member

@georgeh I have pushed some changes to this PR, with a fix. Let me know what you think.

@georgeh
Copy link
Contributor Author

georgeh commented Oct 27, 2022

@spacedmonkey thanks, that's about what I was coming up with so it lgtm. How do we feel about merging this when the _links section points to URLs that don't work yet?

@spacedmonkey
Copy link
Member

@spacedmonkey thanks, that's about what I was coming up with so it lgtm. How do we feel about merging this when the _links section points to URLs that don't work yet?

We can fix the issue in core or guternberg PR.

@spacedmonkey
Copy link
Member

This is looking good. Let's ensure that unit tests / linting are passing. Then we can merge.

@ntsekouras ntsekouras added Backport to WP 6.7 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta and removed Backport to WP 6.7 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta labels Feb 13, 2023
@DaisyOlsen DaisyOlsen added [Type] Enhancement A suggestion for improvement. [Feature] Inspector Controls The interface showing block settings and the controls available for each block and removed Needs Design Feedback Needs general design feedback. Needs Design Needs design efforts. Needs Technical Feedback Needs testing from a developer perspective. labels Feb 14, 2023
@ntsekouras ntsekouras added Backport to WP 6.7 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta and removed Backport to WP 6.7 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta labels Feb 20, 2023
@draganescu
Copy link
Contributor

This cannot be in 6.2 because once we land in the revision UI the links to take us back don't work and fixing that is not trivial.

@draganescu draganescu removed the Backport to WP 6.7 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta label Feb 20, 2023
@femkreations femkreations added the Needs User Documentation Needs new user documentation label Jun 14, 2023
@oandregal
Copy link
Member

I was looking at backporting #48078 which essentially merges the Gutenberg_REST_Template_Revision_Count controller this PR introduced into the existing Gutenberg_REST_Templates_Controller_6_3.

I then went to the trac ticket for this PR and saw it was blocked by upstream changes, see at https://core.trac.wordpress.org/ticket/57704#comment:4 It couldn't be backported in 6.3 and, as far as my understanding goes, it cannot be backported in 6.3 either.

As for next steps, fixing the upstream issue would be ideal, and that's the main next step.

I also wonder how we should mark this code as "blocked by upstream". If the upstream issue is not fixed in time for the 6.4 release, I worry that we may unintentionally remove the revisions related code that lives in lib/compat/6.3. How can make sure that's obvious, so the people involved in the release have the proper information?

  • One idea would be to move the revisions related code to a lib/compat/6.4. However, that's pushing the problem to the future, hoping upstream would fix it.
  • Alternatively, we could move it to lib/experimental and add the proper comments and link to the trac ticket. Code in experimental requires "human intervention", so it's less prone to be unintentionally removed.

How does this sound?

@ramonjd
Copy link
Member

ramonjd commented Jun 21, 2023

Alternatively, we could move it to lib/experimental and add the proper comments and link to the trac ticket. Code in experimental requires "human intervention", so it's less prone to be unintentionally removed.

@oandregal

Moving files to /experimental is what was decided for the Behaviors API:

To me that makes sense. Then it can be relocated again to compat/x.y later when the upstream is fixed.

I can remove the corresponding PR mentions from the 6.3 backport issue if you think we're not going to include it in 6.3?

To confirm, this PR and #48078 are to be scratched for a future release...

@ramonjd
Copy link
Member

ramonjd commented Jun 22, 2023

Here's a PR to move the revisions button API stuff back to /experimental

#51774

ramonjd added a commit that referenced this pull request Jun 25, 2023
ramonjd added a commit that referenced this pull request Jun 25, 2023
sethrubenstein pushed a commit to pewresearch/gutenberg that referenced this pull request Jul 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Inspector Controls The interface showing block settings and the controls available for each block Needs User Documentation Needs new user documentation [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Template inspector: Surface revisions panel