Skip to content

Commit 57a4744

Browse files
authored
Merge branch 'WordPress:trunk' into trunk
2 parents dc99d30 + 1325dea commit 57a4744

4 files changed

Lines changed: 111 additions & 7 deletions

File tree

src/wp-admin/edit-form-comment.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,12 +221,15 @@
221221
if ( $comment_threading_enabled ) {
222222
$max_thread_depth = (int) get_option( 'thread_comments_depth' );
223223

224+
// Pending comments may be nested under pending parents, but approved comments require publicly visible parents.
225+
$parent_statuses = '1' === $comment->comment_approved ? 'approve' : array( 'approve', 'hold' );
226+
224227
// Limit the number of comments to keep memory usage and the size of the dropdown reasonable on busy posts.
225228
$post_comments = get_comments(
226229
array(
227230
'post_id' => $comment->comment_post_ID,
228231
'type' => 'comment',
229-
'status' => array( 'approve', 'hold' ),
232+
'status' => $parent_statuses,
230233
'orderby' => 'comment_date_gmt',
231234
'order' => 'DESC',
232235
'number' => 100,

src/wp-admin/includes/comment.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,18 @@ function edit_comment() {
9292
return new WP_Error( 'comment_parent_invalid', __( 'A comment cannot be a reply to itself.' ) );
9393
}
9494

95-
$parent = get_comment( $comment_parent );
95+
$parent = get_comment( $comment_parent );
96+
$parent_status = $parent ? wp_get_comment_status( $parent ) : false;
97+
$comment_status = $_POST['comment_approved'] ?? $comment->comment_approved;
98+
$comment_is_approved = in_array( $comment_status, array( 1, '1', 'approve' ), true );
9699

97-
// The parent must be a comment of the same type, on the same post, and not in the Trash or marked as spam.
100+
// The parent must be a comment of the same type, on the same post, and publicly visible if the comment is approved.
98101
if (
99102
! $parent
100103
|| (int) $parent->comment_post_ID !== (int) $comment->comment_post_ID
101104
|| $parent->comment_type !== $comment->comment_type
102-
|| in_array( wp_get_comment_status( $parent ), array( 'spam', 'trash' ), true )
105+
|| in_array( $parent_status, array( 'spam', 'trash' ), true )
106+
|| ( $comment_is_approved && 'approved' !== $parent_status )
103107
) {
104108
return new WP_Error( 'comment_parent_invalid', __( 'Invalid parent comment.' ) );
105109
}

tests/phpunit/tests/admin/EditFormComment_Test.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ public function test_should_list_valid_parents_and_exclude_invalid_ones() {
9696
'comment_approved' => 'trash',
9797
)
9898
);
99+
$pending_id = self::factory()->comment->create(
100+
array(
101+
'comment_post_ID' => self::$post_id,
102+
'comment_approved' => '0',
103+
)
104+
);
99105
$comment_id = self::factory()->comment->create( array( 'comment_post_ID' => self::$post_id ) );
100106
$child_id = self::factory()->comment->create(
101107
array(
@@ -113,6 +119,29 @@ public function test_should_list_valid_parents_and_exclude_invalid_ones() {
113119
$this->assertStringNotContainsString( "value='{$child_id}'", $dropdown, 'A reply to the comment being edited should not be listed.' );
114120
$this->assertStringNotContainsString( "value='{$spam_id}'", $dropdown, 'A spam comment should not be listed.' );
115121
$this->assertStringNotContainsString( "value='{$trash_id}'", $dropdown, 'A trashed comment should not be listed.' );
122+
$this->assertStringNotContainsString( "value='{$pending_id}'", $dropdown, 'A pending comment should not be listed for an approved comment.' );
123+
}
124+
125+
/**
126+
* @ticket 65688
127+
*/
128+
public function test_should_list_pending_parent_for_pending_comment() {
129+
$parent_id = self::factory()->comment->create(
130+
array(
131+
'comment_post_ID' => self::$post_id,
132+
'comment_approved' => '0',
133+
)
134+
);
135+
$comment_id = self::factory()->comment->create(
136+
array(
137+
'comment_post_ID' => self::$post_id,
138+
'comment_approved' => '0',
139+
)
140+
);
141+
142+
$dropdown = $this->get_parent_dropdown( $comment_id );
143+
144+
$this->assertStringContainsString( "value='{$parent_id}'", $dropdown, 'A pending comment should be listed for another pending comment.' );
116145
}
117146

118147
/**

tests/phpunit/tests/admin/includes/comment/EditComment_Test.php

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,21 @@ public function tear_down() {
4949
/**
5050
* Calls edit_comment() with a comment ID and a new parent, as submitted from the Edit Comment screen.
5151
*
52-
* @param int $comment_id Comment ID.
53-
* @param int $comment_parent New parent comment ID.
52+
* @param int $comment_id Comment ID.
53+
* @param int $comment_parent New parent comment ID.
54+
* @param string|null $comment_status Optional. New comment status.
5455
* @return int|WP_Error The edit_comment() return value.
5556
*/
56-
private function update_comment_parent( $comment_id, $comment_parent ) {
57+
private function update_comment_parent( $comment_id, $comment_parent, $comment_status = null ) {
5758
$_POST = array(
5859
'comment_ID' => $comment_id,
5960
'comment_parent' => $comment_parent,
6061
);
6162

63+
if ( null !== $comment_status ) {
64+
$_POST['comment_status'] = $comment_status;
65+
}
66+
6267
return edit_comment();
6368
}
6469

@@ -75,6 +80,69 @@ public function test_should_update_comment_parent() {
7580
$this->assertSame( (string) $parent_id, get_comment( $comment_id )->comment_parent );
7681
}
7782

83+
/**
84+
* @ticket 65688
85+
*/
86+
public function test_should_reject_unapproved_parent_for_approved_comment() {
87+
$parent_id = self::factory()->comment->create(
88+
array(
89+
'comment_post_ID' => self::$post_id,
90+
'comment_approved' => '0',
91+
)
92+
);
93+
$comment_id = self::factory()->comment->create( array( 'comment_post_ID' => self::$post_id ) );
94+
95+
$result = $this->update_comment_parent( $comment_id, $parent_id );
96+
97+
$this->assertWPError( $result );
98+
$this->assertSame( 'comment_parent_invalid', $result->get_error_code() );
99+
$this->assertSame( '0', get_comment( $comment_id )->comment_parent );
100+
}
101+
102+
/**
103+
* @ticket 65688
104+
*/
105+
public function test_should_reject_unapproved_parent_when_comment_is_approved_in_same_update() {
106+
$parent_id = self::factory()->comment->create(
107+
array(
108+
'comment_post_ID' => self::$post_id,
109+
'comment_approved' => '0',
110+
)
111+
);
112+
$comment_id = self::factory()->comment->create(
113+
array(
114+
'comment_post_ID' => self::$post_id,
115+
'comment_approved' => '0',
116+
)
117+
);
118+
119+
$result = $this->update_comment_parent( $comment_id, $parent_id, '1' );
120+
121+
$this->assertWPError( $result );
122+
$this->assertSame( 'comment_parent_invalid', $result->get_error_code() );
123+
$this->assertSame( '0', get_comment( $comment_id )->comment_approved );
124+
$this->assertSame( '0', get_comment( $comment_id )->comment_parent );
125+
}
126+
127+
/**
128+
* @ticket 65688
129+
*/
130+
public function test_should_allow_unapproved_parent_when_comment_is_unapproved_in_same_update() {
131+
$parent_id = self::factory()->comment->create(
132+
array(
133+
'comment_post_ID' => self::$post_id,
134+
'comment_approved' => '0',
135+
)
136+
);
137+
$comment_id = self::factory()->comment->create( array( 'comment_post_ID' => self::$post_id ) );
138+
139+
$result = $this->update_comment_parent( $comment_id, $parent_id, '0' );
140+
141+
$this->assertSame( 1, $result );
142+
$this->assertSame( '0', get_comment( $comment_id )->comment_approved );
143+
$this->assertSame( (string) $parent_id, get_comment( $comment_id )->comment_parent );
144+
}
145+
78146
/**
79147
* @ticket 65570
80148
*/

0 commit comments

Comments
 (0)