From 0b6e1b7d5f5f01c8c99f3fb31d8359ddf53c77e7 Mon Sep 17 00:00:00 2001 From: Poli Gilad <83961704+poligilad-auto@users.noreply.github.com> Date: Wed, 24 Jun 2026 15:00:51 +0200 Subject: [PATCH 1/2] Editor: Use radio buttons for Classic Editor status --- src/js/_enqueues/admin/post.js | 114 ++++++++++++++---- src/wp-admin/css/edit.css | 7 ++ src/wp-admin/includes/meta-boxes.php | 34 +++--- .../phpunit/tests/admin/includesMetaBoxes.php | 48 ++++++++ 4 files changed, 165 insertions(+), 38 deletions(-) create mode 100644 tests/phpunit/tests/admin/includesMetaBoxes.php diff --git a/src/js/_enqueues/admin/post.js b/src/js/_enqueues/admin/post.js index d50fe6007d33b..9b8d7580170ec 100644 --- a/src/js/_enqueues/admin/post.js +++ b/src/js/_enqueues/admin/post.js @@ -303,6 +303,8 @@ window.wp = window.wp || {}; */ jQuery( function($) { var stamp, visibility, $submitButtons, updateVisibility, updateText, + getPostStatusValue, setPostStatusValue, getPostStatusLabel, + ensurePublishPostStatus, removePublishPostStatus, $textarea = $('#content'), $document = $(document), postId = $('#post_ID').val() || 0, @@ -721,6 +723,81 @@ jQuery( function($) { stamp = $('#timestamp').html(); visibility = $('#post-visibility-display').html(); + /** + * Get the selected post status value. + * + * @ignore + * + * @return {string} Selected post status value. + */ + getPostStatusValue = function() { + return $postStatusSelect.find('input[name="post_status"]:checked').val(); + }; + + /** + * Set the selected post status value. + * + * @ignore + * + * @param {string} value Post status value. + * + * @return {void} + */ + setPostStatusValue = function( value ) { + $postStatusSelect.find('input[name="post_status"][value="' + value + '"]').prop('checked', true); + }; + + /** + * Get the selected post status label. + * + * @ignore + * + * @return {string} Selected post status label. + */ + getPostStatusLabel = function() { + var $checked = $postStatusSelect.find('input[name="post_status"]:checked'); + + if ( ! $checked.length ) { + return ''; + } + + return $postStatusSelect.find('label[for="' + $checked.attr('id') + '"]').text(); + }; + + /** + * Ensure a publish status radio exists and is selected. + * + * @ignore + * + * @param {string} label Publish status label. + * + * @return {void} + */ + ensurePublishPostStatus = function( label ) { + var $publishStatus = $postStatusSelect.find('input[name="post_status"][value="publish"]'); + + if ( ! $publishStatus.length ) { + $postStatusSelect.find('.post-status-options').prepend( + '
' + ); + $publishStatus = $postStatusSelect.find('input[name="post_status"][value="publish"]'); + } + + $publishStatus.siblings('label').text( label ); + setPostStatusValue('publish'); + }; + + /** + * Remove a dynamically added publish status radio. + * + * @ignore + * + * @return {void} + */ + removePublishPostStatus = function() { + $postStatusSelect.find('input[name="post_status"][value="publish"]').closest('.post-status-option').remove(); + }; + /** * When the visibility of a post changes sub-options should be shown or hidden. * @@ -757,8 +834,8 @@ jQuery( function($) { if ( ! $timestampdiv.length ) return true; - var attemptedDate, originalDate, currentDate, publishOn, postStatus = $('#post_status'), - optPublish = $('option[value="publish"]', postStatus), aa = $('#aa').val(), + var attemptedDate, originalDate, currentDate, publishOn, postStatusValue, + aa = $('#aa').val(), mm = $('#mm').val(), jj = $('#jj').val(), hh = $('#hh').val(), mn = $('#mn').val(); attemptedDate = new Date( aa, mm - 1, jj, hh, mn ); @@ -823,41 +900,34 @@ jQuery( function($) { // Add "privately published" to post status when applies. if ( $postVisibilitySelect.find('input:radio:checked').val() == 'private' ) { $('#publish').val( __( 'Update' ) ); - if ( 0 === optPublish.length ) { - postStatus.append(''); - } else { - optPublish.html( __( 'Privately Published' ) ); - } - $('option[value="publish"]', postStatus).prop('selected', true); + ensurePublishPostStatus( __( 'Privately Published' ) ); $('#misc-publishing-actions .edit-post-status').hide(); } else { - if ( $('#original_post_status').val() == 'future' || $('#original_post_status').val() == 'draft' ) { - if ( optPublish.length ) { - optPublish.remove(); - postStatus.val($('#hidden_post_status').val()); + if ( $('#original_post_status').val() == 'future' || $('#original_post_status').val() == 'draft' || $('#original_post_status').val() == 'auto-draft' ) { + if ( $postStatusSelect.find('input[name="post_status"][value="publish"]').length ) { + removePublishPostStatus(); + setPostStatusValue($('#hidden_post_status').val()); } } else { - optPublish.html( __( 'Published' ) ); + $postStatusSelect.find('input[name="post_status"][value="publish"]').siblings('label').text( __( 'Published' ) ); } - if ( postStatus.is(':hidden') ) + if ( $postStatusSelect.is(':hidden') ) $('#misc-publishing-actions .edit-post-status').show(); } // Update "Status:" to currently selected status. $('#post-status-display').text( // Remove any potential tags from post status text. - wp.sanitize.stripTagsAndEncodeText( $('option:selected', postStatus).text() ) + wp.sanitize.stripTagsAndEncodeText( getPostStatusLabel() ) ); // Show or hide the "Save Draft" button. - if ( - $('option:selected', postStatus).val() == 'private' || - $('option:selected', postStatus).val() == 'publish' - ) { + postStatusValue = getPostStatusValue(); + if ( postStatusValue == 'private' || postStatusValue == 'publish' ) { $('#save-post').hide(); } else { $('#save-post').show(); - if ( $('option:selected', postStatus).val() == 'pending' ) { + if ( postStatusValue == 'pending' ) { $('#save-post').show().val( __( 'Save as Pending' ) ); } else { $('#save-post').show().val( __( 'Save Draft' ) ); @@ -973,7 +1043,7 @@ jQuery( function($) { $postStatusSelect.siblings('a.edit-post-status').on( 'click', function( event ) { if ( $postStatusSelect.is( ':hidden' ) ) { $postStatusSelect.slideDown( 'fast', function() { - $postStatusSelect.find('select').trigger( 'focus' ); + $postStatusSelect.find('input[type="radio"]').first().trigger( 'focus' ); } ); $(this).hide(); } @@ -990,7 +1060,7 @@ jQuery( function($) { // Cancel Post Status editing and hide the options. $postStatusSelect.find('.cancel-post-status').on( 'click', function( event ) { $postStatusSelect.slideUp( 'fast' ).siblings( 'a.edit-post-status' ).show().trigger( 'focus' ); - $('#post_status').val( $('#hidden_post_status').val() ); + setPostStatusValue( $('#hidden_post_status').val() ); updateText(); event.preventDefault(); }); diff --git a/src/wp-admin/css/edit.css b/src/wp-admin/css/edit.css index f1dd76ac31474..229a8b26dc8a3 100644 --- a/src/wp-admin/css/edit.css +++ b/src/wp-admin/css/edit.css @@ -706,12 +706,19 @@ form#tags-filter { font-weight: 600; } +#post-status-select, #post-visibility-select, #comment-status-radio { line-height: 1.5; margin-top: 3px; } +#post-status-select .post-status-options { + border: 0; + margin: 0 0 0.7em; + padding: 0; +} + #linksubmitdiv .inside, /* Old Link Manager back-compat. */ #poststuff #submitdiv .inside { margin: 0; diff --git a/src/wp-admin/includes/meta-boxes.php b/src/wp-admin/includes/meta-boxes.php index 535a00cd3fe94..2de43685d37fa 100644 --- a/src/wp-admin/includes/meta-boxes.php +++ b/src/wp-admin/includes/meta-boxes.php @@ -141,29 +141,31 @@ function post_submit_meta_box( $post, $args = array() ) {
- - post_status, 'publish' ); ?> />
post_status ) : ?> - post_status, 'private' ); ?> value='publish'> + post_status, 'private' ); ?> />
post_status ) : ?> - post_status, 'future' ); ?> value='future'> + post_status, 'future' ); ?> />
- post_status, 'pending' ); ?> value='pending'> + post_status, 'pending' ); ?> />
post_status ) : ?> - post_status, 'auto-draft' ); ?> value='draft'> + post_status, 'auto-draft' ); ?> />
- post_status, 'draft' ); ?> value='draft'> + post_status, 'draft' ); ?> />
- - - + +

