Skip to content

Commit 8f2b422

Browse files
Copilotswissspidy
andcommitted
Add Post_Revision_Command with restore and diff subcommands
Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
1 parent f919b12 commit 8f2b422

File tree

5 files changed

+272
-1
lines changed

5 files changed

+272
-1
lines changed

composer.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@
114114
"post meta patch",
115115
"post meta pluck",
116116
"post meta update",
117+
"post revision",
118+
"post revision diff",
119+
"post revision restore",
117120
"post term",
118121
"post term add",
119122
"post term list",

entity-command.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
)
4747
);
4848
WP_CLI::add_command( 'post meta', 'Post_Meta_Command' );
49+
WP_CLI::add_command( 'post revision', 'Post_Revision_Command' );
4950
WP_CLI::add_command( 'post term', 'Post_Term_Command' );
5051
WP_CLI::add_command( 'post-type', 'Post_Type_Command' );
5152
WP_CLI::add_command( 'site', 'Site_Command' );

features/post-revision.feature

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
Feature: Manage WordPress post revisions
2+
3+
Background:
4+
Given a WP install
5+
6+
Scenario: Restore a post revision
7+
When I run `wp post create --post_title='Original Post' --post_content='Original content' --porcelain`
8+
Then STDOUT should be a number
9+
And save STDOUT as {POST_ID}
10+
11+
When I run `wp post update {POST_ID} --post_content='Updated content'`
12+
Then STDOUT should contain:
13+
"""
14+
Success: Updated post {POST_ID}.
15+
"""
16+
17+
When I run `wp post list --post_type=revision --post_parent={POST_ID} --fields=ID,post_title --format=ids`
18+
Then STDOUT should not be empty
19+
And save STDOUT as {REVISION_ID}
20+
21+
When I run `wp post revision restore {REVISION_ID}`
22+
Then STDOUT should contain:
23+
"""
24+
Success: Restored revision
25+
"""
26+
27+
When I run `wp post get {POST_ID} --field=post_content`
28+
Then STDOUT should contain:
29+
"""
30+
Original content
31+
"""
32+
33+
Scenario: Restore invalid revision should fail
34+
When I try `wp post revision restore 99999`
35+
Then STDERR should contain:
36+
"""
37+
Error: Invalid revision ID
38+
"""
39+
And the return code should be 1
40+
41+
Scenario: Show diff between two revisions
42+
When I run `wp post create --post_title='Test Post' --post_content='First version' --porcelain`
43+
Then STDOUT should be a number
44+
And save STDOUT as {POST_ID}
45+
46+
When I run `wp post update {POST_ID} --post_content='Second version'`
47+
Then STDOUT should contain:
48+
"""
49+
Success: Updated post {POST_ID}.
50+
"""
51+
52+
When I run `wp post list --post_type=revision --post_parent={POST_ID} --fields=ID --format=csv --orderby=ID --order=ASC`
53+
Then STDOUT should not be empty
54+
55+
When I run `wp post list --post_type=revision --post_parent={POST_ID} --format=ids --orderby=ID --order=ASC`
56+
Then STDOUT should not be empty
57+
58+
Scenario: Show diff between revision and current post
59+
When I run `wp post create --post_title='Diff Test' --post_content='Original text' --porcelain`
60+
Then STDOUT should be a number
61+
And save STDOUT as {POST_ID}
62+
63+
When I run `wp post update {POST_ID} --post_content='Modified text'`
64+
Then STDOUT should contain:
65+
"""
66+
Success: Updated post {POST_ID}.
67+
"""
68+
69+
When I run `wp post list --post_type=revision --post_parent={POST_ID} --fields=ID --format=ids --orderby=ID --order=ASC`
70+
Then STDOUT should not be empty
71+
And save STDOUT as {REVISION_ID}
72+
73+
When I run `wp post revision diff {REVISION_ID}`
74+
Then the return code should be 0
75+
76+
Scenario: Diff with invalid revision should fail
77+
When I try `wp post revision diff 99999`
78+
Then STDERR should contain:
79+
"""
80+
Error: Invalid 'from' ID
81+
"""
82+
And the return code should be 1
83+
84+
Scenario: Diff between two invalid revisions should fail
85+
When I try `wp post revision diff 99998 99999`
86+
Then STDERR should contain:
87+
"""
88+
Error: Invalid 'from' ID
89+
"""
90+
And the return code should be 1
91+
92+
Scenario: Diff with specific field
93+
When I run `wp post create --post_title='Field Test' --post_content='Some content' --porcelain`
94+
Then STDOUT should be a number
95+
And save STDOUT as {POST_ID}
96+
97+
When I run `wp post update {POST_ID} --post_title='Modified Field Test'`
98+
Then STDOUT should contain:
99+
"""
100+
Success: Updated post {POST_ID}.
101+
"""
102+
103+
When I run `wp post list --post_type=revision --post_parent={POST_ID} --fields=ID --format=ids --orderby=ID --order=ASC`
104+
Then STDOUT should not be empty
105+
And save STDOUT as {REVISION_ID}
106+
107+
When I run `wp post revision diff {REVISION_ID} --field=post_title`
108+
Then the return code should be 0

phpcs.xml.dist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
<exclude-pattern>*/src/Network_Meta_Command\.php$</exclude-pattern>
6666
<exclude-pattern>*/src/Network_Namespace\.php$</exclude-pattern>
6767
<exclude-pattern>*/src/Option_Command\.php$</exclude-pattern>
68-
<exclude-pattern>*/src/Post(_Block|_Meta|_Term|_Type)?_Command\.php$</exclude-pattern>
68+
<exclude-pattern>*/src/Post(_Block|_Meta|_Revision|_Term|_Type)?_Command\.php$</exclude-pattern>
6969
<exclude-pattern>*/src/Signup_Command\.php$</exclude-pattern>
7070
<exclude-pattern>*/src/Site(_Meta|_Option)?_Command\.php$</exclude-pattern>
7171
<exclude-pattern>*/src/Term(_Meta)?_Command\.php$</exclude-pattern>

