From d7e09ca1861e3cf6aaf305883299176f6df0c603 Mon Sep 17 00:00:00 2001 From: Shekhar Wagh Date: Tue, 24 Mar 2026 23:30:37 +0530 Subject: [PATCH 1/7] Fix "Join" link staying stuck after post lock expires. When RTC is enabled, the "Join" action link on the post list was rendered based on lock state at page load. The heartbeat correctly cleared the lock status text and CSS class when the lock expired, but never updated the action link back to "Edit". This changes the approach to always render both "Edit" and "Join" as separate spans and toggle visibility with CSS using the `wp-collaborative-editing` class the heartbeat already manages. --- src/wp-admin/css/list-tables.css | 12 ++++++++ .../includes/class-wp-posts-list-table.php | 28 ++++++++++--------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/wp-admin/css/list-tables.css b/src/wp-admin/css/list-tables.css index 2e04dc5e8ee90..e2b7e30f1dd63 100644 --- a/src/wp-admin/css/list-tables.css +++ b/src/wp-admin/css/list-tables.css @@ -639,6 +639,18 @@ tr.wp-locked .row-actions .trash { display: block; } +.join-action-text { + display: none; +} + +.wp-collaborative-editing .edit-action-text { + display: none; +} + +.wp-collaborative-editing .join-action-text { + display: inline; +} + #menu-locations-wrap .widefat { width: 60%; } diff --git a/src/wp-admin/includes/class-wp-posts-list-table.php b/src/wp-admin/includes/class-wp-posts-list-table.php index 8cff2b87fad03..87148bdece631 100644 --- a/src/wp-admin/includes/class-wp-posts-list-table.php +++ b/src/wp-admin/includes/class-wp-posts-list-table.php @@ -1491,23 +1491,25 @@ protected function handle_row_actions( $item, $column_name, $primary ) { $title = _draft_or_post_title(); if ( $can_edit_post && 'trash' !== $post->post_status ) { - $is_rtc_locked = get_option( 'wp_collaboration_enabled' ) && wp_check_post_lock( $post->ID ); + $is_rtc_enabled = (bool) get_option( 'wp_collaboration_enabled' ); + + if ( $is_rtc_enabled ) { + $link_text = sprintf( + '%s%s', + __( 'Edit' ), + /* translators: Action link text for a singular post in the post list. Can be any type of post. */ + _x( 'Join', 'post list' ) + ); + } else { + $link_text = __( 'Edit' ); + } $actions['edit'] = sprintf( '%s', get_edit_post_link( $post->ID ), - esc_attr( - sprintf( - $is_rtc_locked - /* translators: %s: Post title. */ - ? __( 'Join editing “%s”', 'post list' ) - /* translators: %s: Post title. */ - : __( 'Edit “%s”' ), - $title - ) - ), - /* translators: Action link text for a singular post in the post list. Can be any type of post. */ - $is_rtc_locked ? _x( 'Join', 'post list' ) : __( 'Edit' ) + /* translators: %s: Post title. */ + esc_attr( sprintf( __( 'Edit “%s”' ), $title ) ), + $link_text ); /** From edbe78e4ca7e4bd7063f3cfdd4d55e3fc3926f94 Mon Sep 17 00:00:00 2001 From: Shekhar Wagh Date: Tue, 24 Mar 2026 23:31:32 +0530 Subject: [PATCH 2/7] Use screen-reader-text for post list action link accessibility. When RTC is enabled, the "Edit" and "Join" action links now include screen-reader-text spans with the post title instead of relying on aria-label. This keeps the accessible name in sync with the visible text as CSS toggles between "Edit" and "Join" on lock state changes. --- .../includes/class-wp-posts-list-table.php | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/wp-admin/includes/class-wp-posts-list-table.php b/src/wp-admin/includes/class-wp-posts-list-table.php index 87148bdece631..46c77a273b685 100644 --- a/src/wp-admin/includes/class-wp-posts-list-table.php +++ b/src/wp-admin/includes/class-wp-posts-list-table.php @@ -1495,23 +1495,31 @@ protected function handle_row_actions( $item, $column_name, $primary ) { if ( $is_rtc_enabled ) { $link_text = sprintf( - '%s%s', + '%s %s%s %s', __( 'Edit' ), + /* translators: %s: Post title. */ + sprintf( __( '“%s”' ), $title ), /* translators: Action link text for a singular post in the post list. Can be any type of post. */ - _x( 'Join', 'post list' ) + _x( 'Join', 'post list' ), + /* translators: %s: Post title. */ + sprintf( __( 'editing “%s”' ), $title ) + ); + + $actions['edit'] = sprintf( + '%s', + get_edit_post_link( $post->ID ), + $link_text ); } else { - $link_text = __( 'Edit' ); + $actions['edit'] = sprintf( + '%s', + get_edit_post_link( $post->ID ), + /* translators: %s: Post title. */ + esc_attr( sprintf( __( 'Edit “%s”' ), $title ) ), + __( 'Edit' ) + ); } - $actions['edit'] = sprintf( - '%s', - get_edit_post_link( $post->ID ), - /* translators: %s: Post title. */ - esc_attr( sprintf( __( 'Edit “%s”' ), $title ) ), - $link_text - ); - /** * Filters whether Quick Edit should be enabled for the given post type. * From 0fdeefff82ddcfbb01a091a2023f93ef93c4c8f6 Mon Sep 17 00:00:00 2001 From: Shekhar Wagh Date: Tue, 24 Mar 2026 23:38:38 +0530 Subject: [PATCH 3/7] Reuse existing translatable strings for action link accessibility. --- src/wp-admin/includes/class-wp-posts-list-table.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wp-admin/includes/class-wp-posts-list-table.php b/src/wp-admin/includes/class-wp-posts-list-table.php index 46c77a273b685..7867c62a0df1f 100644 --- a/src/wp-admin/includes/class-wp-posts-list-table.php +++ b/src/wp-admin/includes/class-wp-posts-list-table.php @@ -1495,14 +1495,14 @@ protected function handle_row_actions( $item, $column_name, $primary ) { if ( $is_rtc_enabled ) { $link_text = sprintf( - '%s %s%s %s', + '%s%s', __( 'Edit' ), /* translators: %s: Post title. */ - sprintf( __( '“%s”' ), $title ), + sprintf( __( 'Edit “%s”' ), $title ), /* translators: Action link text for a singular post in the post list. Can be any type of post. */ _x( 'Join', 'post list' ), /* translators: %s: Post title. */ - sprintf( __( 'editing “%s”' ), $title ) + sprintf( __( 'Join editing “%s”', 'post list' ), $title ) ); $actions['edit'] = sprintf( From 00351ba877e7383f9693d17fc75612e9f53ea59a Mon Sep 17 00:00:00 2001 From: Shekhar Wagh Date: Tue, 24 Mar 2026 23:50:00 +0530 Subject: [PATCH 4/7] Use string concatenation for action link markup. --- .../includes/class-wp-posts-list-table.php | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/wp-admin/includes/class-wp-posts-list-table.php b/src/wp-admin/includes/class-wp-posts-list-table.php index 7867c62a0df1f..1d014cb965626 100644 --- a/src/wp-admin/includes/class-wp-posts-list-table.php +++ b/src/wp-admin/includes/class-wp-posts-list-table.php @@ -1494,16 +1494,17 @@ protected function handle_row_actions( $item, $column_name, $primary ) { $is_rtc_enabled = (bool) get_option( 'wp_collaboration_enabled' ); if ( $is_rtc_enabled ) { - $link_text = sprintf( - '%s%s', - __( 'Edit' ), - /* translators: %s: Post title. */ - sprintf( __( 'Edit “%s”' ), $title ), - /* translators: Action link text for a singular post in the post list. Can be any type of post. */ - _x( 'Join', 'post list' ), - /* translators: %s: Post title. */ - sprintf( __( 'Join editing “%s”', 'post list' ), $title ) - ); + $link_text = ''; + $link_text .= ''; + /* translators: %s: Post title. */ + $link_text .= '' . sprintf( __( 'Edit “%s”' ), $title ) . ''; + $link_text .= ''; + $link_text .= ''; + /* translators: Action link text for a singular post in the post list. Can be any type of post. */ + $link_text .= ''; + /* translators: %s: Post title. */ + $link_text .= '' . sprintf( __( 'Join editing “%s”', 'post list' ), $title ) . ''; + $link_text .= ''; $actions['edit'] = sprintf( '%s', From ffe30e7eccee24130561063a1662cbdaa40ed8c6 Mon Sep 17 00:00:00 2001 From: Shekhar Wagh Date: Thu, 26 Mar 2026 19:39:15 +0530 Subject: [PATCH 5/7] Use sprintf with multi-line template for action link markup. --- .../includes/class-wp-posts-list-table.php | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/wp-admin/includes/class-wp-posts-list-table.php b/src/wp-admin/includes/class-wp-posts-list-table.php index 1d014cb965626..9d8d8e5e26e83 100644 --- a/src/wp-admin/includes/class-wp-posts-list-table.php +++ b/src/wp-admin/includes/class-wp-posts-list-table.php @@ -1494,22 +1494,25 @@ protected function handle_row_actions( $item, $column_name, $primary ) { $is_rtc_enabled = (bool) get_option( 'wp_collaboration_enabled' ); if ( $is_rtc_enabled ) { - $link_text = ''; - $link_text .= ''; - /* translators: %s: Post title. */ - $link_text .= '' . sprintf( __( 'Edit “%s”' ), $title ) . ''; - $link_text .= ''; - $link_text .= ''; - /* translators: Action link text for a singular post in the post list. Can be any type of post. */ - $link_text .= ''; - /* translators: %s: Post title. */ - $link_text .= '' . sprintf( __( 'Join editing “%s”', 'post list' ), $title ) . ''; - $link_text .= ''; - $actions['edit'] = sprintf( - '%s', + '' + . '' + . '' + . '%3$s' + . '' + . '' + . '' + . '%5$s' + . '' + . '', get_edit_post_link( $post->ID ), - $link_text + __( 'Edit' ), + /* translators: %s: Post title. */ + sprintf( __( 'Edit “%s”' ), $title ), + /* translators: Action link text for a singular post in the post list. Can be any type of post. */ + _x( 'Join', 'post list' ), + /* translators: %s: Post title. */ + sprintf( __( 'Join editing “%s”', 'post list' ), $title ) ); } else { $actions['edit'] = sprintf( From 39f1ece7332fbabcb856915fd6d664e0758a625c Mon Sep 17 00:00:00 2001 From: Shekhar Wagh Date: Thu, 26 Mar 2026 19:41:00 +0530 Subject: [PATCH 6/7] Add explanatory comment for action link toggle mechanism. --- src/wp-admin/includes/class-wp-posts-list-table.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/wp-admin/includes/class-wp-posts-list-table.php b/src/wp-admin/includes/class-wp-posts-list-table.php index 9d8d8e5e26e83..cd36a0cce5e1e 100644 --- a/src/wp-admin/includes/class-wp-posts-list-table.php +++ b/src/wp-admin/includes/class-wp-posts-list-table.php @@ -1493,6 +1493,12 @@ protected function handle_row_actions( $item, $column_name, $primary ) { if ( $can_edit_post && 'trash' !== $post->post_status ) { $is_rtc_enabled = (bool) get_option( 'wp_collaboration_enabled' ); + /* + * When RTC is enabled, both "Edit" and "Join" labels are rendered. + * The visible label is toggled by CSS based on the row's + * `wp-collaborative-editing` class, which is added or removed by + * inline-edit-post.js in response to heartbeat ticks. + */ if ( $is_rtc_enabled ) { $actions['edit'] = sprintf( '' From c260aa2b1d6342661491e905400f103d4c2641a8 Mon Sep 17 00:00:00 2001 From: Shekhar Wagh Date: Thu, 26 Mar 2026 19:43:53 +0530 Subject: [PATCH 7/7] Fix lint errors --- .../includes/class-wp-posts-list-table.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/wp-admin/includes/class-wp-posts-list-table.php b/src/wp-admin/includes/class-wp-posts-list-table.php index cd36a0cce5e1e..fc039a7573f19 100644 --- a/src/wp-admin/includes/class-wp-posts-list-table.php +++ b/src/wp-admin/includes/class-wp-posts-list-table.php @@ -1502,14 +1502,14 @@ protected function handle_row_actions( $item, $column_name, $primary ) { if ( $is_rtc_enabled ) { $actions['edit'] = sprintf( '' - . '' - . '' - . '%3$s' - . '' - . '' - . '' - . '%5$s' - . '' + . '' + . '' + . '%3$s' + . '' + . '' + . '' + . '%5$s' + . '' . '', get_edit_post_link( $post->ID ), __( 'Edit' ),