+ + +

user->create( array( 'role' => 'administrator' ) ); + } + + public function set_up() { + parent::set_up(); + + require_once ABSPATH . 'wp-admin/includes/meta-boxes.php'; + + wp_set_current_user( self::$admin_id ); + } + + public function test_post_submit_meta_box_status_controls_are_rendered_as_radios() { + $post = self::factory()->post->create_and_get( array( 'post_status' => 'draft' ) ); + $output = $this->get_post_submit_meta_box_output( $post ); + + $this->assertStringNotContainsString( '
' - ); - $publishStatus = $postStatusSelect.find('input[name="post_status"][value="publish"]'); - } - - $publishStatus.siblings('label').text( label ); - setPostStatusValue('publish'); - }; - - /** - * Remove a dynamically added publish status radio. - * - * @ignore - * - * @return {void} - */ - removePublishPostStatus = function() { - $postStatusSelect.find('input[name="post_status"][value="publish"]').closest('.post-status-option').remove(); - }; - /** * When the visibility of a post changes sub-options should be shown or hidden. * @@ -834,8 +757,8 @@ jQuery( function($) { if ( ! $timestampdiv.length ) return true; - var attemptedDate, originalDate, currentDate, publishOn, postStatusValue, - aa = $('#aa').val(), + var attemptedDate, originalDate, currentDate, publishOn, postStatus = $('#post_status'), + optPublish = $('option[value="publish"]', postStatus), aa = $('#aa').val(), mm = $('#mm').val(), jj = $('#jj').val(), hh = $('#hh').val(), mn = $('#mn').val(); attemptedDate = new Date( aa, mm - 1, jj, hh, mn ); @@ -900,34 +823,41 @@ jQuery( function($) { // Add "privately published" to post status when applies. if ( $postVisibilitySelect.find('input:radio:checked').val() == 'private' ) { $('#publish').val( __( 'Update' ) ); - ensurePublishPostStatus( __( 'Privately Published' ) ); + if ( 0 === optPublish.length ) { + postStatus.append(''); + } else { + optPublish.html( __( 'Privately Published' ) ); + } + $('option[value="publish"]', postStatus).prop('selected', true); $('#misc-publishing-actions .edit-post-status').hide(); } else { - if ( $('#original_post_status').val() == 'future' || $('#original_post_status').val() == 'draft' || $('#original_post_status').val() == 'auto-draft' ) { - if ( $postStatusSelect.find('input[name="post_status"][value="publish"]').length ) { - removePublishPostStatus(); - setPostStatusValue($('#hidden_post_status').val()); + if ( $('#original_post_status').val() == 'future' || $('#original_post_status').val() == 'draft' ) { + if ( optPublish.length ) { + optPublish.remove(); + postStatus.val($('#hidden_post_status').val()); } } else { - $postStatusSelect.find('input[name="post_status"][value="publish"]').siblings('label').text( __( 'Published' ) ); + optPublish.html( __( 'Published' ) ); } - if ( $postStatusSelect.is(':hidden') ) + if ( postStatus.is(':hidden') ) $('#misc-publishing-actions .edit-post-status').show(); } // Update "Status:" to currently selected status. $('#post-status-display').text( // Remove any potential tags from post status text. - wp.sanitize.stripTagsAndEncodeText( getPostStatusLabel() ) + wp.sanitize.stripTagsAndEncodeText( $('option:selected', postStatus).text() ) ); // Show or hide the "Save Draft" button. - postStatusValue = getPostStatusValue(); - if ( postStatusValue == 'private' || postStatusValue == 'publish' ) { + if ( + $('option:selected', postStatus).val() == 'private' || + $('option:selected', postStatus).val() == 'publish' + ) { $('#save-post').hide(); } else { $('#save-post').show(); - if ( postStatusValue == 'pending' ) { + if ( $('option:selected', postStatus).val() == 'pending' ) { $('#save-post').show().val( __( 'Save as Pending' ) ); } else { $('#save-post').show().val( __( 'Save Draft' ) ); @@ -1043,7 +973,7 @@ jQuery( function($) { $postStatusSelect.siblings('a.edit-post-status').on( 'click', function( event ) { if ( $postStatusSelect.is( ':hidden' ) ) { $postStatusSelect.slideDown( 'fast', function() { - $postStatusSelect.find('input[type="radio"]').first().trigger( 'focus' ); + $postStatusSelect.find('select').trigger( 'focus' ); } ); $(this).hide(); } @@ -1060,7 +990,7 @@ jQuery( function($) { // Cancel Post Status editing and hide the options. $postStatusSelect.find('.cancel-post-status').on( 'click', function( event ) { $postStatusSelect.slideUp( 'fast' ).siblings( 'a.edit-post-status' ).show().trigger( 'focus' ); - setPostStatusValue( $('#hidden_post_status').val() ); + $('#post_status').val( $('#hidden_post_status').val() ); updateText(); event.preventDefault(); }); diff --git a/src/wp-admin/css/edit.css b/src/wp-admin/css/edit.css index 229a8b26dc8a3..9d6fdeaf010e0 100644 --- a/src/wp-admin/css/edit.css +++ b/src/wp-admin/css/edit.css @@ -713,10 +713,13 @@ form#tags-filter { margin-top: 3px; } -#post-status-select .post-status-options { - border: 0; - margin: 0 0 0.7em; - padding: 0; +#post-status-select select { + max-width: 100%; + width: 100%; +} + +#post-status-select .post-status-actions { + margin: 0.7em 0 0; } #linksubmitdiv .inside, /* Old Link Manager back-compat. */ diff --git a/src/wp-admin/includes/meta-boxes.php b/src/wp-admin/includes/meta-boxes.php index 2de43685d37fa..ca81d369d8458 100644 --- a/src/wp-admin/includes/meta-boxes.php +++ b/src/wp-admin/includes/meta-boxes.php @@ -141,28 +141,28 @@ function post_submit_meta_box( $post, $args = array() ) {
-
- - - + + post_status, 'publish' ); ?> />
+ post_status, 'publish' ); ?> value='publish'> post_status ) : ?> - post_status, 'private' ); ?> />
+ post_status, 'private' ); ?> value='publish'> post_status ) : ?> - post_status, 'future' ); ?> />
+ post_status, 'future' ); ?> value='future'> - post_status, 'pending' ); ?> />
+ post_status, 'pending' ); ?> value='pending'> post_status ) : ?> - post_status, 'auto-draft' ); ?> />
+ post_status, 'auto-draft' ); ?> value='draft'> - post_status, 'draft' ); ?> />
+ post_status, 'draft' ); ?> value='draft'> -
-

+ +

diff --git a/tests/phpunit/tests/admin/includesMetaBoxes.php b/tests/phpunit/tests/admin/includesMetaBoxes.php index 06810f7418672..360220ef91af2 100644 --- a/tests/phpunit/tests/admin/includesMetaBoxes.php +++ b/tests/phpunit/tests/admin/includesMetaBoxes.php @@ -18,22 +18,21 @@ public function set_up() { wp_set_current_user( self::$admin_id ); } - public function test_post_submit_meta_box_status_controls_are_rendered_as_radios() { + public function test_post_submit_meta_box_status_controls_keep_legacy_select_contract() { $post = self::factory()->post->create_and_get( array( 'post_status' => 'draft' ) ); $output = $this->get_post_submit_meta_box_output( $post ); - $this->assertStringNotContainsString( '', $output ); + $this->assertStringNotContainsString( '
assertStringContainsString( '', $output ); + $this->assertStringContainsString( '', $output ); $this->assertMatchesRegularExpression( - '/
.*post-status-radio-pending.*post-status-radio-draft.*<\/fieldset>/s', + '/