src/Post_Revision_Command.php

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
<?php
2+
3+
use WP_CLI\Fetchers\Post as PostFetcher;
4+
use WP_CLI\Utils;
5+
6+
/**
7+
* Manages post revisions.
8+
*
9+
* ## EXAMPLES
10+
*
11+
* # Restore a post revision
12+
* $ wp post revision restore 123
13+
* Success: Restored revision 123.
14+
*
15+
* # Show diff between two revisions
16+
* $ wp post revision diff 123 456
17+
*
18+
* @package wp-cli
19+
*/
20+
class Post_Revision_Command {
21+
22+
private $fetcher;
23+
24+
public function __construct() {
25+
$this->fetcher = new PostFetcher();
26+
}
27+
28+
/**
29+
* Restores a post revision.
30+
*
31+
* ## OPTIONS
32+
*
33+
* <revision_id>
34+
* : The revision ID to restore.
35+
*
36+
* ## EXAMPLES
37+
*
38+
* # Restore a post revision
39+
* $ wp post revision restore 123
40+
* Success: Restored revision 123.
41+
*
42+
* @subcommand restore
43+
*/
44+
public function restore( $args ) {
45+
$revision_id = (int) $args[0];
46+
47+
// Get the revision post
48+
$revision = wp_get_post_revision( $revision_id );
49+
50+
if ( ! $revision ) {
51+
WP_CLI::error( "Invalid revision ID {$revision_id}." );
52+
}
53+
54+
// Restore the revision
55+
$restored_post_id = wp_restore_post_revision( $revision_id );
56+
57+
if ( false === $restored_post_id || null === $restored_post_id ) {
58+
WP_CLI::error( "Failed to restore revision {$revision_id}." );
59+
}
60+
61+
WP_CLI::success( "Restored revision {$revision_id}." );
62+
}
63+
64+
/**
65+
* Shows the difference between two revisions.
66+
*
67+
* ## OPTIONS
68+
*
69+
* <from>
70+
* : The 'from' revision ID or post ID.
71+
*
72+
* [<to>]
73+
* : The 'to' revision ID. If not provided, compares with the current post.
74+
*
75+
* [--field=<field>]
76+
* : Compare specific field(s). Default: post_content
77+
*
78+
* ## EXAMPLES
79+
*
80+
* # Show diff between two revisions
81+
* $ wp post revision diff 123 456
82+
*
83+
* # Show diff between a revision and the current post
84+
* $ wp post revision diff 123
85+
*
86+
* @subcommand diff
87+
*/
88+
public function diff( $args, $assoc_args ) {
89+
$from_id = (int) $args[0];
90+
$to_id = isset( $args[1] ) ? (int) $args[1] : null;
91+
$field = Utils\get_flag_value( $assoc_args, 'field', 'post_content' );
92+
93+
// Get the 'from' revision or post
94+
$from_revision = wp_get_post_revision( $from_id );
95+
if ( ! $from_revision instanceof \WP_Post ) {
96+
// Try as a regular post
97+
$from_revision = get_post( $from_id );
98+
if ( ! $from_revision instanceof \WP_Post ) {
99+
WP_CLI::error( "Invalid 'from' ID {$from_id}." );
100+
}
101+
}
102+
103+
// Get the 'to' revision or post
104+
$to_revision = null;
105+
if ( $to_id ) {
106+
$to_revision = wp_get_post_revision( $to_id );
107+
if ( ! $to_revision instanceof \WP_Post ) {
108+
// Try as a regular post
109+
$to_revision = get_post( $to_id );
110+
if ( ! $to_revision instanceof \WP_Post ) {
111+
WP_CLI::error( "Invalid 'to' ID {$to_id}." );
112+
}
113+
}
114+
} elseif ( 'revision' === $from_revision->post_type ) {
115+
// If no 'to' ID provided, use the parent post of the revision
116+
$to_revision = get_post( $from_revision->post_parent );
117+
if ( ! $to_revision instanceof \WP_Post ) {
118+
WP_CLI::error( "Could not find parent post for revision {$from_id}." );
119+
}
120+
} else {
121+
WP_CLI::error( "Please provide a 'to' revision ID when comparing posts." );
122+
}
123+
124+
// Validate field
125+
if ( ! property_exists( $from_revision, $field ) || ! property_exists( $to_revision, $field ) ) {
126+
WP_CLI::error( "Invalid field '{$field}'." );
127+
}
128+
129+
// Get the field values
130+
$left_string = $from_revision->{$field};
131+
$right_string = $to_revision->{$field};
132+
133+
// Generate the diff
134+
$diff_args = [
135+
'title_left' => sprintf(
136+
'%s (%s) - ID %d',
137+
$from_revision->post_title,
138+
$from_revision->post_modified,
139+
$from_revision->ID
140+
),
141+
'title_right' => sprintf(
142+
'%s (%s) - ID %d',
143+
$to_revision->post_title,
144+
$to_revision->post_modified,
145+
$to_revision->ID
146+
),
147+
];
148+
149+
$diff = wp_text_diff( $left_string, $right_string, $diff_args );
150+
151+
if ( ! $diff ) {
152+
WP_CLI::success( 'No difference found.' );
153+
return;
154+
}
155+
156+
// Output the diff
157+
WP_CLI::line( $diff );
158+
}
159+
}

0 commit comments

Comments
 (0)