• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Yoast / duplicate-post / 21596629254

02 Feb 2026 03:40PM UTC coverage: 57.637% (+1.3%) from 56.353%
21596629254

push

github

web-flow
Merge pull request #446 from Yoast/enrico/add-sidebar-panel

Use a sidebar panel instead of the metabox in the block editor

68 of 86 new or added lines in 6 files covered. (79.07%)

1 existing line in 1 file now uncovered.

1517 of 2632 relevant lines covered (57.64%)

7.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.65
/src/handlers/rest-api-handler.php
1
<?php
2

3
namespace Yoast\WP\Duplicate_Post\Handlers;
4

5
use WP_Error;
6
use WP_REST_Request;
7
use WP_REST_Response;
8
use WP_REST_Server;
9
use Yoast\WP\Duplicate_Post\Permissions_Helper;
10

11
/**
12
 * Duplicate Post handler class for REST API endpoints.
13
 *
14
 * @since 4.6
15
 */
16
class Rest_API_Handler {
17

18
        /**
19
         * The REST API namespace.
20
         *
21
         * @var string
22
         */
23
        public const REST_NAMESPACE = 'duplicate-post/v1';
24

25
        /**
26
         * Holds the permissions helper.
27
         *
28
         * @var Permissions_Helper
29
         */
30
        protected $permissions_helper;
31

32
        /**
33
         * Initializes the class.
34
         *
35
         * @param Permissions_Helper $permissions_helper The Permissions Helper object.
36
         */
NEW
37
        public function __construct( Permissions_Helper $permissions_helper ) {
×
NEW
38
                $this->permissions_helper = $permissions_helper;
×
39
        }
40

41
        /**
42
         * Adds hooks to integrate with WordPress.
43
         *
44
         * @return void
45
         */
NEW
46
        public function register_hooks() {
×
NEW
47
                \add_action( 'rest_api_init', [ $this, 'register_routes' ] );
×
48
        }
49

50
        /**
51
         * Registers the REST API routes.
52
         *
53
         * @return void
54
         */
55
        public function register_routes() {
8✔
56
                \register_rest_route(
8✔
57
                        self::REST_NAMESPACE,
8✔
58
                        '/original/(?P<post_id>\d+)',
8✔
59
                        [
8✔
60
                                'methods'             => WP_REST_Server::DELETABLE,
8✔
61
                                'callback'            => [ $this, 'remove_original' ],
8✔
62
                                'permission_callback' => [ $this, 'can_remove_original' ],
8✔
63
                                'args'                => [
8✔
64
                                        'post_id' => [
8✔
65
                                                'description'       => \__( 'The ID of the post to remove the original reference from.', 'duplicate-post' ),
8✔
66
                                                'type'              => 'integer',
8✔
67
                                                'required'          => true,
8✔
68
                                                'validate_callback' => static function ( $param ) {
8✔
69
                                                        return \is_numeric( $param ) && (int) $param > 0;
4✔
70
                                                },
8✔
71
                                                'sanitize_callback' => 'absint',
8✔
72
                                        ],
8✔
73
                                ],
8✔
74
                        ]
8✔
75
                );
8✔
76
        }
77

78
        /**
79
         * Checks if the current user can remove the original reference.
80
         *
81
         * @param WP_REST_Request $request The REST request object.
82
         *
83
         * @return bool|WP_Error True if the user can remove the original, WP_Error otherwise.
84
         */
85
        public function can_remove_original( WP_REST_Request $request ) {
20✔
86
                $post_id = $request->get_param( 'post_id' );
20✔
87
                $post    = \get_post( $post_id );
20✔
88

89
                if ( ! $post ) {
20✔
90
                        return new WP_Error(
4✔
91
                                'rest_post_not_found',
4✔
92
                                \__( 'Post not found.', 'duplicate-post' ),
4✔
93
                                [ 'status' => 404 ]
4✔
94
                        );
4✔
95
                }
96

97
                if ( ! \current_user_can( 'edit_post', $post_id ) ) {
16✔
98
                        return new WP_Error(
8✔
99
                                'rest_forbidden',
8✔
100
                                \__( 'You do not have permission to edit this post.', 'duplicate-post' ),
8✔
101
                                [ 'status' => 403 ]
8✔
102
                        );
8✔
103
                }
104

105
                if ( $this->permissions_helper->is_rewrite_and_republish_copy( $post ) ) {
8✔
106
                        return new WP_Error(
4✔
107
                                'rest_forbidden',
4✔
108
                                \__( 'Cannot remove original reference from a Rewrite & Republish copy.', 'duplicate-post' ),
4✔
109
                                [ 'status' => 403 ]
4✔
110
                        );
4✔
111
                }
112

113
                return true;
4✔
114
        }
115

116
        /**
117
         * Removes the original reference from a post.
118
         *
119
         * @param WP_REST_Request $request The REST request object.
120
         *
121
         * @return WP_REST_Response|WP_Error The REST response or error.
122
         */
123
        public function remove_original( WP_REST_Request $request ) {
8✔
124
                $post_id = $request->get_param( 'post_id' );
8✔
125

126
                $deleted = \delete_post_meta( $post_id, '_dp_original' );
8✔
127

128
                if ( ! $deleted ) {
8✔
129
                        return new WP_Error(
4✔
130
                                'rest_cannot_delete',
4✔
131
                                \__( 'Could not remove the original reference.', 'duplicate-post' ),
4✔
132
                                [ 'status' => 500 ]
4✔
133
                        );
4✔
134
                }
135

136
                return new WP_REST_Response(
4✔
137
                        [
4✔
138
                                'success' => true,
4✔
139
                                'message' => \__( 'Original reference removed successfully.', 'duplicate-post' ),
4✔
140
                        ],
4✔
141
                        200
4✔
142
                );
4✔
143
        }
144
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc