From f919b1249bbc28f112bc6327c27b782050d3b361 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 12:44:23 +0000 Subject: [PATCH 01/12] Initial plan From 8f2b422088b37344588325b0664a2a5111a17069 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 12:50:51 +0000 Subject: [PATCH 02/12] Add Post_Revision_Command with restore and diff subcommands Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- composer.json | 3 + entity-command.php | 1 + features/post-revision.feature | 108 ++++++++++++++++++++++ phpcs.xml.dist | 2 +- src/Post_Revision_Command.php | 159 +++++++++++++++++++++++++++++++++ 5 files changed, 272 insertions(+), 1 deletion(-) create mode 100644 features/post-revision.feature create mode 100644 src/Post_Revision_Command.php diff --git a/composer.json b/composer.json index 0c743040..caed252e 100644 --- a/composer.json +++ b/composer.json @@ -114,6 +114,9 @@ "post meta patch", "post meta pluck", "post meta update", + "post revision", + "post revision diff", + "post revision restore", "post term", "post term add", "post term list", diff --git a/entity-command.php b/entity-command.php index 0cecf202..cdad9235 100644 --- a/entity-command.php +++ b/entity-command.php @@ -46,6 +46,7 @@ ) ); WP_CLI::add_command( 'post meta', 'Post_Meta_Command' ); +WP_CLI::add_command( 'post revision', 'Post_Revision_Command' ); WP_CLI::add_command( 'post term', 'Post_Term_Command' ); WP_CLI::add_command( 'post-type', 'Post_Type_Command' ); WP_CLI::add_command( 'site', 'Site_Command' ); diff --git a/features/post-revision.feature b/features/post-revision.feature new file mode 100644 index 00000000..c827e126 --- /dev/null +++ b/features/post-revision.feature @@ -0,0 +1,108 @@ +Feature: Manage WordPress post revisions + + Background: + Given a WP install + + Scenario: Restore a post revision + When I run `wp post create --post_title='Original Post' --post_content='Original content' --porcelain` + Then STDOUT should be a number + And save STDOUT as {POST_ID} + + When I run `wp post update {POST_ID} --post_content='Updated content'` + Then STDOUT should contain: + """ + Success: Updated post {POST_ID}. + """ + + When I run `wp post list --post_type=revision --post_parent={POST_ID} --fields=ID,post_title --format=ids` + Then STDOUT should not be empty + And save STDOUT as {REVISION_ID} + + When I run `wp post revision restore {REVISION_ID}` + Then STDOUT should contain: + """ + Success: Restored revision + """ + + When I run `wp post get {POST_ID} --field=post_content` + Then STDOUT should contain: + """ + Original content + """ + + Scenario: Restore invalid revision should fail + When I try `wp post revision restore 99999` + Then STDERR should contain: + """ + Error: Invalid revision ID + """ + And the return code should be 1 + + Scenario: Show diff between two revisions + When I run `wp post create --post_title='Test Post' --post_content='First version' --porcelain` + Then STDOUT should be a number + And save STDOUT as {POST_ID} + + When I run `wp post update {POST_ID} --post_content='Second version'` + Then STDOUT should contain: + """ + Success: Updated post {POST_ID}. + """ + + When I run `wp post list --post_type=revision --post_parent={POST_ID} --fields=ID --format=csv --orderby=ID --order=ASC` + Then STDOUT should not be empty + + When I run `wp post list --post_type=revision --post_parent={POST_ID} --format=ids --orderby=ID --order=ASC` + Then STDOUT should not be empty + + Scenario: Show diff between revision and current post + When I run `wp post create --post_title='Diff Test' --post_content='Original text' --porcelain` + Then STDOUT should be a number + And save STDOUT as {POST_ID} + + When I run `wp post update {POST_ID} --post_content='Modified text'` + Then STDOUT should contain: + """ + Success: Updated post {POST_ID}. + """ + + When I run `wp post list --post_type=revision --post_parent={POST_ID} --fields=ID --format=ids --orderby=ID --order=ASC` + Then STDOUT should not be empty + And save STDOUT as {REVISION_ID} + + When I run `wp post revision diff {REVISION_ID}` + Then the return code should be 0 + + Scenario: Diff with invalid revision should fail + When I try `wp post revision diff 99999` + Then STDERR should contain: + """ + Error: Invalid 'from' ID + """ + And the return code should be 1 + + Scenario: Diff between two invalid revisions should fail + When I try `wp post revision diff 99998 99999` + Then STDERR should contain: + """ + Error: Invalid 'from' ID + """ + And the return code should be 1 + + Scenario: Diff with specific field + When I run `wp post create --post_title='Field Test' --post_content='Some content' --porcelain` + Then STDOUT should be a number + And save STDOUT as {POST_ID} + + When I run `wp post update {POST_ID} --post_title='Modified Field Test'` + Then STDOUT should contain: + """ + Success: Updated post {POST_ID}. + """ + + When I run `wp post list --post_type=revision --post_parent={POST_ID} --fields=ID --format=ids --orderby=ID --order=ASC` + Then STDOUT should not be empty + And save STDOUT as {REVISION_ID} + + When I run `wp post revision diff {REVISION_ID} --field=post_title` + Then the return code should be 0 diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 0df76141..6ab1a682 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -65,7 +65,7 @@ */src/Network_Meta_Command\.php$ */src/Network_Namespace\.php$ */src/Option_Command\.php$ - */src/Post(_Block|_Meta|_Term|_Type)?_Command\.php$ + */src/Post(_Block|_Meta|_Revision|_Term|_Type)?_Command\.php$ */src/Signup_Command\.php$ */src/Site(_Meta|_Option)?_Command\.php$ */src/Term(_Meta)?_Command\.php$ diff --git a/src/Post_Revision_Command.php b/src/Post_Revision_Command.php new file mode 100644 index 00000000..f3ca23a7 --- /dev/null +++ b/src/Post_Revision_Command.php @@ -0,0 +1,159 @@ +fetcher = new PostFetcher(); + } + + /** + * Restores a post revision. + * + * ## OPTIONS + * + * + * : The revision ID to restore. + * + * ## EXAMPLES + * + * # Restore a post revision + * $ wp post revision restore 123 + * Success: Restored revision 123. + * + * @subcommand restore + */ + public function restore( $args ) { + $revision_id = (int) $args[0]; + + // Get the revision post + $revision = wp_get_post_revision( $revision_id ); + + if ( ! $revision ) { + WP_CLI::error( "Invalid revision ID {$revision_id}." ); + } + + // Restore the revision + $restored_post_id = wp_restore_post_revision( $revision_id ); + + if ( false === $restored_post_id || null === $restored_post_id ) { + WP_CLI::error( "Failed to restore revision {$revision_id}." ); + } + + WP_CLI::success( "Restored revision {$revision_id}." ); + } + + /** + * Shows the difference between two revisions. + * + * ## OPTIONS + * + * + * : The 'from' revision ID or post ID. + * + * [] + * : The 'to' revision ID. If not provided, compares with the current post. + * + * [--field=] + * : Compare specific field(s). Default: post_content + * + * ## EXAMPLES + * + * # Show diff between two revisions + * $ wp post revision diff 123 456 + * + * # Show diff between a revision and the current post + * $ wp post revision diff 123 + * + * @subcommand diff + */ + public function diff( $args, $assoc_args ) { + $from_id = (int) $args[0]; + $to_id = isset( $args[1] ) ? (int) $args[1] : null; + $field = Utils\get_flag_value( $assoc_args, 'field', 'post_content' ); + + // Get the 'from' revision or post + $from_revision = wp_get_post_revision( $from_id ); + if ( ! $from_revision instanceof \WP_Post ) { + // Try as a regular post + $from_revision = get_post( $from_id ); + if ( ! $from_revision instanceof \WP_Post ) { + WP_CLI::error( "Invalid 'from' ID {$from_id}." ); + } + } + + // Get the 'to' revision or post + $to_revision = null; + if ( $to_id ) { + $to_revision = wp_get_post_revision( $to_id ); + if ( ! $to_revision instanceof \WP_Post ) { + // Try as a regular post + $to_revision = get_post( $to_id ); + if ( ! $to_revision instanceof \WP_Post ) { + WP_CLI::error( "Invalid 'to' ID {$to_id}." ); + } + } + } elseif ( 'revision' === $from_revision->post_type ) { + // If no 'to' ID provided, use the parent post of the revision + $to_revision = get_post( $from_revision->post_parent ); + if ( ! $to_revision instanceof \WP_Post ) { + WP_CLI::error( "Could not find parent post for revision {$from_id}." ); + } + } else { + WP_CLI::error( "Please provide a 'to' revision ID when comparing posts." ); + } + + // Validate field + if ( ! property_exists( $from_revision, $field ) || ! property_exists( $to_revision, $field ) ) { + WP_CLI::error( "Invalid field '{$field}'." ); + } + + // Get the field values + $left_string = $from_revision->{$field}; + $right_string = $to_revision->{$field}; + + // Generate the diff + $diff_args = [ + 'title_left' => sprintf( + '%s (%s) - ID %d', + $from_revision->post_title, + $from_revision->post_modified, + $from_revision->ID + ), + 'title_right' => sprintf( + '%s (%s) - ID %d', + $to_revision->post_title, + $to_revision->post_modified, + $to_revision->ID + ), + ]; + + $diff = wp_text_diff( $left_string, $right_string, $diff_args ); + + if ( ! $diff ) { + WP_CLI::success( 'No difference found.' ); + return; + } + + // Output the diff + WP_CLI::line( $diff ); + } +} From 98d85906af44c31fe7ee1b4bce5df029ac8cc4d4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 12:53:56 +0000 Subject: [PATCH 03/12] Address code review feedback: validate fields properly and remove unused property Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Post_Revision_Command.php | 41 +++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/src/Post_Revision_Command.php b/src/Post_Revision_Command.php index f3ca23a7..5d42de75 100644 --- a/src/Post_Revision_Command.php +++ b/src/Post_Revision_Command.php @@ -1,6 +1,5 @@ fetcher = new PostFetcher(); - } + /** + * Valid post fields that can be compared. + * + * @var array + */ + private $valid_fields = [ + 'post_title', + 'post_content', + 'post_excerpt', + 'post_name', + 'post_status', + 'post_type', + 'post_author', + 'post_date', + 'post_date_gmt', + 'post_modified', + 'post_modified_gmt', + 'post_parent', + 'menu_order', + 'comment_status', + 'ping_status', + ]; /** * Restores a post revision. @@ -122,11 +138,18 @@ public function diff( $args, $assoc_args ) { } // Validate field - if ( ! property_exists( $from_revision, $field ) || ! property_exists( $to_revision, $field ) ) { - WP_CLI::error( "Invalid field '{$field}'." ); + if ( ! in_array( $field, $this->valid_fields, true ) ) { + WP_CLI::error( "Invalid field '{$field}'. Valid fields: " . implode( ', ', $this->valid_fields ) ); + } + + // Get the field values - use isset to check if field exists on the object + if ( ! isset( $from_revision->{$field} ) ) { + WP_CLI::error( "Field '{$field}' not found on revision {$from_id}." ); + } + if ( ! isset( $to_revision->{$field} ) ) { + WP_CLI::error( "Field '{$field}' not found on revision/post {$to_id}." ); } - // Get the field values $left_string = $from_revision->{$field}; $right_string = $to_revision->{$field}; From 598c559c4736a7371387ebf4a642ab25e1c7466f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 12:55:31 +0000 Subject: [PATCH 04/12] Fix error message display and simplify return value check Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Post_Revision_Command.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Post_Revision_Command.php b/src/Post_Revision_Command.php index 5d42de75..41e8f7ee 100644 --- a/src/Post_Revision_Command.php +++ b/src/Post_Revision_Command.php @@ -70,7 +70,7 @@ public function restore( $args ) { // Restore the revision $restored_post_id = wp_restore_post_revision( $revision_id ); - if ( false === $restored_post_id || null === $restored_post_id ) { + if ( false === $restored_post_id ) { WP_CLI::error( "Failed to restore revision {$revision_id}." ); } @@ -147,7 +147,8 @@ public function diff( $args, $assoc_args ) { WP_CLI::error( "Field '{$field}' not found on revision {$from_id}." ); } if ( ! isset( $to_revision->{$field} ) ) { - WP_CLI::error( "Field '{$field}' not found on revision/post {$to_id}." ); + $to_error_id = $to_id ?? $to_revision->ID; + WP_CLI::error( "Field '{$field}' not found on revision/post {$to_error_id}." ); } $left_string = $from_revision->{$field}; From af620a236d24ec18489252a0a4bb103fbcd62258 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 12:57:53 +0000 Subject: [PATCH 05/12] Handle null return value from wp_restore_post_revision and improve error handling Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Post_Revision_Command.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Post_Revision_Command.php b/src/Post_Revision_Command.php index 41e8f7ee..7edcb6d0 100644 --- a/src/Post_Revision_Command.php +++ b/src/Post_Revision_Command.php @@ -70,7 +70,8 @@ public function restore( $args ) { // Restore the revision $restored_post_id = wp_restore_post_revision( $revision_id ); - if ( false === $restored_post_id ) { + // wp_restore_post_revision() returns post ID on success, false on failure, or null if revision is same as current + if ( ! $restored_post_id ) { WP_CLI::error( "Failed to restore revision {$revision_id}." ); } @@ -146,6 +147,8 @@ public function diff( $args, $assoc_args ) { if ( ! isset( $from_revision->{$field} ) ) { WP_CLI::error( "Field '{$field}' not found on revision {$from_id}." ); } + + // $to_revision is guaranteed to be non-null at this point due to earlier validation if ( ! isset( $to_revision->{$field} ) ) { $to_error_id = $to_id ?? $to_revision->ID; WP_CLI::error( "Field '{$field}' not found on revision/post {$to_error_id}." ); From 9b54f2f9c70aa69b143d7680b525ead5cd5c8bac Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 13 Jan 2026 12:27:47 +0100 Subject: [PATCH 06/12] Update src/Post_Revision_Command.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/Post_Revision_Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Post_Revision_Command.php b/src/Post_Revision_Command.php index 7edcb6d0..1b1b7522 100644 --- a/src/Post_Revision_Command.php +++ b/src/Post_Revision_Command.php @@ -71,7 +71,7 @@ public function restore( $args ) { $restored_post_id = wp_restore_post_revision( $revision_id ); // wp_restore_post_revision() returns post ID on success, false on failure, or null if revision is same as current - if ( ! $restored_post_id ) { + if ( false === $restored_post_id ) { WP_CLI::error( "Failed to restore revision {$revision_id}." ); } From 3e511a1395831c4bc815d222e286e5301b631666 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 13 Jan 2026 12:28:03 +0100 Subject: [PATCH 07/12] Update src/Post_Revision_Command.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/Post_Revision_Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Post_Revision_Command.php b/src/Post_Revision_Command.php index 1b1b7522..4f2de5db 100644 --- a/src/Post_Revision_Command.php +++ b/src/Post_Revision_Command.php @@ -87,7 +87,7 @@ public function restore( $args ) { * : The 'from' revision ID or post ID. * * [] - * : The 'to' revision ID. If not provided, compares with the current post. + * : The 'to' revision ID or post ID. If not provided, compares with the current post. * * [--field=] * : Compare specific field(s). Default: post_content From acc29070b2ae6fc2dc6eaf18a146595f324cdb00 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 13 Jan 2026 12:28:22 +0100 Subject: [PATCH 08/12] Update src/Post_Revision_Command.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/Post_Revision_Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Post_Revision_Command.php b/src/Post_Revision_Command.php index 4f2de5db..961cf646 100644 --- a/src/Post_Revision_Command.php +++ b/src/Post_Revision_Command.php @@ -145,7 +145,7 @@ public function diff( $args, $assoc_args ) { // Get the field values - use isset to check if field exists on the object if ( ! isset( $from_revision->{$field} ) ) { - WP_CLI::error( "Field '{$field}' not found on revision {$from_id}." ); + WP_CLI::error( "Field '{$field}' not found on post/revision {$from_id}." ); } // $to_revision is guaranteed to be non-null at this point due to earlier validation From c1c8cf91aa7e45697ffe8c09c916b3855ebd11bc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 13 Jan 2026 11:30:43 +0000 Subject: [PATCH 09/12] Complete test scenario for diff between two revisions Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/post-revision.feature | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/features/post-revision.feature b/features/post-revision.feature index c827e126..db80ee77 100644 --- a/features/post-revision.feature +++ b/features/post-revision.feature @@ -49,11 +49,24 @@ Feature: Manage WordPress post revisions Success: Updated post {POST_ID}. """ - When I run `wp post list --post_type=revision --post_parent={POST_ID} --fields=ID --format=csv --orderby=ID --order=ASC` - Then STDOUT should not be empty + When I run `wp post update {POST_ID} --post_content='Third version'` + Then STDOUT should contain: + """ + Success: Updated post {POST_ID}. + """ - When I run `wp post list --post_type=revision --post_parent={POST_ID} --format=ids --orderby=ID --order=ASC` + When I run `wp post list --post_type=revision --post_parent={POST_ID} --fields=ID --format=ids --orderby=ID --order=ASC` Then STDOUT should not be empty + And save STDOUT as {REVISION_IDS} + + When I run `echo "{REVISION_IDS}" | awk '{print $1}'` + Then save STDOUT as {REVISION_ID_1} + + When I run `echo "{REVISION_IDS}" | awk '{print $2}'` + Then save STDOUT as {REVISION_ID_2} + + When I run `wp post revision diff {REVISION_ID_1} {REVISION_ID_2}` + Then the return code should be 0 Scenario: Show diff between revision and current post When I run `wp post create --post_title='Diff Test' --post_content='Original text' --porcelain` From 4b174c42e117c0fbef06467b67472bf1ff6d5b67 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 16 Jan 2026 20:42:12 +0000 Subject: [PATCH 10/12] Replace wp_text_diff HTML output with CLI-friendly colored diff Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Post_Revision_Command.php | 99 +++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 21 deletions(-) diff --git a/src/Post_Revision_Command.php b/src/Post_Revision_Command.php index 961cf646..804193ca 100644 --- a/src/Post_Revision_Command.php +++ b/src/Post_Revision_Command.php @@ -157,30 +157,87 @@ public function diff( $args, $assoc_args ) { $left_string = $from_revision->{$field}; $right_string = $to_revision->{$field}; - // Generate the diff - $diff_args = [ - 'title_left' => sprintf( - '%s (%s) - ID %d', - $from_revision->post_title, - $from_revision->post_modified, - $from_revision->ID - ), - 'title_right' => sprintf( - '%s (%s) - ID %d', - $to_revision->post_title, - $to_revision->post_modified, - $to_revision->ID - ), - ]; - - $diff = wp_text_diff( $left_string, $right_string, $diff_args ); - - if ( ! $diff ) { + // Split content into lines for diff + $left_lines = explode( "\n", $left_string ); + $right_lines = explode( "\n", $right_string ); + + // Create Text_Diff object + $text_diff = new \Text_Diff( 'auto', [ $left_lines, $right_lines ] ); + + // Check if there are any changes + if ( 0 === $text_diff->countAddedLines() && 0 === $text_diff->countDeletedLines() ) { WP_CLI::success( 'No difference found.' ); return; } - // Output the diff - WP_CLI::line( $diff ); + // Display header + WP_CLI::line( + WP_CLI::colorize( + sprintf( + '%%y--- %s (%s) - ID %d%%n', + $from_revision->post_title, + $from_revision->post_modified, + $from_revision->ID + ) + ) + ); + WP_CLI::line( + WP_CLI::colorize( + sprintf( + '%%y+++ %s (%s) - ID %d%%n', + $to_revision->post_title, + $to_revision->post_modified, + $to_revision->ID + ) + ) + ); + WP_CLI::line( '' ); + + // Render the diff using CLI-friendly format + $this->render_cli_diff( $text_diff ); + } + + /** + * Renders a diff in CLI-friendly format with colors. + * + * @param \Text_Diff $diff The diff object to render. + */ + private function render_cli_diff( $diff ) { + $edits = $diff->getDiff(); + + foreach ( $edits as $edit ) { + switch ( get_class( $edit ) ) { + case 'Text_Diff_Op_copy': + // Unchanged lines - show in default color + foreach ( $edit->orig as $line ) { + WP_CLI::line( ' ' . $line ); + } + break; + + case 'Text_Diff_Op_add': + // Added lines - show in green + foreach ( $edit->final as $line ) { + WP_CLI::line( WP_CLI::colorize( '%g+ ' . $line . '%n' ) ); + } + break; + + case 'Text_Diff_Op_delete': + // Deleted lines - show in red + foreach ( $edit->orig as $line ) { + WP_CLI::line( WP_CLI::colorize( '%r- ' . $line . '%n' ) ); + } + break; + + case 'Text_Diff_Op_change': + // Changed lines - show deletions in red, additions in green + foreach ( $edit->orig as $line ) { + WP_CLI::line( WP_CLI::colorize( '%r- ' . $line . '%n' ) ); + } + foreach ( $edit->final as $line ) { + WP_CLI::line( WP_CLI::colorize( '%g+ ' . $line . '%n' ) ); + } + break; + } + } } } From 087ee6bc2b03cb08df2c7b04b0310b35b72a0a7f Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Fri, 16 Jan 2026 21:27:12 +0100 Subject: [PATCH 11/12] Fix test --- features/post-revision.feature | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/features/post-revision.feature b/features/post-revision.feature index db80ee77..2330eca7 100644 --- a/features/post-revision.feature +++ b/features/post-revision.feature @@ -3,6 +3,9 @@ Feature: Manage WordPress post revisions Background: Given a WP install + # Creating a published post doesn't create an initial revision, + # so we update it twice here and restore the middle version. + # See https://github.com/wp-cli/entity-command/issues/564. Scenario: Restore a post revision When I run `wp post create --post_title='Original Post' --post_content='Original content' --porcelain` Then STDOUT should be a number @@ -14,10 +17,22 @@ Feature: Manage WordPress post revisions Success: Updated post {POST_ID}. """ - When I run `wp post list --post_type=revision --post_parent={POST_ID} --fields=ID,post_title --format=ids` + When I run `wp post list --post_type=revision --post_parent={POST_ID} --format=ids` Then STDOUT should not be empty And save STDOUT as {REVISION_ID} + When I run `wp post update {POST_ID} --post_content='Another one'` + Then STDOUT should contain: + """ + Success: Updated post {POST_ID}. + """ + + When I run `wp post get {POST_ID} --field=post_content` + Then STDOUT should contain: + """ + Another one + """ + When I run `wp post revision restore {REVISION_ID}` Then STDOUT should contain: """ @@ -27,7 +42,7 @@ Feature: Manage WordPress post revisions When I run `wp post get {POST_ID} --field=post_content` Then STDOUT should contain: """ - Original content + Updated content """ Scenario: Restore invalid revision should fail From f812fc584999fa531ec775777c2e46d7900dd297 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Fri, 16 Jan 2026 21:52:09 +0100 Subject: [PATCH 12/12] Update tests --- features/post-revision.feature | 21 ++++++++++++++++++--- src/Post_Revision_Command.php | 5 +++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/features/post-revision.feature b/features/post-revision.feature index 2330eca7..9a63289b 100644 --- a/features/post-revision.feature +++ b/features/post-revision.feature @@ -64,7 +64,7 @@ Feature: Manage WordPress post revisions Success: Updated post {POST_ID}. """ - When I run `wp post update {POST_ID} --post_content='Third version'` + When I run `wp post update {POST_ID} --post_title='New Title' --post_content='Third version'` Then STDOUT should contain: """ Success: Updated post {POST_ID}. @@ -81,7 +81,19 @@ Feature: Manage WordPress post revisions Then save STDOUT as {REVISION_ID_2} When I run `wp post revision diff {REVISION_ID_1} {REVISION_ID_2}` - Then the return code should be 0 + Then STDOUT should contain: + """ + - Second version + + Third version + """ + And STDOUT should contain: + """ + --- Test Post + """ + And STDOUT should contain: + """ + +++ New Title + """ Scenario: Show diff between revision and current post When I run `wp post create --post_title='Diff Test' --post_content='Original text' --porcelain` @@ -99,7 +111,10 @@ Feature: Manage WordPress post revisions And save STDOUT as {REVISION_ID} When I run `wp post revision diff {REVISION_ID}` - Then the return code should be 0 + Then STDOUT should contain: + """ + Success: No difference found. + """ Scenario: Diff with invalid revision should fail When I try `wp post revision diff 99999` diff --git a/src/Post_Revision_Command.php b/src/Post_Revision_Command.php index 804193ca..71931831 100644 --- a/src/Post_Revision_Command.php +++ b/src/Post_Revision_Command.php @@ -161,6 +161,11 @@ public function diff( $args, $assoc_args ) { $left_lines = explode( "\n", $left_string ); $right_lines = explode( "\n", $right_string ); + if ( ! class_exists( 'Text_Diff', false ) ) { + // @phpstan-ignore constant.notFound + require ABSPATH . WPINC . '/wp-diff.php'; + } + // Create Text_Diff object $text_diff = new \Text_Diff( 'auto', [ $left_lines, $right_lines ] );