diff --git a/src/wp-includes/IXR/class-IXR-date.php b/src/wp-includes/IXR/class-IXR-date.php
index fc80cda4a1f26..53903acb79042 100644
--- a/src/wp-includes/IXR/class-IXR-date.php
+++ b/src/wp-includes/IXR/class-IXR-date.php
@@ -57,16 +57,33 @@ function parseIso($iso)
$this->timezone = substr($iso, 17);
}
- function getIso()
+ /**
+ * Gets the datetime in ISO format.
+ *
+ * @return string ISO datetime.
+ * @phpstan-return non-falsy-string
+ */
+ function getIso(): string
{
return $this->year.$this->month.$this->day.'T'.$this->hour.':'.$this->minute.':'.$this->second.$this->timezone;
}
- function getXml()
+ /**
+ * Gets the `dateTime.iso8601` XML tag.
+ *
+ * @return string A dateTime.iso8601 XML tag.
+ * @phpstan-return non-falsy-string
+ */
+ function getXml(): string
{
return ''.$this->getIso().'';
}
+ /**
+ * Gets the timestamp.
+ *
+ * @return int|false Timestamp, or false on error.
+ */
function getTimestamp()
{
return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year);
diff --git a/src/wp-includes/class-wp-xmlrpc-server.php b/src/wp-includes/class-wp-xmlrpc-server.php
index 1a0a46262254a..9d955f453997a 100644
--- a/src/wp-includes/class-wp-xmlrpc-server.php
+++ b/src/wp-includes/class-wp-xmlrpc-server.php
@@ -827,6 +827,25 @@ protected function _is_fields_array( $fields ): bool {
return true;
}
+ /**
+ * Checks that the content struct argument received from a client is an associative array.
+ *
+ * @since 7.2.0
+ *
+ * @param mixed $content_struct The content struct argument to check.
+ * @return bool True if `$content_struct` is an associative array, false otherwise.
+ *
+ * @phpstan-assert-if-true array $content_struct
+ */
+ protected function _is_content_struct_array( $content_struct ): bool {
+ if ( ! is_array( $content_struct ) || wp_is_numeric_array( $content_struct ) ) {
+ $this->error = new IXR_Error( 400, __( 'The content struct argument must be an associative array.' ) );
+ return false;
+ }
+
+ return true;
+ }
+
/**
* Prepares taxonomy data for return in an XML-RPC object.
*
@@ -910,11 +929,13 @@ protected function _prepare_term( $term ) {
/**
* Converts a WordPress date string to an IXR_Date object.
*
+ * @since 7.2.0 A value that is not a string is treated as an empty date.
+ *
* @param string $date Date string to convert.
* @return IXR_Date IXR_Date object.
*/
protected function _convert_date( $date ) {
- if ( '0000-00-00 00:00:00' === $date ) {
+ if ( ! is_string( $date ) || '0000-00-00 00:00:00' === $date ) {
return new IXR_Date( '00000000T00:00:00Z' );
}
return new IXR_Date( mysql2date( 'Ymd\TH:i:s', $date, false ) );
@@ -928,12 +949,38 @@ protected function _convert_date( $date ) {
* @return IXR_Date IXR_Date object.
*/
protected function _convert_date_gmt( $date_gmt, $date ) {
- if ( '0000-00-00 00:00:00' !== $date && '0000-00-00 00:00:00' === $date_gmt ) {
+ if ( is_string( $date ) && '0000-00-00 00:00:00' !== $date && '0000-00-00 00:00:00' === $date_gmt ) {
return new IXR_Date( get_gmt_from_date( mysql2date( 'Y-m-d H:i:s', $date, false ), 'Ymd\TH:i:s' ) );
}
return $this->_convert_date( $date_gmt );
}
+ /**
+ * Converts a client-supplied date value to an IXR_Date object.
+ *
+ * XML-RPC clients may send a date either as a dateTime.iso8601 value, which
+ * arrives as an IXR_Date object, or as a plain string. Any other type cannot
+ * be a date and results in an error.
+ *
+ * @since 7.2.0
+ *
+ * @param mixed $date Client-supplied date value.
+ * @return IXR_Date|IXR_Error IXR_Date object on success, IXR_Error if the value is not a date.
+ *
+ * @phpstan-return ( $date is IXR_Date|string ? IXR_Date : IXR_Error )
+ */
+ protected function _convert_client_date( $date ) {
+ if ( $date instanceof IXR_Date ) {
+ return $date;
+ }
+
+ if ( is_string( $date ) ) {
+ return $this->_convert_date( $date );
+ }
+
+ return new IXR_Error( 400, __( 'Dates must be a dateTime.iso8601 value or a string.' ) );
+ }
+
/**
* Prepares post data for return in an XML-RPC object.
*
@@ -1305,6 +1352,7 @@ protected function _prepare_user( $user, $fields ) {
* Creates a new post for any registered post type.
*
* @since 3.4.0
+ * @since 7.2.0 Returns an error if the content struct argument is not an array.
*
* @link https://en.wikipedia.org/wiki/RSS_enclosure for information on RSS enclosures.
*
@@ -1359,13 +1407,17 @@ public function wp_newPost( $args ) {
$password = $args[2];
$content_struct = $args[3];
+ if ( ! $this->_is_content_struct_array( $content_struct ) ) {
+ return $this->error;
+ }
+
$user = $this->login( $username, $password );
if ( ! $user ) {
return $this->error;
}
// Convert the date field back to IXR form.
- if ( isset( $content_struct['post_date'] ) && ! ( $content_struct['post_date'] instanceof IXR_Date ) ) {
+ if ( isset( $content_struct['post_date'] ) && is_string( $content_struct['post_date'] ) ) {
$content_struct['post_date'] = $this->_convert_date( $content_struct['post_date'] );
}
@@ -1373,7 +1425,7 @@ public function wp_newPost( $args ) {
* Ignore the existing GMT date if it is empty or a non-GMT date was supplied in $content_struct,
* since _insert_post() will ignore the non-GMT date if the GMT date is set.
*/
- if ( isset( $content_struct['post_date_gmt'] ) && ! ( $content_struct['post_date_gmt'] instanceof IXR_Date ) ) {
+ if ( isset( $content_struct['post_date_gmt'] ) && is_string( $content_struct['post_date_gmt'] ) ) {
if ( '0000-00-00 00:00:00' === $content_struct['post_date_gmt'] || isset( $content_struct['post_date'] ) ) {
unset( $content_struct['post_date_gmt'] );
} else {
@@ -1577,10 +1629,20 @@ protected function _insert_post( $user, $content_struct ) {
// Do some timestamp voodoo.
if ( ! empty( $post_data['post_date_gmt'] ) ) {
+ $post_date_gmt = $this->_convert_client_date( $post_data['post_date_gmt'] );
+ if ( $post_date_gmt instanceof IXR_Error ) {
+ return $post_date_gmt;
+ }
+
// We know this is supposed to be GMT, so we're going to slap that Z on there by force.
- $date_created = rtrim( $post_data['post_date_gmt']->getIso(), 'Z' ) . 'Z';
+ $date_created = rtrim( $post_date_gmt->getIso(), 'Z' ) . 'Z';
} elseif ( ! empty( $post_data['post_date'] ) ) {
- $date_created = $post_data['post_date']->getIso();
+ $post_date = $this->_convert_client_date( $post_data['post_date'] );
+ if ( $post_date instanceof IXR_Error ) {
+ return $post_date;
+ }
+
+ $date_created = $post_date->getIso();
}
// Default to not flagging the post date to be edited unless it's intentional.
@@ -1780,6 +1842,7 @@ static function ( $value ) {
* should be changed. All other fields will retain their existing values.
*
* @since 3.4.0
+ * @since 7.2.0 Returns an error if the content struct argument is not an array.
*
* @param array $args {
* Method arguments. Note: arguments must be ordered as documented.
@@ -1804,6 +1867,10 @@ public function wp_editPost( $args ) {
$post_id = (int) $args[3];
$content_struct = $args[4];
+ if ( ! $this->_is_content_struct_array( $content_struct ) ) {
+ return $this->error;
+ }
+
$user = $this->login( $username, $password );
if ( ! $user ) {
return $this->error;
@@ -1819,8 +1886,18 @@ public function wp_editPost( $args ) {
}
if ( isset( $content_struct['if_not_modified_since'] ) ) {
+ $if_not_modified_since = $this->_convert_client_date( $content_struct['if_not_modified_since'] );
+ if ( $if_not_modified_since instanceof IXR_Error ) {
+ return $if_not_modified_since;
+ }
+
+ $post_modified_timestamp = false;
+ if ( is_string( $post['post_modified_gmt'] ) ) {
+ $post_modified_timestamp = mysql2date( 'U', $post['post_modified_gmt'] );
+ }
+
// If the post has been modified since the date provided, return an error.
- if ( mysql2date( 'U', $post['post_modified_gmt'] ) > $content_struct['if_not_modified_since']->getTimestamp() ) {
+ if ( false !== $post_modified_timestamp && $post_modified_timestamp > $if_not_modified_since->getTimestamp() ) {
return new IXR_Error( 409, __( 'There is a revision of this post that is more recent.' ) );
}
}
@@ -3888,6 +3965,7 @@ public function wp_deleteComment( $args ) {
* - 'status'. Common statuses are 'approve', 'hold', 'spam'. See get_comment_statuses() for more details.
*
* @since 2.7.0
+ * @since 7.2.0 Returns an error if the content struct argument is not an array.
*
* @param array $args {
* Method arguments. Note: arguments must be ordered as documented.
@@ -3908,6 +3986,10 @@ public function wp_editComment( $args ) {
$comment_id = (int) $args[3];
$content_struct = $args[4];
+ if ( ! $this->_is_content_struct_array( $content_struct ) ) {
+ return $this->error;
+ }
+
$user = $this->login( $username, $password );
if ( ! $user ) {
return $this->error;
@@ -3940,8 +4022,13 @@ public function wp_editComment( $args ) {
// Do some timestamp voodoo.
if ( ! empty( $content_struct['date_created_gmt'] ) ) {
+ $date_created_gmt = $this->_convert_client_date( $content_struct['date_created_gmt'] );
+ if ( $date_created_gmt instanceof IXR_Error ) {
+ return $date_created_gmt;
+ }
+
// We know this is supposed to be GMT, so we're going to slap that Z on there by force.
- $date_created = rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z';
+ $date_created = rtrim( $date_created_gmt->getIso(), 'Z' ) . 'Z';
$comment['comment_date'] = get_date_from_gmt( $date_created );
$comment['comment_date_gmt'] = iso8601_to_datetime( $date_created, 'gmt' );
@@ -5465,6 +5552,7 @@ public function blogger_deletePost( $args ) {
* - wp_post_thumbnail
*
* @since 1.5.0
+ * @since 7.2.0 Returns an error if the content struct argument is not an array.
*
* @param array $args {
* Method arguments. Note: arguments must be ordered as documented.
@@ -5485,6 +5573,10 @@ public function mw_newPost( $args ) {
$content_struct = $args[3];
$publish = $args[4] ?? 0;
+ if ( ! $this->_is_content_struct_array( $content_struct ) ) {
+ return $this->error;
+ }
+
$user = $this->login( $username, $password );
if ( ! $user ) {
return $this->error;
@@ -5698,10 +5790,20 @@ public function mw_newPost( $args ) {
// Do some timestamp voodoo.
if ( ! empty( $content_struct['date_created_gmt'] ) ) {
+ $date_created_gmt = $this->_convert_client_date( $content_struct['date_created_gmt'] );
+ if ( $date_created_gmt instanceof IXR_Error ) {
+ return $date_created_gmt;
+ }
+
// We know this is supposed to be GMT, so we're going to slap that Z on there by force.
- $date_created = rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z';
+ $date_created = rtrim( $date_created_gmt->getIso(), 'Z' ) . 'Z';
} elseif ( ! empty( $content_struct['dateCreated'] ) ) {
- $date_created = $content_struct['dateCreated']->getIso();
+ $date_created_object = $this->_convert_client_date( $content_struct['dateCreated'] );
+ if ( $date_created_object instanceof IXR_Error ) {
+ return $date_created_object;
+ }
+
+ $date_created = $date_created_object->getIso();
}
$post_date = '';
@@ -5860,6 +5962,7 @@ public function attach_uploads( $post_id, $post_content ) {
* Edits a post.
*
* @since 1.5.0
+ * @since 7.2.0 Returns an error if the content struct argument is not an array.
*
* @param array $args {
* Method arguments. Note: arguments must be ordered as documented.
@@ -5881,6 +5984,10 @@ public function mw_editPost( $args ) {
$content_struct = $args[3];
$publish = $args[4] ?? 0;
+ if ( ! $this->_is_content_struct_array( $content_struct ) ) {
+ return $this->error;
+ }
+
$user = $this->login( $username, $password );
if ( ! $user ) {
return $this->error;
@@ -6104,10 +6211,20 @@ public function mw_editPost( $args ) {
// Do some timestamp voodoo.
if ( ! empty( $content_struct['date_created_gmt'] ) ) {
+ $date_created_gmt = $this->_convert_client_date( $content_struct['date_created_gmt'] );
+ if ( $date_created_gmt instanceof IXR_Error ) {
+ return $date_created_gmt;
+ }
+
// We know this is supposed to be GMT, so we're going to slap that Z on there by force.
- $date_created = rtrim( $content_struct['date_created_gmt']->getIso(), 'Z' ) . 'Z';
+ $date_created = rtrim( $date_created_gmt->getIso(), 'Z' ) . 'Z';
} elseif ( ! empty( $content_struct['dateCreated'] ) ) {
- $date_created = $content_struct['dateCreated']->getIso();
+ $date_created_object = $this->_convert_client_date( $content_struct['dateCreated'] );
+ if ( $date_created_object instanceof IXR_Error ) {
+ return $date_created_object;
+ }
+
+ $date_created = $date_created_object->getIso();
}
// Default to not flagging the post date to be edited unless it's intentional.
diff --git a/tests/phpunit/tests/xmlrpc/mw/editPost.php b/tests/phpunit/tests/xmlrpc/mw/editPost.php
index 23515233325ff..4e9a264f6128b 100644
--- a/tests/phpunit/tests/xmlrpc/mw/editPost.php
+++ b/tests/phpunit/tests/xmlrpc/mw/editPost.php
@@ -335,4 +335,30 @@ public function test_draft_not_prematurely_published() {
$future_date_string = date_format( date_create( "@{$future_time}" ), 'Y-m-d H:i:s' );
$this->assertSame( $future_date_string, $after->post_date );
}
+
+ /**
+ * @ticket 66107
+ */
+ public function test_string_date_created_is_accepted(): void {
+ $editor_id = $this->make_user_by_role( 'editor' );
+ $post_id = self::factory()->post->create( array( 'post_author' => $editor_id ) );
+
+ $date_string = '1984-01-11 05:00:00';
+ $result = $this->myxmlrpcserver->mw_editPost( array( $post_id, 'editor', 'editor', array( 'dateCreated' => $date_string ) ) );
+ $this->assertNotIXRError( $result );
+ $this->assertTrue( $result );
+ $this->assertSame( $date_string, get_post( $post_id )->post_date );
+ }
+
+ /**
+ * @ticket 66107
+ */
+ public function test_non_array_content_struct_returns_error(): void {
+ $editor_id = $this->make_user_by_role( 'editor' );
+ $post_id = self::factory()->post->create( array( 'post_author' => $editor_id ) );
+
+ $result = $this->myxmlrpcserver->mw_editPost( array( $post_id, 'editor', 'editor', 'not a struct' ) );
+ $this->assertIXRError( $result );
+ $this->assertSame( 400, $result->code );
+ }
}
diff --git a/tests/phpunit/tests/xmlrpc/mw/newPost.php b/tests/phpunit/tests/xmlrpc/mw/newPost.php
index e7c4af0cee01f..924bec51d0e96 100644
--- a/tests/phpunit/tests/xmlrpc/mw/newPost.php
+++ b/tests/phpunit/tests/xmlrpc/mw/newPost.php
@@ -201,4 +201,31 @@ public function test_draft_post_date() {
$this->assertSame( 'draft', $out->post_status );
$this->assertSame( '0000-00-00 00:00:00', $out->post_date_gmt );
}
+
+ /**
+ * @ticket 66107
+ */
+ public function test_string_date_created_is_accepted(): void {
+ $this->make_user_by_role( 'author' );
+
+ $date_string = '1984-01-11 05:00:00';
+ $post = array(
+ 'title' => 'Test',
+ 'dateCreated' => $date_string,
+ );
+ $result = $this->myxmlrpcserver->mw_newPost( array( 1, 'author', 'author', $post ) );
+ $this->assertNotIXRError( $result );
+ $this->assertSame( $date_string, get_post( $result )->post_date );
+ }
+
+ /**
+ * @ticket 66107
+ */
+ public function test_non_array_content_struct_returns_error(): void {
+ $this->make_user_by_role( 'author' );
+
+ $result = $this->myxmlrpcserver->mw_newPost( array( 1, 'author', 'author', 'not a struct' ) );
+ $this->assertIXRError( $result );
+ $this->assertSame( 400, $result->code );
+ }
}
diff --git a/tests/phpunit/tests/xmlrpc/wp/editComment.php b/tests/phpunit/tests/xmlrpc/wp/editComment.php
index 0f998df96707a..d355e85ef2a30 100644
--- a/tests/phpunit/tests/xmlrpc/wp/editComment.php
+++ b/tests/phpunit/tests/xmlrpc/wp/editComment.php
@@ -93,4 +93,33 @@ public function test_trash_comment() {
$this->assertSame( 'trash', get_comment( $comment_id )->comment_approved );
}
+
+ /**
+ * @ticket 66107
+ * @ticket 42995
+ */
+ public function test_string_date_created_gmt_is_accepted(): void {
+ $this->make_user_by_role( 'administrator' );
+ $comment_id = self::factory()->comment->create();
+
+ $date_string = '1984-01-11 05:00:00';
+ $result = $this->myxmlrpcserver->wp_editComment(
+ array( 1, 'administrator', 'administrator', $comment_id, array( 'date_created_gmt' => $date_string ) )
+ );
+ $this->assertNotIXRError( $result );
+ $this->assertTrue( $result );
+ $this->assertSame( $date_string, get_comment( $comment_id )->comment_date_gmt );
+ }
+
+ /**
+ * @ticket 66107
+ */
+ public function test_non_array_content_struct_returns_error(): void {
+ $this->make_user_by_role( 'administrator' );
+ $comment_id = self::factory()->comment->create();
+
+ $result = $this->myxmlrpcserver->wp_editComment( array( 1, 'administrator', 'administrator', $comment_id, 'not a struct' ) );
+ $this->assertIXRError( $result );
+ $this->assertSame( 400, $result->code );
+ }
}
diff --git a/tests/phpunit/tests/xmlrpc/wp/editPost.php b/tests/phpunit/tests/xmlrpc/wp/editPost.php
index dacd64573a6d5..85fbd7a8033e5 100644
--- a/tests/phpunit/tests/xmlrpc/wp/editPost.php
+++ b/tests/phpunit/tests/xmlrpc/wp/editPost.php
@@ -528,4 +528,98 @@ public function test_draft_not_assigned_published_date() {
$after = get_post( $post_id );
$this->assertSame( '0000-00-00 00:00:00', $after->post_date_gmt );
}
+
+ /**
+ * @ticket 66107
+ */
+ public function test_string_post_date_is_accepted(): void {
+ $editor_id = $this->make_user_by_role( 'editor' );
+ $post_id = self::factory()->post->create( array( 'post_author' => $editor_id ) );
+
+ $date_string = '1984-01-11 05:00:00';
+ $result = $this->myxmlrpcserver->wp_editPost( array( 1, 'editor', 'editor', $post_id, array( 'post_date' => $date_string ) ) );
+ $this->assertNotIXRError( $result );
+ $this->assertTrue( $result );
+ $this->assertSame( $date_string, get_post( $post_id )->post_date );
+ }
+
+ /**
+ * @ticket 66107
+ */
+ public function test_string_post_date_gmt_is_accepted(): void {
+ $editor_id = $this->make_user_by_role( 'editor' );
+ $post_id = self::factory()->post->create( array( 'post_author' => $editor_id ) );
+
+ $date_string = '1984-01-11 05:00:00';
+ $result = $this->myxmlrpcserver->wp_editPost( array( 1, 'editor', 'editor', $post_id, array( 'post_date_gmt' => $date_string ) ) );
+ $this->assertNotIXRError( $result );
+ $this->assertTrue( $result );
+ $this->assertSame( $date_string, get_post( $post_id )->post_date_gmt );
+ }
+
+ /**
+ * @ticket 66107
+ */
+ public function test_string_if_not_modified_since_is_accepted(): void {
+ $editor_id = $this->make_user_by_role( 'editor' );
+ $post_id = self::factory()->post->create( array( 'post_author' => $editor_id ) );
+
+ $struct = array(
+ 'post_title' => 'Updated',
+ 'if_not_modified_since' => gmdate( 'Y-m-d H:i:s', strtotime( '+1 day' ) ),
+ );
+ $result = $this->myxmlrpcserver->wp_editPost( array( 1, 'editor', 'editor', $post_id, $struct ) );
+ $this->assertNotIXRError( $result );
+ $this->assertTrue( $result );
+ $this->assertSame( 'Updated', get_post( $post_id )->post_title );
+ }
+
+ /**
+ * @ticket 66107
+ */
+ public function test_non_date_post_date_returns_error(): void {
+ $editor_id = $this->make_user_by_role( 'editor' );
+ $post_id = self::factory()->post->create( array( 'post_author' => $editor_id ) );
+
+ $struct = array( 'post_date' => array( '1984-01-11 05:00:00' ) );
+ $result = $this->myxmlrpcserver->wp_editPost( array( 1, 'editor', 'editor', $post_id, $struct ) );
+ $this->assertIXRError( $result );
+ $this->assertSame( 400, $result->code );
+ }
+
+ /**
+ * @ticket 66107
+ */
+ public function test_non_array_content_struct_returns_error(): void {
+ $editor_id = $this->make_user_by_role( 'editor' );
+ $post_id = self::factory()->post->create( array( 'post_author' => $editor_id ) );
+
+ $result = $this->myxmlrpcserver->wp_editPost( array( 1, 'editor', 'editor', $post_id, 'not a struct' ) );
+ $this->assertIXRError( $result );
+ $this->assertSame( 400, $result->code );
+ }
+
+ /**
+ * Ensure a stored modified date that is not a string skips the `if_not_modified_since` check
+ * instead of causing a fatal error.
+ *
+ * @ticket 66107
+ */
+ public function test_non_string_stored_modified_date_skips_if_not_modified_since(): void {
+ $editor_id = $this->make_user_by_role( 'editor' );
+ $post_id = self::factory()->post->create( array( 'post_author' => $editor_id ) );
+
+ $cached_post = (object) get_object_vars( get_post( $post_id ) );
+ $cached_post->post_modified_gmt = array( 'not a date' );
+ wp_cache_set( $post_id, $cached_post, 'posts' );
+
+ $struct = array(
+ 'post_title' => 'Updated',
+ 'if_not_modified_since' => new IXR_Date( time() ),
+ );
+ $result = $this->myxmlrpcserver->wp_editPost( array( 1, 'editor', 'editor', $post_id, $struct ) );
+
+ $this->assertTrue( $result );
+ $this->assertSame( 'Updated', get_post( $post_id )->post_title );
+ }
}
diff --git a/tests/phpunit/tests/xmlrpc/wp/getPost.php b/tests/phpunit/tests/xmlrpc/wp/getPost.php
index 8f2e28b5fd6ae..050e45b58ab96 100644
--- a/tests/phpunit/tests/xmlrpc/wp/getPost.php
+++ b/tests/phpunit/tests/xmlrpc/wp/getPost.php
@@ -159,4 +159,26 @@ public function test_non_array_fields_returns_error(): void {
$this->assertIXRError( $result );
$this->assertSame( 400, $result->code );
}
+
+ /**
+ * Ensure a stored date that is not a string is returned as an empty date instead of causing a fatal error.
+ *
+ * @ticket 66107
+ */
+ public function test_non_string_stored_date_returns_empty_date(): void {
+ /*
+ * A non-string date with an empty GMT date reaches both _convert_date()
+ * and the local date fallback in _convert_date_gmt().
+ */
+ $cached_post = (object) get_object_vars( get_post( $this->post_id ) );
+ $cached_post->post_modified = array( 'not a date' );
+ $cached_post->post_modified_gmt = '0000-00-00 00:00:00';
+ wp_cache_set( $this->post_id, $cached_post, 'posts' );
+
+ $result = $this->myxmlrpcserver->wp_getPost( array( 1, 'author', 'author', $this->post_id, array( 'post' ) ) );
+
+ $this->assertNotIXRError( $result );
+ $this->assertSame( '00000000T00:00:00Z', $result['post_modified']->getIso() );
+ $this->assertSame( '00000000T00:00:00Z', $result['post_modified_gmt']->getIso() );
+ }
}
diff --git a/tests/phpunit/tests/xmlrpc/wp/newPost.php b/tests/phpunit/tests/xmlrpc/wp/newPost.php
index c6386a1f23d5b..28053415915aa 100644
--- a/tests/phpunit/tests/xmlrpc/wp/newPost.php
+++ b/tests/phpunit/tests/xmlrpc/wp/newPost.php
@@ -446,4 +446,30 @@ public function test_valid_IXR_post_date_gmt() {
$this->assertStringMatchesFormat( '%d', $result );
$this->assertSame( $date_string, $fetched_post->post_date_gmt );
}
+
+ /**
+ * @ticket 66107
+ */
+ public function test_non_date_post_date_returns_error(): void {
+ $this->make_user_by_role( 'author' );
+
+ $post = array(
+ 'post_title' => 'test',
+ 'post_date' => array( '1984-01-11 05:00:00' ),
+ );
+ $result = $this->myxmlrpcserver->wp_newPost( array( 1, 'author', 'author', $post ) );
+ $this->assertIXRError( $result );
+ $this->assertSame( 400, $result->code );
+ }
+
+ /**
+ * @ticket 66107
+ */
+ public function test_non_array_content_struct_returns_error(): void {
+ $this->make_user_by_role( 'author' );
+
+ $result = $this->myxmlrpcserver->wp_newPost( array( 1, 'author', 'author', 'not a struct' ) );
+ $this->assertIXRError( $result );
+ $this->assertSame( 400, $result->code );
+ }
}