diff --git a/js/src/duplicate-post-edit-script.js b/js/src/duplicate-post-edit-script.js
index 3587ef8d0..5f27c6a4f 100644
--- a/js/src/duplicate-post-edit-script.js
+++ b/js/src/duplicate-post-edit-script.js
@@ -257,6 +257,7 @@ class DuplicatePost {
notice.text,
{
isDismissible: notice.isDismissible || true,
+ __unstableHTML: notice.isHTML || false,
}
);
}
diff --git a/src/watchers/copied-post-watcher.php b/src/watchers/copied-post-watcher.php
index 2e7278933..71aec54fa 100644
--- a/src/watchers/copied-post-watcher.php
+++ b/src/watchers/copied-post-watcher.php
@@ -47,9 +47,33 @@ public function register_hooks() {
*/
public function get_notice_text( $post ) {
if ( $this->permissions_helper->has_trashed_rewrite_and_republish_copy( $post ) ) {
+ $trash_url = \add_query_arg(
+ [
+ 'post_status' => 'trash',
+ 'post_type' => $post->post_type,
+ ],
+ \admin_url( 'edit.php' ),
+ );
+ $view_trash_html = \sprintf(
+ ' %2$s',
+ \esc_url( $trash_url ),
+ \__( 'View trash.', 'duplicate-post' ),
+ );
+
return \__(
'You can only make one Rewrite & Republish duplicate at a time, and a duplicate of this post already exists in the trash. Permanently delete it if you want to make a new duplicate.',
'duplicate-post',
+ ) . $view_trash_html;
+ }
+
+ $copy = $this->permissions_helper->get_rewrite_and_republish_copy( $post );
+ $edit_url = ( $copy instanceof WP_Post ) ? \get_edit_post_link( $copy->ID, 'raw' ) : '';
+ $link_html = '';
+ if ( $edit_url !== '' ) {
+ $link_html = \sprintf(
+ ' %2$s',
+ \esc_url( $edit_url ),
+ \__( 'Edit the duplicate.', 'duplicate-post' ),
);
}
@@ -58,7 +82,7 @@ public function get_notice_text( $post ) {
return \__(
'A duplicate of this post was made. Please note that any changes you make to this post will be replaced when the duplicated version is republished.',
'duplicate-post',
- );
+ ) . $link_html;
}
return \sprintf(
@@ -69,7 +93,7 @@ public function get_notice_text( $post ) {
),
\get_the_time( \get_option( 'date_format' ), $scheduled_copy ),
\get_the_time( \get_option( 'time_format' ), $scheduled_copy ),
- );
+ ) . $link_html;
}
/**
@@ -90,7 +114,7 @@ public function add_admin_notice() {
if ( $this->permissions_helper->has_rewrite_and_republish_copy( $post ) ) {
print '
'
- . \esc_html( $this->get_notice_text( $post ) )
+ . \wp_kses( $this->get_notice_text( $post ), [ 'a' => [ 'href' => [] ] ] )
. '
';
}
}
@@ -113,6 +137,7 @@ public function add_block_editor_notice() {
'text' => $this->get_notice_text( $post ),
'status' => 'warning',
'isDismissible' => true,
+ 'isHTML' => true,
];
\wp_add_inline_script(
diff --git a/tests/Unit/Watchers/Copied_Post_Watcher_Test.php b/tests/Unit/Watchers/Copied_Post_Watcher_Test.php
index 88d34138f..c483a3467 100644
--- a/tests/Unit/Watchers/Copied_Post_Watcher_Test.php
+++ b/tests/Unit/Watchers/Copied_Post_Watcher_Test.php
@@ -81,8 +81,12 @@ public function test_register_hooks() {
*/
public function test_get_notice_text_not_scheduled() {
$this->stubTranslationFunctions();
+ $this->stubEscapeFunctions();
$post = Mockery::mock( WP_Post::class );
+ $copy = Mockery::mock( WP_Post::class );
+
+ $copy->ID = 456;
$this->permissions_helper
->expects( 'has_scheduled_rewrite_and_republish_copy' )
@@ -94,8 +98,16 @@ public function test_get_notice_text_not_scheduled() {
->with( $post )
->andReturnFalse();
+ $this->permissions_helper
+ ->expects( 'get_rewrite_and_republish_copy' )
+ ->with( $post )
+ ->andReturn( $copy );
+
+ Monkey\Functions\when( '\get_edit_post_link' )
+ ->justReturn( 'http://example.com/edit?post=456' );
+
$this->assertSame(
- 'A duplicate of this post was made. Please note that any changes you make to this post will be replaced when the duplicated version is republished.',
+ 'A duplicate of this post was made. Please note that any changes you make to this post will be replaced when the duplicated version is republished. Edit the duplicate.',
$this->instance->get_notice_text( $post ),
);
}
@@ -109,10 +121,13 @@ public function test_get_notice_text_not_scheduled() {
*/
public function test_get_notice_text_scheduled() {
$this->stubTranslationFunctions();
+ $this->stubEscapeFunctions();
$post = Mockery::mock( WP_Post::class );
$copy = Mockery::mock( WP_Post::class );
+ $copy->ID = 789;
+
$this->permissions_helper
->expects( 'has_scheduled_rewrite_and_republish_copy' )
->with( $post )
@@ -123,6 +138,14 @@ public function test_get_notice_text_scheduled() {
->with( $post )
->andReturnFalse();
+ $this->permissions_helper
+ ->expects( 'get_rewrite_and_republish_copy' )
+ ->with( $post )
+ ->andReturn( $copy );
+
+ Monkey\Functions\when( '\get_edit_post_link' )
+ ->justReturn( 'http://example.com/edit?post=789' );
+
Monkey\Functions\expect( '\get_option' )
->twice()
->andReturnValues( [ 'Y/m/d', 'g:i a' ] );
@@ -132,7 +155,7 @@ public function test_get_notice_text_scheduled() {
->andReturnValues( [ '2020/12/02', '10:30 am' ] );
$this->assertSame(
- 'A duplicate of this post was made, which is scheduled to replace this post on 2020/12/02 at 10:30 am.',
+ 'A duplicate of this post was made, which is scheduled to replace this post on 2020/12/02 at 10:30 am. Edit the duplicate.',
$this->instance->get_notice_text( $post ),
);
}
@@ -146,9 +169,12 @@ public function test_get_notice_text_scheduled() {
*/
public function test_get_notice_text_copy_in_the_trash() {
$this->stubTranslationFunctions();
+ $this->stubEscapeFunctions();
$post = Mockery::mock( WP_Post::class );
+ $post->post_type = 'post';
+
$this->permissions_helper
->expects( 'has_scheduled_rewrite_and_republish_copy' )
->never();
@@ -158,8 +184,14 @@ public function test_get_notice_text_copy_in_the_trash() {
->with( $post )
->andReturnTrue();
+ Monkey\Functions\when( '\admin_url' )
+ ->justReturn( 'http://example.com/wp-admin/edit.php' );
+
+ Monkey\Functions\when( '\add_query_arg' )
+ ->justReturn( 'http://example.com/wp-admin/edit.php?post_status=trash&post_type=post' );
+
$this->assertSame(
- 'You can only make one Rewrite & Republish duplicate at a time, and a duplicate of this post already exists in the trash. Permanently delete it if you want to make a new duplicate.',
+ 'You can only make one Rewrite & Republish duplicate at a time, and a duplicate of this post already exists in the trash. Permanently delete it if you want to make a new duplicate. View trash.',
$this->instance->get_notice_text( $post ),
);
}
@@ -192,6 +224,10 @@ public function test_add_admin_notice_classic() {
->expects( 'get_notice_text' )
->andReturn( 'notice' );
+ Monkey\Functions\expect( '\wp_kses' )
+ ->with( 'notice', [ 'a' => [ 'href' => [] ] ] )
+ ->andReturn( 'notice' );
+
$this->instance->add_admin_notice();
$this->expectOutputString( '' );
@@ -268,16 +304,17 @@ public function test_add_block_editor_notice() {
'text' => 'notice',
'status' => 'warning',
'isDismissible' => true,
+ 'isHTML' => true,
];
Monkey\Functions\expect( '\wp_json_encode' )
->with( $notice )
- ->andReturn( '{"text":"notice","status":"warning","isDismissible":true}' );
+ ->andReturn( '{"text":"notice","status":"warning","isDismissible":true,"isHTML":true}' );
Monkey\Functions\expect( '\wp_add_inline_script' )
->with(
'duplicate_post_edit_script',
- 'duplicatePostNotices.has_rewrite_and_republish_notice = {"text":"notice","status":"warning","isDismissible":true};',
+ 'duplicatePostNotices.has_rewrite_and_republish_notice = {"text":"notice","status":"warning","isDismissible":true,"isHTML":true};',
'before',
);