Plugin Directory

source: clone-posts/trunk/admin/class-clone-posts-admin.php

Last change on this file was 3319548, checked in by pattihis, 9 months ago

Version 2.1.3

  • Property svn:eol-style set to native
File size: 13.6 KB
Line 
1<?php
2/**
3 * The admin-specific functionality of the plugin.
4 *
5 * @link       https://profiles.wordpress.org/pattihis/
6 * @since      2.0.0
7 *
8 * @package    Clone_Posts
9 * @subpackage Clone_Posts/admin
10 */
11
12/**
13 * The admin-specific functionality of the plugin.
14 *
15 * Defines the plugin name and version
16 *
17 * @package    Clone_Posts
18 * @subpackage Clone_Posts/admin
19 * @author     George Pattichis <gpattihis@gmail.com>
20 */
21class Clone_Posts_Admin {
22
23        /**
24         * The ID of this plugin.
25         *
26         * @since    2.0.0
27         * @access   private
28         * @var      string    $plugin_name    The ID of this plugin.
29         */
30        private $plugin_name;
31
32        /**
33         * The version of this plugin.
34         *
35         * @since    2.0.0
36         * @access   private
37         * @var      string    $version    The current version of this plugin.
38         */
39        private $version;
40
41        /**
42         * Initialize the class and set its properties.
43         *
44         * @since    2.0.0
45         * @param      string $plugin_name       The name of this plugin.
46         * @param      string $version    The version of this plugin.
47         */
48        public function __construct( $plugin_name, $version ) {
49
50                $this->plugin_name = $plugin_name;
51                $this->version     = $version;
52        }
53
54
55        /**
56         * Register the stylesheets for the admin area.
57         *
58         * @since    2.1.0
59         */
60        public function enqueue_styles() {
61
62                wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/clone-posts-admin.css', array(), $this->version, 'all' );
63        }
64
65        /**
66         * Register the admin settings page
67         *
68         * @since    2.0.0
69         */
70        public function clone_posts_admin_page() {
71
72                add_options_page(
73                        esc_html__( 'Clone Posts Settings', 'clone-posts' ),
74                        esc_html__( 'Clone Posts', 'clone-posts' ),
75                        'manage_options',
76                        'clone-posts-options',
77                        array( $this, 'clone_posts_admin_display' ),
78                        null
79                );
80        }
81
82        /**
83         * Render the settings page content
84         *
85         * @since  2.0.0
86         */
87        public function clone_posts_admin_display() {
88                include_once 'partials/clone-posts-admin-display.php';
89        }
90
91        /**
92         * Register the actual settings
93         *
94         * @since  2.0.0
95         */
96        public function clone_posts_register_setting() {
97
98                add_settings_section(
99                        'clone_posts_settings_section',
100                        '',
101                        '',
102                        'clone-posts-options'
103                );
104
105                register_setting(
106                        'clone_post_settings',
107                        'clone_posts_post_status',
108                        'sanitize_text_field'
109                );
110
111                add_settings_field(
112                        'clone_posts_post_status',
113                        'Post Status',
114                        array( $this, 'clone_posts_option_post_status' ),
115                        'clone-posts-options',
116                        'clone_posts_settings_section',
117                        array(
118                                'label_for' => 'clone_posts_post_status',
119                                'class'     => 'clone-posts',
120                        )
121                );
122
123                register_setting(
124                        'clone_post_settings',
125                        'clone_posts_post_date',
126                        'sanitize_text_field'
127                );
128
129                add_settings_field(
130                        'clone_posts_post_date',
131                        'Post Date',
132                        array( $this, 'clone_posts_option_post_date' ),
133                        'clone-posts-options',
134                        'clone_posts_settings_section',
135                        array(
136                                'label_for' => 'clone_posts_post_date',
137                                'class'     => 'clone-posts',
138                        )
139                );
140
141                register_setting(
142                        'clone_post_settings',
143                        'clone_posts_post_type',
144                        array( $this, 'clone_posts_sanitize_array' )
145                );
146
147                add_settings_field(
148                        'clone_posts_post_type',
149                        'Post Type',
150                        array( $this, 'clone_posts_option_post_type' ),
151                        'clone-posts-options',
152                        'clone_posts_settings_section',
153                        array(
154                                'label_for' => 'clone_posts_post_type',
155                                'class'     => 'clone-posts',
156                        )
157                );
158        }
159
160        /**
161         * Field for Post Status option
162         *
163         * @since  2.0.0
164         */
165        public function clone_posts_option_post_status() {
166                $option     = get_option( 'clone_posts_post_status' );
167                $status_txt = esc_html__( 'status', 'clone-posts' );
168                $link       = '<a href="https://wordpress.org/support/article/post-status/#default-statuses" target="_blank">' . $status_txt . '</a>';
169                ?>
170                <select name="clone_posts_post_status" id="clone_posts_post_status">
171                        <option value="draft" <?php selected( $option, 'draft' ); ?>>Draft</option>
172                        <option value="publish" <?php selected( $option, 'publish' ); ?>>Publish</option>
173                        <option value="private" <?php selected( $option, 'private' ); ?>>Private</option>
174                        <option value="pending" <?php selected( $option, 'pending' ); ?>>Pending</option>
175                </select>
176                <?php
177                // translators: %s is the link to the WordPress Codex about statuses.
178                echo wp_kses_post( '<p>' . sprintf( __( 'Select the %s of the cloned post.', 'clone-posts' ), $link ) . '</p>' );
179        }
180
181        /**
182         * Field for Post Date option
183         *
184         * @since  2.0.0
185         */
186        public function clone_posts_option_post_date() {
187                $option = get_option( 'clone_posts_post_date' );
188                ?>
189                <select name="clone_posts_post_date" id="clone_posts_post_date">
190                        <option value="current" <?php selected( $option, 'current' ); ?>>Current Date/Time</option>
191                        <option value="original" <?php selected( $option, 'original' ); ?>>Original Post Date</option>
192                </select>
193                <p><?php esc_html_e( 'Select the date/time of the cloned post.', 'clone-posts' ); ?></p>
194                <?php
195        }
196
197        /**
198         * Field for Post Type option
199         *
200         * @since  2.0.0
201         */
202        public function clone_posts_option_post_type() {
203                $options = maybe_unserialize( get_option( 'clone_posts_post_type' ) );
204                if ( ! is_array( $options ) ) {
205                        $options = array( 'post', 'page' );
206                }
207                $exclude_cpt = array( 'attachment' );
208                $post_types  = get_post_types( array( 'public' => true ), 'objects', 'and' );
209                echo '<fieldset>';
210                if ( $post_types ) {
211                        foreach ( $post_types as $post_type ) {
212                                if ( ! in_array( $post_type->name, $exclude_cpt, true ) ) {
213                                        ?>
214                                        <div>
215                                                <input type="checkbox" name="clone_posts_post_type[]" value="<?php echo esc_attr( $post_type->name ); ?>" id="post_type_<?php echo esc_attr( $post_type->name ); ?>" <?php checked( in_array( $post_type->name, $options, true ), 1 ); ?>>
216                                                <label for="post_type_<?php echo esc_attr( $post_type->name ); ?>"><?php echo esc_html( $post_type->labels->name ); ?></label>
217                                        </div>
218                                        <?php
219                                }
220                        }
221                }
222                echo '<p>' . esc_html__( 'Enable Clone for the above Post Types', 'clone-posts' ) . '</p></fieldset>';
223        }
224
225        /**
226         * A custom sanitization function for arrays.
227         *
228         * @since    2.0.0
229         * @param    array $input        The posted array.
230         * @return   array    $output       The array sanitized.
231         */
232        public function clone_posts_sanitize_array( $input ) {
233                $output = array();
234                foreach ( $input as $key => $val ) {
235                        $output[ $key ] = ( isset( $input[ $key ] ) ) ? sanitize_text_field( $val ) : '';
236                }
237                return $output;
238        }
239
240        /**
241         * Add the custom Bulk Action to the select menus
242         *
243         * @since    2.0.0
244         */
245        public function clone_posts_admin_footer() {
246                $options = maybe_unserialize( get_option( 'clone_posts_post_type' ) );
247
248                if ( ! is_array( $options ) ) {
249                        $options = array( 'post', 'page' );
250                }
251
252                if ( ! in_array( $GLOBALS['post_type'], $options, true ) ) {
253                        return;
254                }
255                ?>
256                <script type="text/javascript">
257                        jQuery(function() {
258                                jQuery('<option>').val('clone').text('<?php esc_html_e( 'Clone' ); ?>').appendTo("select[name='action']");
259                                jQuery('<option>').val('clone').text('<?php esc_html_e( 'Clone' ); ?>').appendTo("select[name='action2']");
260                        });
261                </script>
262                <?php
263        }
264
265        /**
266         * Handle the custom Bulk Action
267         *
268         * @since    2.0.0
269         */
270        public function clone_posts_bulk_action() {
271                global $typenow;
272                $post_type = $typenow;
273
274                // get the action.
275                $wp_list_table = _get_list_table( 'WP_Posts_List_Table' );
276                $action        = $wp_list_table->current_action();
277
278                $allowed_actions = array( 'clone' );
279                if ( ! in_array( $action, $allowed_actions, true ) ) {
280                        return;
281                }
282
283                // security check.
284                check_admin_referer( 'bulk-posts' );
285
286                // make sure ids are submitted.  depending on the resource type, this may be 'media' or 'ids'.
287                if ( isset( $_REQUEST['post'] ) ) {
288                        $post_ids = array_map( 'intval', $_REQUEST['post'] );
289                }
290
291                if ( empty( $post_ids ) ) {
292                        return;
293                }
294
295                // this is based on wp-admin/edit.php .
296                $sendback = remove_query_arg( array( 'cloned', 'untrashed', 'deleted', 'ids' ), wp_get_referer() );
297                if ( ! $sendback ) {
298                        $sendback = admin_url( "edit.php?post_type=$post_type" );
299                }
300
301                $pagenum  = $wp_list_table->get_pagenum();
302                $sendback = add_query_arg( 'paged', $pagenum, $sendback );
303
304                switch ( $action ) {
305                        case 'clone':
306                                $cloned = 0;
307                                foreach ( $post_ids as $post_id ) {
308
309                                        if ( ! current_user_can( 'edit_post', $post_id ) ) {
310                                                wp_die( esc_html__( 'You are not allowed to clone this post.', 'clone-posts' ) );
311                                        }
312
313                                        if ( ! $this->clone_posts_clone_single( $post_id ) ) {
314                                                wp_die( esc_html__( 'Error cloning post.', 'clone-posts' ) );
315                                        }
316
317                                        ++$cloned;
318                                }
319
320                                $sendback = add_query_arg(
321                                        array(
322                                                'cloned' => $cloned,
323                                                'ids'    => join(
324                                                        ',',
325                                                        $post_ids
326                                                ),
327                                        ),
328                                        $sendback
329                                );
330                                break;
331
332                        default:
333                                return;
334                }
335
336                $sendback = remove_query_arg(
337                        array(
338                                'action',
339                                'action2',
340                                'tags_input',
341                                'post_author',
342                                'comment_status',
343                                'ping_status',
344                                '_status',
345                                'post',
346                                'bulk_edit',
347                                'post_view',
348                        ),
349                        $sendback
350                );
351
352                wp_safe_redirect( $sendback );
353                exit();
354        }
355
356        /**
357         * Display an admin notice on the Posts page after cloning
358         *
359         * @since    2.0.0
360         */
361        public function clone_posts_admin_notices() {
362                global $pagenow;
363
364                //phpcs:disable WordPress.Security.NonceVerification.Recommended
365                if ( 'edit.php' === $pagenow && ! isset( $_GET['trashed'] ) ) {
366                        $cloned = 0;
367                        if ( isset( $_REQUEST['cloned'] ) && (int) $_REQUEST['cloned'] ) {
368                                $cloned = (int) $_REQUEST['cloned'];
369                        } elseif ( isset( $_GET['cloned'] ) && (int) $_GET['cloned'] ) {
370                                $cloned = (int) $_GET['cloned'];
371                        }
372                        if ( $cloned ) {
373                                /* translators: %s is the number of clomned posts. */
374                                $message = sprintf( _n( '%s Post cloned.', '%s Posts cloned.', $cloned ), number_format_i18n( $cloned ) );
375                                echo '<div class="notice notice-success is-dismissible"><p>' . esc_html( $message ) . '</p></div>';
376                        }
377                }
378        }
379
380        /**
381         * Filters the array of row action links on the admin table.
382         *
383         * @since    2.0.0
384         *
385         * @param array   $actions An array of row action links.
386         * @param WP_Post $post    The post object.
387         */
388        public function clone_posts_post_row_actions( $actions, $post ) {
389                global $post_type;
390
391                $options = maybe_unserialize( get_option( 'clone_posts_post_type' ) );
392
393                if ( ! is_array( $options ) ) {
394                        $options = array( 'post', 'page' );
395                }
396
397                if ( ! in_array( $post_type, $options, true ) ) {
398                        return $actions;
399                }
400
401                $url = remove_query_arg( array( 'cloned', 'untrashed', 'deleted', 'ids' ), '' );
402                if ( ! $url ) {
403                        $url = admin_url( "?post_type=$post_type" );
404                }
405                $url = remove_query_arg(
406                        array(
407                                'action',
408                                'action2',
409                                'tags_input',
410                                'post_author',
411                                'comment_status',
412                                'ping_status',
413                                '_status',
414                                'post',
415                                'bulk_edit',
416                                'post_view',
417                        ),
418                        $url
419                );
420                $url = add_query_arg(
421                        array(
422                                'action'   => 'clone-single',
423                                'post'     => $post->ID,
424                                'redirect' => isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : get_home_url(),
425                        ),
426                        $url
427                );
428
429                $actions['clone'] = '<a href=\'' . $url . '\'>' . __( 'Clone', 'clone-posts' ) . '</a>';
430                return $actions;
431        }
432
433        /**
434         * Fires before admin_init, clears query args and redirects
435         *
436         * @since    2.0.0
437         */
438        public function clone_posts_wp_loaded() {
439                global $post_type;
440
441                if ( ! isset( $_GET['action'] ) || 'clone-single' !== $_GET['action'] || ! isset( $_GET['post'] ) || ! isset( $_GET['redirect'] ) ) {
442                        return;
443                }
444
445                $post_id = (int) $_GET['post'];
446
447                if ( ! current_user_can( 'edit_post', $post_id ) ) {
448                        wp_die( esc_html__( 'You are not allowed to clone this post.', 'clone-posts' ) );
449                }
450
451                if ( ! $this->clone_posts_clone_single( $post_id ) ) {
452                        wp_die( esc_html__( 'Error cloning post.', 'clone-posts' ) );
453                }
454
455                $sendback = remove_query_arg( array( 'cloned', 'untrashed', 'deleted', 'ids' ), esc_url_raw( wp_unslash( $_GET['redirect'] ) ) );
456                if ( ! $sendback ) {
457                        $sendback = admin_url( "edit.php?post_type=$post_type" );
458                }
459
460                $sendback = add_query_arg( array( 'cloned' => 1 ), $sendback );
461                $sendback = remove_query_arg( array( 'action', 'action2', 'tags_input', 'post_author', 'comment_status', 'ping_status', '_status', 'post', 'bulk_edit', 'post_view' ), $sendback );
462
463                wp_safe_redirect( $sendback );
464                exit();
465        }
466
467        /**
468         * Clone the Post
469         *
470         * @param int $id The Post ID.
471         * @since    2.0.0
472         */
473        public function clone_posts_clone_single( $id ) {
474                $p = get_post( $id );
475                if ( null === $p ) {
476                        return false;
477                }
478
479                $newpost = array(
480                        'post_name'             => $p->post_name,
481                        'post_type'             => $p->post_type,
482                        'ping_status'           => $p->ping_status,
483                        'post_parent'           => $p->post_parent,
484                        'menu_order'            => $p->menu_order,
485                        'post_password'         => $p->post_password,
486                        'post_excerpt'          => $p->post_excerpt,
487                        'comment_status'        => $p->comment_status,
488                        'post_title'            => $p->post_title . __( ' - Clone', 'clone-posts' ),
489                        'post_content'          => $p->post_content,
490                        'post_author'           => $p->post_author,
491                        'to_ping'               => $p->to_ping,
492                        'pinged'                => $p->pinged,
493                        'post_content_filtered' => $p->post_content_filtered,
494                        'post_category'         => $p->post_category,
495                        'tags_input'            => $p->tags_input,
496                        'tax_input'             => $p->tax_input,
497                        'page_template'         => $p->page_template,
498                );
499
500                $post_status = get_option( 'clone_posts_post_status' );
501                if ( 'draft' !== $post_status ) {
502                        $newpost['post_status'] = $post_status;
503                }
504
505                $date = get_option( 'clone_posts_post_date' );
506                if ( 'current' !== $date ) {
507                        $newpost['post_date']     = $p->post_date;
508                        $newpost['post_date_gmt'] = $p->post_date_gmt;
509                }
510
511                $newid  = wp_insert_post( $newpost );
512                $format = get_post_format( $id );
513                set_post_format( $newid, $format );
514
515                $meta = get_post_meta( $id );
516                foreach ( $meta as $key => $val ) {
517                        update_post_meta( $newid, $key, maybe_unserialize( $val[0] ) );
518                }
519
520                return true;
521        }
522}
Note: See TracBrowser for help on using the repository browser.