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

Yoast / duplicate-post / 14725616456

29 Apr 2025 07:21AM UTC coverage: 45.469% (-4.7%) from 50.122%
14725616456

push

github

web-flow
Merge pull request #402 from Yoast/feature/drop-php-7.2-7.3

Drop support for Php 7.2 and 7.3

1164 of 2560 relevant lines covered (45.47%)

1.61 hits per line

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

88.15
/src/ui/classic-editor.php
1
<?php
2

3
namespace Yoast\WP\Duplicate_Post\UI;
4

5
use WP_Post;
6
use Yoast\WP\Duplicate_Post\Permissions_Helper;
7
use Yoast\WP\Duplicate_Post\Utils;
8

9
/**
10
 * Duplicate Post class to manage the classic editor UI.
11
 */
12
class Classic_Editor {
13

14
        /**
15
         * Holds the object to create the action link to duplicate.
16
         *
17
         * @var Link_Builder
18
         */
19
        protected $link_builder;
20

21
        /**
22
         * Holds the permissions helper.
23
         *
24
         * @var Permissions_Helper
25
         */
26
        protected $permissions_helper;
27

28
        /**
29
         * Holds the asset manager.
30
         *
31
         * @var Asset_Manager
32
         */
33
        protected $asset_manager;
34

35
        /**
36
         * Initializes the class.
37
         *
38
         * @param Link_Builder       $link_builder       The link builder.
39
         * @param Permissions_Helper $permissions_helper The permissions helper.
40
         * @param Asset_Manager      $asset_manager      The asset manager.
41
         */
42
        public function __construct( Link_Builder $link_builder, Permissions_Helper $permissions_helper, Asset_Manager $asset_manager ) {
2✔
43
                $this->link_builder       = $link_builder;
2✔
44
                $this->permissions_helper = $permissions_helper;
2✔
45
                $this->asset_manager      = $asset_manager;
2✔
46
        }
47

48
        /**
49
         * Adds hooks to integrate with WordPress.
50
         *
51
         * @return void
52
         */
53
        public function register_hooks() {
2✔
54
                \add_action( 'post_submitbox_misc_actions', [ $this, 'add_check_changes_link' ], 90 );
2✔
55

56
                if ( \intval( Utils::get_option( 'duplicate_post_show_link_in', 'submitbox' ) ) === 1 ) {
2✔
57
                        if ( \intval( Utils::get_option( 'duplicate_post_show_link', 'new_draft' ) ) === 1 ) {
2✔
58
                                \add_action( 'post_submitbox_start', [ $this, 'add_new_draft_post_button' ] );
2✔
59
                        }
60

61
                        if ( \intval( Utils::get_option( 'duplicate_post_show_link', 'rewrite_republish' ) ) === 1 ) {
2✔
62
                                \add_action( 'post_submitbox_start', [ $this, 'add_rewrite_and_republish_post_button' ] );
2✔
63
                        }
64
                }
65

66
                \add_action( 'load-post.php', [ $this, 'hook_translations' ] );
2✔
67
                \add_filter( 'post_updated_messages', [ $this, 'change_scheduled_notice_classic_editor' ] );
2✔
68

69
                \add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_classic_editor_scripts' ] );
2✔
70
                if ( \intval( Utils::get_option( 'duplicate_post_show_link_in', 'submitbox' ) ) === 1 ) {
2✔
71
                        if ( \intval( Utils::get_option( 'duplicate_post_show_link', 'new_draft' ) ) === 1
2✔
72
                                || \intval( Utils::get_option( 'duplicate_post_show_link', 'rewrite_republish' ) ) === 1 ) {
2✔
73
                                \add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_classic_editor_styles' ] );
2✔
74
                        }
75
                }
76

77
                // Remove slug editing from Classic Editor.
78
                \add_action( 'add_meta_boxes', [ $this, 'remove_slug_meta_box' ], 10, 2 );
2✔
79
                \add_filter( 'get_sample_permalink_html', [ $this, 'remove_sample_permalink_slug_editor' ], 10, 5 );
2✔
80
        }
81

82
        /**
83
         * Hooks the functions to change the translations.
84
         *
85
         * @return void
86
         */
87
        public function hook_translations() {
2✔
88
                        \add_filter( 'gettext', [ $this, 'change_republish_strings_classic_editor' ], 10, 3 );
2✔
89
                        \add_filter( 'gettext_with_context', [ $this, 'change_schedule_strings_classic_editor' ], 10, 4 );
2✔
90
        }
91

92
        /**
93
         * Enqueues the necessary JavaScript code for the Classic editor.
94
         *
95
         * @return void
96
         */
97
        public function enqueue_classic_editor_scripts() {
2✔
98
                if ( $this->permissions_helper->is_classic_editor() && isset( $_GET['post'] ) ) {
2✔
99
                        $id   = \intval( \wp_unslash( $_GET['post'] ) );
2✔
100
                        $post = \get_post( $id );
2✔
101

102
                        if ( ! \is_null( $post ) && $this->permissions_helper->is_rewrite_and_republish_copy( $post ) ) {
2✔
103
                                $this->asset_manager->enqueue_strings_script();
2✔
104
                        }
105
                }
106
        }
107

108
        /**
109
         * Enqueues the necessary styles for the Classic editor.
110
         *
111
         * @return void
112
         */
113
        public function enqueue_classic_editor_styles() {
2✔
114
                if ( $this->permissions_helper->is_classic_editor()
2✔
115
                        && isset( $_GET['post'] ) ) {
2✔
116
                        $id   = \intval( \wp_unslash( $_GET['post'] ) );
2✔
117
                        $post = \get_post( $id );
2✔
118

119
                        if ( ! \is_null( $post ) && $this->permissions_helper->should_links_be_displayed( $post ) ) {
2✔
120
                                $this->asset_manager->enqueue_styles();
2✔
121
                        }
122
                }
123
        }
124

125
        /**
126
         * Adds a button in the post/page edit screen to create a clone
127
         *
128
         * @param WP_Post|null $post The post object that's being edited.
129
         *
130
         * @return void
131
         */
132
        public function add_new_draft_post_button( $post = null ) {
8✔
133
                if ( \is_null( $post ) ) {
8✔
134
                        if ( isset( $_GET['post'] ) ) {
4✔
135
                                $id   = \intval( \wp_unslash( $_GET['post'] ) );
2✔
136
                                $post = \get_post( $id );
2✔
137
                        }
138
                }
139

140
                if ( $post instanceof WP_Post && $this->permissions_helper->should_links_be_displayed( $post ) ) {
8✔
141
                        ?>
142
                        <div id="duplicate-action">
4✔
143
                                <a class="submitduplicate duplication"
4✔
144
                                        href="<?php echo \esc_url( $this->link_builder->build_new_draft_link( $post ) ); ?>"><?php \esc_html_e( 'Copy to a new draft', 'duplicate-post' ); ?>
4✔
145
                                </a>
4✔
146
                        </div>
4✔
147
                        <?php
4✔
148
                }
149
        }
150

151
        /**
152
         * Adds a button in the post/page edit screen to create a clone for Rewrite & Republish.
153
         *
154
         * @param WP_Post|null $post The post object that's being edited.
155
         *
156
         * @return void
157
         */
158
        public function add_rewrite_and_republish_post_button( $post = null ) {
10✔
159
                if ( \is_null( $post ) ) {
10✔
160
                        if ( isset( $_GET['post'] ) ) {
6✔
161
                                $id   = \intval( \wp_unslash( $_GET['post'] ) );
2✔
162
                                $post = \get_post( $id );
2✔
163
                        }
164
                }
165

166
                if (
167
                        $post instanceof WP_Post
10✔
168
                        && $this->permissions_helper->should_rewrite_and_republish_be_allowed( $post )
10✔
169
                        && $this->permissions_helper->should_links_be_displayed( $post )
10✔
170
                ) {
171
                        ?>
172
                        <div id="rewrite-republish-action">
4✔
173
                                <a class="submitduplicate duplication" href="<?php echo \esc_url( $this->link_builder->build_rewrite_and_republish_link( $post ) ); ?>"><?php \esc_html_e( 'Rewrite & Republish', 'duplicate-post' ); ?>
4✔
174
                                </a>
4✔
175
                        </div>
4✔
176
                        <?php
4✔
177
                }
178
        }
179

180
        /**
181
         * Adds a message in the post/page edit screen to create a clone for Rewrite & Republish.
182
         *
183
         * @param WP_Post|null $post The post object that's being edited.
184
         *
185
         * @return void
186
         */
187
        public function add_check_changes_link( $post = null ) {
×
188
                if ( \is_null( $post ) ) {
×
189
                        if ( isset( $_GET['post'] ) ) {
×
190
                                $id   = \intval( \wp_unslash( $_GET['post'] ) );
×
191
                                $post = \get_post( $id );
×
192
                        }
193
                }
194

195
                if ( $post instanceof WP_Post && $this->permissions_helper->is_rewrite_and_republish_copy( $post ) ) {
×
196
                        ?>
197
                                <div id="check-changes-action" class="misc-pub-section">
×
198
                                        <?php \esc_html_e( 'Do you want to compare your changes with the original version before merging? Please save any changes first.', 'duplicate-post' ); ?>
×
199
                                        <br><br>
×
200
                                        <a class='button' href=<?php echo \esc_url( $this->link_builder->build_check_link( $post ) ); ?>>
×
201
                                                <?php \esc_html_e( 'Compare', 'duplicate-post' ); ?>
×
202
                                        </a>
×
203
                                </div>
×
204
                                <?php
×
205
                }
206
        }
207

208
        /**
209
         * Changes the 'Publish' copies in the submitbox to 'Republish' if a post is intended for republishing.
210
         *
211
         * @param string $translation The translated text.
212
         * @param string $text        The text to translate.
213
         * @param string $domain      The translation domain.
214
         *
215
         * @return string The to-be-used copy of the text.
216
         */
217
        public function change_republish_strings_classic_editor( $translation, $text, $domain ) {
10✔
218
                if ( $domain !== 'default' ) {
10✔
219
                        return $translation;
2✔
220
                }
221

222
                if ( $text === 'Publish'
8✔
223
                        && $this->should_change_rewrite_republish_copy( \get_post() ) ) {
8✔
224
                                return \__( 'Republish', 'duplicate-post' );
2✔
225
                }
226
                elseif ( $text === 'Publish on: %s'
6✔
227
                        && $this->should_change_rewrite_republish_copy( \get_post() ) ) {
6✔
228
                        /* translators: %s: Date on which the post is to be republished. */
229
                        return \__( 'Republish on: %s', 'duplicate-post' );
2✔
230
                }
231

232
                return $translation;
4✔
233
        }
234

235
        /**
236
         * Changes the 'Schedule' copy in the submitbox to 'Schedule republish' if a post is intended for republishing.
237
         *
238
         * @param string $translation The translated text.
239
         * @param string $text        The text to translate.
240
         * @param string $context     The translation context.
241
         * @param string $domain      The translation domain.
242
         *
243
         * @return string The to-be-used copy of the text.
244
         */
245
        public function change_schedule_strings_classic_editor( $translation, $text, $context, $domain ) {
10✔
246
                if ( $domain !== 'default' || $context !== 'post action/button label' ) {
10✔
247
                        return $translation;
4✔
248
                }
249

250
                if ( $text === 'Schedule'
6✔
251
                        && $this->should_change_rewrite_republish_copy( \get_post() ) ) {
6✔
252
                        return \__( 'Schedule republish', 'duplicate-post' );
2✔
253
                }
254

255
                return $translation;
4✔
256
        }
257

258
        /**
259
         * Changes the post-scheduled notice when a post or page intended for republishing is scheduled.
260
         *
261
         * @param array[] $messages Post updated messaged.
262
         *
263
         * @return array[] The to-be-used messages.
264
         */
265
        public function change_scheduled_notice_classic_editor( $messages ) {
4✔
266
                $post = \get_post();
4✔
267
                if ( ! $this->should_change_rewrite_republish_copy( $post ) ) {
4✔
268
                        return $messages;
×
269
                }
270

271
                $permalink      = \get_permalink( $post->ID );
4✔
272
                $scheduled_date = \get_the_time( \get_option( 'date_format' ), $post );
4✔
273
                $scheduled_time = \get_the_time( \get_option( 'time_format' ), $post );
4✔
274

275
                if ( $post->post_type === 'post' ) {
4✔
276
                        $messages['post'][9] = \sprintf(
2✔
277
                                /* translators: 1: The post title with a link to the frontend page, 2: The scheduled date and time. */
278
                                \esc_html__(
2✔
279
                                        'This rewritten post %1$s is now scheduled to replace the original post. It will be published on %2$s.',
2✔
280
                                        'duplicate-post'
2✔
281
                                ),
2✔
282
                                '<a href="' . $permalink . '">' . $post->post_title . '</a>',
2✔
283
                                '<strong>' . $scheduled_date . ' ' . $scheduled_time . '</strong>'
2✔
284
                        );
2✔
285
                        return $messages;
2✔
286
                }
287

288
                if ( $post->post_type === 'page' ) {
2✔
289
                        $messages['page'][9] = \sprintf(
2✔
290
                                /* translators: 1: The page title with a link to the frontend page, 2: The scheduled date and time. */
291
                                \esc_html__(
2✔
292
                                        'This rewritten page %1$s is now scheduled to replace the original page. It will be published on %2$s.',
2✔
293
                                        'duplicate-post'
2✔
294
                                ),
2✔
295
                                '<a href="' . $permalink . '">' . $post->post_title . '</a>',
2✔
296
                                '<strong>' . $scheduled_date . ' ' . $scheduled_time . '</strong>'
2✔
297
                        );
2✔
298
                }
299

300
                return $messages;
2✔
301
        }
302

303
        /**
304
         * Determines if the Rewrite & Republish copies for the post should be used.
305
         *
306
         * @param WP_Post $post The current post object.
307
         *
308
         * @return bool True if the Rewrite & Republish copies should be used.
309
         */
310
        public function should_change_rewrite_republish_copy( $post ) {
10✔
311
                global $pagenow;
10✔
312
                if ( ! \in_array( $pagenow, [ 'post.php', 'post-new.php' ], true ) ) {
10✔
313
                        return false;
2✔
314
                }
315

316
                if ( ! $post instanceof WP_Post ) {
8✔
317
                        return false;
2✔
318
                }
319

320
                return $this->permissions_helper->is_rewrite_and_republish_copy( $post );
6✔
321
        }
322

323
        /**
324
         * Removes the slug meta box in the Classic Editor when the post is a Rewrite & Republish copy.
325
         *
326
         * @param string  $post_type Post type.
327
         * @param WP_Post $post      Post object.
328
         *
329
         * @return void
330
         */
331
        public function remove_slug_meta_box( $post_type, $post ) {
4✔
332
                if ( $post instanceof WP_Post && $this->permissions_helper->is_rewrite_and_republish_copy( $post ) ) {
4✔
333
                        \remove_meta_box( 'slugdiv', $post_type, 'normal' );
2✔
334
                }
335
        }
336

337
        /**
338
         * Removes the sample permalink slug editor in the Classic Editor when the post is a Rewrite & Republish copy.
339
         *
340
         * @param string  $html      Sample permalink HTML markup.
341
         * @param int     $post_id   Post ID.
342
         * @param string  $new_title New sample permalink title.
343
         * @param string  $new_slug  New sample permalink slug.
344
         * @param WP_Post $post      Post object.
345
         *
346
         * @return string The filtered HTML of the sample permalink slug editor.
347
         */
348
        public function remove_sample_permalink_slug_editor( $html, $post_id, $new_title, $new_slug, $post ) {
4✔
349
                if ( ! $post instanceof WP_Post ) {
4✔
350
                        return $html;
×
351
                }
352

353
                if ( $this->permissions_helper->is_rewrite_and_republish_copy( $post ) ) {
4✔
354
                        return '';
2✔
355
                }
356

357
                return $html;
2✔
358
        }
359
}
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

© 2025 Coveralls, Inc