diff --git a/src/wp-includes/collaboration.php b/src/wp-includes/collaboration.php index 31f816c87b670..16392bc216e8b 100644 --- a/src/wp-includes/collaboration.php +++ b/src/wp-includes/collaboration.php @@ -34,3 +34,168 @@ function wp_collaboration_inject_setting() { 'after' ); } + +/** + * Modifies the post list UI and heartbeat responses for real-time collaboration. + * + * When RTC is enabled, hides the lock icon and user avatar, replaces the + * user-specific lock text with "Currently being edited", changes the "Edit" + * row action to "Join", and re-enables controls that core normally hides + * for locked posts (since collaborative editing is possible). + * + * @since 7.0.0 + * + * @access private + * + * @global string $pagenow The filename of the current screen. + */ +function wp_post_list_collaboration_ui() { + global $pagenow; + + if ( ! get_option( 'wp_enable_real_time_collaboration' ) ) { + return; + } + + // Heartbeat filter applies globally (not just edit.php) since the + // heartbeat API can fire from any admin page. + add_filter( 'heartbeat_received', 'wp_filter_locked_posts_heartbeat_for_rtc', 20 ); + + // CSS, JS, and row action overrides only apply on the posts list page. + if ( 'edit.php' !== $pagenow ) { + return; + } + + add_action( 'admin_head', 'wp_post_list_collaboration_styles' ); + add_filter( 'gettext', 'wp_filter_locked_post_text_for_rtc', 10, 3 ); + add_filter( 'post_row_actions', 'wp_post_list_collaboration_row_actions', 10, 2 ); + add_filter( 'page_row_actions', 'wp_post_list_collaboration_row_actions', 10, 2 ); +} + +/** + * Filters the heartbeat response to remove user-specific lock information + * when real-time collaboration is enabled. + * + * WordPress core's wp_check_locked_posts() runs at priority 10 and populates + * the 'wp-check-locked-posts' key with user name, avatar, and text. This + * filter runs at priority 20 to replace that data with a generic message, + * preventing user-specific lock info from reaching the client. + * + * @since 7.0.0 + * + * @access private + * + * @param array $response The heartbeat response. + * @return array Modified heartbeat response. + */ +function wp_filter_locked_posts_heartbeat_for_rtc( $response ) { + if ( ! empty( $response['wp-check-locked-posts'] ) ) { + foreach ( $response['wp-check-locked-posts'] as $key => $lock_data ) { + $response['wp-check-locked-posts'][ $key ]['text'] = __( 'Currently being edited' ); + unset( $response['wp-check-locked-posts'][ $key ]['avatar_src'] ); + unset( $response['wp-check-locked-posts'][ $key ]['avatar_src_2x'] ); + } + } + + return $response; +} + +/** + * Outputs CSS to hide the post lock icon and user avatar in the post list + * when real-time collaboration is enabled. + * + * Also re-enables checkboxes and row actions that WordPress core hides for + * locked posts, since collaborative editing means the post is not exclusively + * locked. + * + * @since 7.0.0 + * + * @access private + */ +function wp_post_list_collaboration_styles() { + ?> + + ID ); + if ( ! $lock_holder ) { + return $actions; + } + + if ( isset( $actions['edit'] ) ) { + $actions['edit'] = preg_replace( + '/>Edit' . esc_html__( 'Join' ) . '<', + $actions['edit'] + ); + } + + return $actions; +} diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index 24b808bf9cd17..2e94141c30a2e 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -800,6 +800,7 @@ // Collaboration. add_action( 'admin_init', 'wp_collaboration_inject_setting' ); +add_action( 'admin_init', 'wp_post_list_collaboration_ui' ); // Add ignoredHookedBlocks metadata attribute to the template and template part post types. add_filter( 'rest_pre_insert_wp_template', 'inject_ignored_hooked_blocks_metadata_attributes' );