Editor: Add Heartbeat post locking for Site Editor templates#11805
Editor: Add Heartbeat post locking for Site Editor templates#11805itzmekhokan wants to merge 6 commits into
Conversation
…n hook for templates. Adds wp_set_site_editor_post_lock_on_rest_prepare(), a small helper hooked to rest_prepare_wp_template and rest_prepare_wp_template_part that calls wp_set_post_lock() when a template is fetched with context=edit. The classic editor acquires its lock during edit-screen render in edit-form-advanced.php; Site Editor templates load over the REST API, so this fills the equivalent acquisition point for wp_template and wp_template_part. A new wp_apply_site_editor_post_lock filter lets real-time collaboration plugins (or future core RTC) opt the entire lock pipeline out with a single return false. No new Heartbeat handler is introduced; the existing wp_refresh_post_lock() in wp-admin/includes/misc.php is already post-type-agnostic and will be driven from the Site Editor in a follow-up commit. See #65126.
Resolves the current wp_template or wp_template_part post when site-editor.php
loads with either the legacy ?postId= argument or the canonical
?p=/{post_type}/{post_id} form, and adds a get-post-lock=1 handler that
mirrors the classic wp-admin/post.php take-over flow:
- Verifies the lock-post_{id} nonce via check_admin_referer().
- Respects wp_apply_site_editor_post_lock so RTC plugins keep their opt-out.
- Calls wp_set_post_lock() and redirects back to the editor without the
take-over query args.
Theme-supplied templates that have no numeric post ID yet are intentionally
skipped; locking only starts once a real WP_Post exists in the database.
See #65126.
Hooks _admin_notice_post_locked() to admin_footer when site-editor.php has resolved a wp_template or wp_template_part post and the wp_apply_site_editor_post_lock filter has not opted out. The existing notification-dialog markup from wp-admin/includes/post.php is reused as-is; the JS bridge introduced in a follow-up commit reveals it on a Heartbeat lock_error response and points the "Take over" button at the get-post-lock handler added in the previous commit. $GLOBALS['post'] is swapped to the resolved template post for the duration of the callback so _admin_notice_post_locked() resolves the correct WP_Post, mirroring how wp-admin/edit-form-advanced.php prepares the global before registering the same hook. See #65126.
Registers the new site-editor-post-lock script handle in wp_default_scripts()
next to its closest neighbour, post. The script depends on jquery, heartbeat,
wp-data, and wp-i18n.
On site-editor.php:
- Acquires the lock on initial render when no other user holds it, using
the wp_check_post_lock() then wp_set_post_lock() pattern from
wp-admin/post.php:191-192.
- Enqueues heartbeat and the new bridge script only when a template post
has been resolved and the wp_apply_site_editor_post_lock filter is
truthy.
- Localizes wpSiteEditorPostLockL10n with the post ID, post type, current
lock string, and a pre-built take-over URL that targets the canonical
?p=/{post_type}/{post_id} form so the round-trip resolution in the
take-over handler is unambiguous.
The matching JS bridge that consumes this data is added in the next commit.
See #65126.
The bridge is a thin classic-jQuery layer that connects the Site Editor to
the existing wp-refresh-post-lock Heartbeat workflow:
- Tracks the currently edited template entity via the core/edit-site data
store so client-side navigation between templates is reflected in the
Heartbeat payload.
- On heartbeat-send, populates data['wp-refresh-post-lock'] with the
active post ID and the most recent lock string. This is the same payload
shape wp-admin/js/post.js sends from the classic editor, so the server
handler wp_refresh_post_lock() needs no changes.
- On heartbeat-tick, reveals the server-rendered #post-lock-dialog on
lock_error and updates the cached lock token on new_lock.
- Rewrites the dialog's "Take over" anchor to the canonical
?p=/{post_type}/{post_id} take-over URL so the server resolver in
site-editor.php picks it up unambiguously.
Bails out immediately when wpSiteEditorPostLockL10n.enabled is false, which
is how the wp_apply_site_editor_post_lock filter propagates RTC opt-outs to
the client side.
See #65126.
Adds Tests_Admin_WpSetSiteEditorPostLockOnRestPrepare covering:
- Both rest_prepare_wp_template and rest_prepare_wp_template_part have the
new callback registered at priority 10.
- Edit-context responses acquire the lock for wp_template and
wp_template_part.
- View-context responses do not acquire any lock.
- wp_apply_site_editor_post_lock returning false skips acquisition.
- The filter receives the resolved WP_Post as its second argument.
- Edit-context responses refresh the lock for the current user when
another user had previously held it.
The function is invoked directly rather than going through a full REST
round-trip so the assertions are focused on the filter behaviour itself
(matching the style of the rest of tests/phpunit/tests/admin/).
See #65126.
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
Implements post locking for Site Editor template entities (
wp_template,wp_template_part) using the same Heartbeat flow as the classic editor:wp-refresh-post-lockon send, existingwp_refresh_post_lockhandling on the server, and the shared#post-lock-dialogmarkup from_admin_notice_post_locked().Trac ticket: https://core.trac.wordpress.org/ticket/65126
Approach
rest_prepare_wp_template/rest_prepare_wp_template_partwithcontext=edit, acquire a lock viawp_set_post_lock()when allowed.wp_apply_site_editor_post_lock(documented inwp-admin/includes/post.php) so real-time collaboration can disable locking consistently.get-post-lock+ nonce for take-over; enqueue Heartbeat +site-editor-post-lockand localize lock/takeover data.site-editor-post-lock.jstracks the active template viacore/edit-site, sends the same Heartbeat payload aswp-admin/js/post.js, and shows/refreshes the lock dialog on tick.