Skip to content
Open
20 changes: 20 additions & 0 deletions features/post-create-duplicate.feature
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,23 @@ Feature: Create Duplicate WordPress post from existing posts.
Then STDOUT should be a table containing rows:
| Field | Value |
| post_type | page |

Scenario: Duplicating a post does not inherit its modification date
Given a WP install

When I run `wp post create --post_title='Source' --post_status=publish --porcelain`
Then STDOUT should be a number
And save STDOUT as {SOURCE_ID}

When I run `wp post update {SOURCE_ID} --post_modified='2015-03-03 09:00:00'`
Then STDOUT should not be empty

When I run `wp post create --from-post={SOURCE_ID} --post_title='Duplicate' --porcelain`
Then STDOUT should be a number
And save STDOUT as {DUPLICATE_ID}

When I run `wp post get {DUPLICATE_ID} --field=post_modified`
Then STDOUT should not contain:
"""
2015-03-03
"""
104 changes: 104 additions & 0 deletions features/post.feature
Original file line number Diff line number Diff line change
Expand Up @@ -878,3 +878,107 @@ Feature: Manage WordPress posts
"""
2
"""

Scenario: Set a post's modification date on update
Given a WP install

When I run `wp post create --post_title='A post' --post_status=publish --porcelain`
Then STDOUT should be a number
And save STDOUT as {POST_ID}

When I run `wp post update {POST_ID} --post_modified='2020-01-01 12:00:00'`
Then STDOUT should be:
"""
Success: Updated post {POST_ID}.
"""

When I run `wp post get {POST_ID} --field=post_modified`
Then STDOUT should be:
"""
2020-01-01 12:00:00
"""

Scenario: Set a post's modification date on create
Given a WP install

When I run `wp post create --post_title='Another post' --post_date='2019-05-05 10:00:00' --post_modified='2020-01-01 12:00:00' --porcelain`
Then STDOUT should be a number
And save STDOUT as {POST_ID}

When I run `wp post get {POST_ID} --field=post_modified`
Then STDOUT should be:
"""
2020-01-01 12:00:00
"""
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Scenario: A post's modification date defaults to the current time
Given a WP install

# Given a known modification date, so that an update which failed to set one
# would leave this value behind and be caught.
When I run `wp post create --post_title='Undated post' --post_status=publish --post_modified='2019-02-03 04:05:06' --porcelain`
Then STDOUT should be a number
And save STDOUT as {POST_ID}

When I run `wp post get {POST_ID} --field=post_modified`
Then STDOUT should be:
"""
2019-02-03 04:05:06
"""

When I run `wp post update {POST_ID} --post_title='Retitled'`
Then STDOUT should be:
"""
Success: Updated post {POST_ID}.
"""

When I run `wp post get {POST_ID} --field=post_modified`
Then STDOUT should not contain:
"""
2019-02-03 04:05:06
"""
And STDOUT should not be empty

Scenario: Setting only the GMT modification date derives the local one
Given a WP install

# A timezone with an offset, so the derived local value is distinguishable
# from the GMT one it was derived from. 1 January is outside DST in New York.
When I run `wp option update timezone_string 'America/New_York'`
Then STDOUT should not be empty
Comment thread
swissspidy marked this conversation as resolved.

When I run `wp post create --post_title='GMT only' --post_status=publish --post_modified_gmt='2020-01-01 12:00:00' --porcelain`
Then STDOUT should be a number
And save STDOUT as {POST_ID}

When I run `wp post get {POST_ID} --field=post_modified_gmt`
Then STDOUT should be:
"""
2020-01-01 12:00:00
"""

When I run `wp post get {POST_ID} --field=post_modified`
Then STDOUT should be:
"""
2020-01-01 07:00:00
"""

# And the same on update, which takes the other of the two code paths.
When I run `wp post update {POST_ID} --post_modified_gmt='2020-06-01 12:00:00'`
Then STDOUT should be:
"""
Success: Updated post {POST_ID}.
"""

When I run `wp post get {POST_ID} --field=post_modified_gmt`
Then STDOUT should be:
"""
2020-06-01 12:00:00
"""

# June is inside DST, so the offset is four hours rather than five.
When I run `wp post get {POST_ID} --field=post_modified`
Then STDOUT should be:
"""
2020-06-01 08:00:00
"""
83 changes: 83 additions & 0 deletions features/user.feature
Original file line number Diff line number Diff line change
Expand Up @@ -811,3 +811,86 @@ Feature: Manage WordPress users
"""
newtestuser
"""

Scenario: Create a user with a nicename and rich editing preference
Given a WP install

When I run `wp user create bob bob@example.com --user_nicename=bobby --rich_editing=false --porcelain`
Then STDOUT should be a number
And save STDOUT as {USER_ID}

When I run `wp user get {USER_ID} --field=user_nicename`
Then STDOUT should be:
"""
bobby
"""

When I run `wp user meta get {USER_ID} rich_editing`
Then STDOUT should be:
"""
false
"""

Scenario: Creating a user without a nicename falls back to the login
Given a WP install

When I run `wp user create carol carol@example.com --porcelain`
Then STDOUT should be a number
And save STDOUT as {USER_ID}

When I run `wp user get {USER_ID} --field=user_nicename`
Then STDOUT should be:
"""
carol
"""

When I run `wp user meta get {USER_ID} rich_editing`
Then STDOUT should be:
"""
true
"""
Comment thread
swissspidy marked this conversation as resolved.

# Multisite creates the user through wpmu_create_user(), which takes only a
# login, a password and an email, and then applies the rest with
# wp_update_user(). That is a different path to wp_insert_user(), so both
# fields are worth asserting again here.
Scenario: Create a user with a nicename and rich editing preference on multisite
Given a WP multisite install

# Multisite requires a login of at least four characters, and a login that
# differs from the nicename shows the nicename was applied rather than
# derived.
When I run `wp user create robert robert@example.com --user_nicename=bobby --rich_editing=false --porcelain`
Then STDOUT should be a number
And save STDOUT as {USER_ID}

When I run `wp user get {USER_ID} --field=user_nicename`
Then STDOUT should be:
"""
bobby
"""

When I run `wp user meta get {USER_ID} rich_editing`
Then STDOUT should be:
"""
false
"""

Scenario: Creating a user without a nicename falls back to the login on multisite
Given a WP multisite install

When I run `wp user create carol carol@example.com --porcelain`
Then STDOUT should be a number
And save STDOUT as {USER_ID}

When I run `wp user get {USER_ID} --field=user_nicename`
Then STDOUT should be:
"""
carol
"""

When I run `wp user meta get {USER_ID} rich_editing`
Then STDOUT should be:
"""
true
"""
59 changes: 59 additions & 0 deletions src/Post_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ public function create( $args, $assoc_args ) {
$post_id = $post_arr['ID'];
unset( $post_arr['post_date'] );
unset( $post_arr['post_date_gmt'] );
unset( $post_arr['post_modified'] );
unset( $post_arr['post_modified_gmt'] );
unset( $post_arr['guid'] );
unset( $post_arr['ID'] );

Expand Down Expand Up @@ -249,8 +251,14 @@ function ( $params ) {
}
}

$modified_callback = self::add_post_modified_filter( $params );

$result = wp_insert_post( $params, true );

if ( $modified_callback ) {
remove_filter( 'wp_insert_post_data', $modified_callback );
}

if ( $filter_callback ) {
remove_filter( 'user_has_cap', $filter_callback );
}
Expand All @@ -260,6 +268,51 @@ function ( $params ) {
);
}

/**
* Applies an explicitly requested modification date.
*
* wp_insert_post() derives post_modified and post_modified_gmt itself and
* never reads them back from $postarr — on update they are unconditionally
* the current time — so the documented parameters have to be applied to the
* post data on its way to the database.
*
* @param array<string, mixed> $params Parameters passed to wp_insert_post() or wp_update_post().
* @return callable|null The registered callback, for the caller to remove, or null when
* no modification date was requested.
*/
private static function add_post_modified_filter( $params ) {
$local = ! empty( $params['post_modified'] ) && is_scalar( $params['post_modified'] )
? (string) $params['post_modified']
: null;
$gmt = ! empty( $params['post_modified_gmt'] ) && is_scalar( $params['post_modified_gmt'] )
? (string) $params['post_modified_gmt']
: null;

if ( null === $local && null === $gmt ) {
return null;
}

// Keep the pair consistent when only one of the two was given.
if ( null === $gmt ) {
$gmt = get_gmt_from_date( $local );
} elseif ( null === $local ) {
$local = get_date_from_gmt( $gmt );
}

$modified = [
'post_modified' => $local,
'post_modified_gmt' => $gmt,
];

$callback = static function ( $data ) use ( $modified ) {
return array_merge( $data, $modified );
};

add_filter( 'wp_insert_post_data', $callback );

return $callback;
}

/**
* Updates one or more existing posts.
*
Expand Down Expand Up @@ -432,8 +485,14 @@ function ( $params ) {
}
}

$modified_callback = self::add_post_modified_filter( $params );

$result = wp_update_post( $params, true );

if ( $modified_callback ) {
remove_filter( 'wp_insert_post_data', $modified_callback );
}

if ( $filter_callback ) {
remove_filter( 'user_has_cap', $filter_callback );
}
Expand Down
4 changes: 4 additions & 0 deletions src/User_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,10 @@ public function create( $args, $assoc_args ) {

$user->user_url = Utils\get_flag_value( $assoc_args, 'user_url', false );

$user->user_nicename = Utils\get_flag_value( $assoc_args, 'user_nicename', false );

$user->rich_editing = Utils\get_flag_value( $assoc_args, 'rich_editing', false );

if ( isset( $assoc_args['user_pass'] ) ) {
$user->user_pass = $assoc_args['user_pass'];
} else {
Expand Down