From 54a3a254ca2153e1ec77b6662261827f1f4c49a7 Mon Sep 17 00:00:00 2001 From: Leandro Bosaipo Date: Mon, 19 Aug 2019 13:18:23 -0400 Subject: [PATCH] initial plugin --- compat/duplicate-post-jetpack.php | 30 ++ compat/duplicate-post-wpml.php | 81 ++++ donate.png | Bin 0 -> 3207 bytes duplicate-post-admin.php | 722 ++++++++++++++++++++++++++++++ duplicate-post-common.php | 171 +++++++ duplicate-post-options.php | 395 ++++++++++++++++ duplicate-post.css | 32 ++ duplicate-post.php | 57 +++ gpl-2.0.txt | 339 ++++++++++++++ readme.txt | 313 +++++++++++++ 10 files changed, 2140 insertions(+) create mode 100644 compat/duplicate-post-jetpack.php create mode 100644 compat/duplicate-post-wpml.php create mode 100644 donate.png create mode 100644 duplicate-post-admin.php create mode 100644 duplicate-post-common.php create mode 100644 duplicate-post-options.php create mode 100644 duplicate-post.css create mode 100644 duplicate-post.php create mode 100644 gpl-2.0.txt create mode 100644 readme.txt diff --git a/compat/duplicate-post-jetpack.php b/compat/duplicate-post-jetpack.php new file mode 100644 index 0000000..6bd76b9 --- /dev/null +++ b/compat/duplicate-post-jetpack.php @@ -0,0 +1,30 @@ +unload_markdown_for_posts(); +} + +function duplicate_post_jetpack_enable_markdown(){ + WPCom_Markdown::get_instance()->load_markdown_for_posts(); +} \ No newline at end of file diff --git a/compat/duplicate-post-wpml.php b/compat/duplicate-post-wpml.php new file mode 100644 index 0000000..d7aebb3 --- /dev/null +++ b/compat/duplicate-post-wpml.php @@ -0,0 +1,81 @@ +get_current_language(); + $trid = $sitepress->get_element_trid($post->ID); + if (!empty($trid)) { + $translations = $sitepress->get_element_translations($trid); + $new_trid = $sitepress->get_element_trid($post_id); + foreach ($translations as $code => $details) { + if ($code != $current_language) { + if ( $details->element_id ) { + $translation = get_post( $details->element_id ); + if (!$translation) continue; + $new_post_id = duplicate_post_create_duplicate( $translation, $status ); + $sitepress->set_element_language_details( $new_post_id, 'post_' . $translation->post_type, $new_trid, $code, $current_language ); + } + } + } + $duplicated_posts[ $post->ID ] = $post_id; + } +} + +function duplicate_wpml_string_packages() { + global $duplicated_posts; + + foreach ( $duplicated_posts as $original_post_id => $duplicate_post_id ) { + + $original_string_packages = apply_filters( 'wpml_st_get_post_string_packages', false, $original_post_id ); + $new_string_packages = apply_filters( 'wpml_st_get_post_string_packages', false, $duplicate_post_id ); + if ( is_array( $original_string_packages ) ) { + foreach ( $original_string_packages as $original_string_package ) { + $translated_original_strings = $original_string_package->get_translated_strings( array() ); + + foreach ( $new_string_packages as $new_string_package ) { + $cache = new WPML_WP_Cache( 'WPML_Package' ); + $cache->flush_group_cache(); + $new_strings = $new_string_package->get_package_strings(); + foreach ( $new_strings as $new_string ) { + + if ( isset( $translated_original_strings[ $new_string->name ] ) ) { + foreach ( $translated_original_strings[ $new_string->name ] as $language => $translated_string ) { + + do_action( + 'wpml_add_string_translation', + $new_string->id, + $language, + $translated_string['value'], + $translated_string['status'] + ); + + } + } + + } + + } + + } + } + } +} + +?> \ No newline at end of file diff --git a/donate.png b/donate.png new file mode 100644 index 0000000000000000000000000000000000000000..5d0f15dda8dc6026157a1622f9bde8766dc66752 GIT binary patch literal 3207 zcmaJ^dpwhEA0Nt4@i>IS%u@Xs2l9XdA zhbXC>lAOt566V-DJ=OF6@%G-I`@XO1`h9-i@9*^e=Spy}-?L3*rw9N5*k)^k!SPmW z-UkvAvZEU+ipheAU`W-6;8V2T$SLeR&;unbGGFU2N2 zkn9w0k0*uukqo^crY2zHP!x}VN@fwkp;Uhw6BUYv{NP3L_8Vp>1pLE=<%fp+laveA z0c=SRB!l&}b+t$^I2?>XXv6jN5eWEhunr8a1BLNkgce*6rH?@AAi+N$2rpWomp2NB zvHls0cS1vaSu6$$3JnPf(GJnorU&{!;f98W8yq@1T09ReW*Ch{4Ar7Bm47i{$V^fo zg~6iGY2Xb;q9;9wg@*7l{ig&f<2Nmh`Lj*DhCxG#3@BV1wo%eAM=bXLyHcsYy_qZ= z`QLp1CovNr#vns+WF|c*ki;9DxAI0P2Ffy!Ok~jm@pQWXuP!?H(phw-FP#ClbV7jD zu|yJuwqeltfxu!>wlpS-NF$MLF=z;nLz_bJLg|=W!Qe=1i~$m61&3Q946HG5D;-?~ z(!d<1Yk)EQg~iZGK~yr0^$Y9uFV^ah*bOmI8NA3Cav&v`>}4HDr-FYJjiUTH7mGjg z{lt3xITy=6Vxhcbpc|w8uTlRp@$|E?{ViPH;kWe3G@jlAdBUb5tY!fKp(R_4IX<*| z($&vj>ce&u-7oXS*D52bsq*sv(J{$#{DP-D zs+;|2xY+u1^!Q>gv#p{&K9{?xNXn8(0K4#cyQWmS=plV)K5?`_Ue zX0t-C^Pz?!-VSBpo_SH|_Ak{E0c*Rn1eC}NK$im}Duy0O$bYvO$1OMF? zXcK?h_o8jGQEyTS1Z+fB{)6+U99ClQJyA{OBj=|jT0A!jk+7oH|(ogYN*Tc)RE;^1f;3yLp77X%dX{|l67_qKwmIdveat! z#U}BAtxpGWXW3z8!HyaG`Q3Z|PHNG0IkVfyuaq(>Mj`>=E_3f?rYo(Y7;gt-OeYJY z@4u^vTe4lzYExNV>ECiQ*!=m-m|XPzXydmg^VqD<^_m~QI%Ck<3n>SbDqWLFpevkL zHEM@rVDV)SzWS=ZNxPX}!Ct+7xJSvfPq=P?e^TQJ@Gja38)dN*vHWP1J66c519}YI{NQ|Oog@3F`U`9lbdXd z4H9IM!8a=hw??NebZe<*s(u9ROxvCNnC&o_ZLqR^vbftWyLJ8*l`{%;`#e6sSXY(* z(2qK^Rw}%dMI_Ns{%%Luv-?j52}gWlfc%4vN`ir%5Mirb>*yzSHWZS91NU^u_wFBh#_jBHuxwX-$_)1l#8uy%VtW2`-&jLYX`=yn(Ex>m#*tKB)EZZURz4kvNzW^?&6 z`}x4C|Gpd6Y6g!G{ZSgM0YggT&g!z;!1N%IZ=xv|&j#G{0W^usyt&%*vR9g~x9~xZ z;<(&=q))KYZjX*=(PLxWCcOlyaYZXb3jW1@)G?1^?x>E;tO+yD4!hUeB~@20UJ^+> zdFL3Q=}e5tAU|kP;1;H$6=l4&d1xRm583^KMO~sz?xY)k{=(0DH?hGH37Yb$V+I$JyDz~N{@dC zQT&#BvOTLRK(shFMs)KC3bj<&Ubc@`-l?9?#@mWc?RmWCZ_N`V zr)L?O5DEM8L)W?RH?81XVLprS6jZOYF^ERVDraa=zccvTGU zj-t#cDhpp5shJN!91Y&q5`_eE3?CIdB<*yE*hcS8S zm{Lp{=UvsrF^FQi$NkTrN_P^1WZTUlHo$}j(?>;P*HybIz;b1gfm{Wl5(UrKAD(@F zNOHXUQmE%yWA`4v1CQKNueP5eo)Z=Vq;td{+jhaC6HvpLY|o^IWC7A~naSF%eR={P zQVRCl?HJS-+>x=p!(41b@Oo1D zd@JEhRw_s}EZAW98FE2;=hlIm%Z|c}*e9Uf4PD;JR`R0M}XBEg39M-MAXqTG?ZYEj*(C1G4d#o&W#< literal 0 HcmV?d00001 diff --git a/duplicate-post-admin.php b/duplicate-post-admin.php new file mode 100644 index 0000000..a46681c --- /dev/null +++ b/duplicate-post-admin.php @@ -0,0 +1,722 @@ + 'editor', + 8 => 'administrator', + ); + + // Cycle all roles and assign capability if its level >= duplicate_post_copy_user_level + foreach ($default_roles as $level => $name){ + $role = get_role($name); + if(!empty($role)) $role->add_cap( 'copy_posts' ); + } + } else { + $min_user_level = get_option('duplicate_post_copy_user_level'); + + if (!empty($min_user_level)){ + // Get default roles + $default_roles = array( + 1 => 'contributor', + 2 => 'author', + 3 => 'editor', + 8 => 'administrator', + ); + + // Cycle all roles and assign capability if its level >= duplicate_post_copy_user_level + foreach ($default_roles as $level => $name){ + $role = get_role($name); + if ($role && $min_user_level <= $level) + $role->add_cap( 'copy_posts' ); + } + delete_option('duplicate_post_copy_user_level'); + } + } + + + 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',array()); + add_option('duplicate_post_blacklist',''); + add_option('duplicate_post_types_enabled',array('post', 'page')); + add_option('duplicate_post_show_row','1'); + add_option('duplicate_post_show_adminbar','1'); + add_option('duplicate_post_show_submitbox','1'); + add_option('duplicate_post_show_bulkactions','1'); + + $taxonomies_blacklist = get_option('duplicate_post_taxonomies_blacklist'); + if ($taxonomies_blacklist == "") $taxonomies_blacklist = array(); + if(in_array('post_format',$taxonomies_blacklist)){ + update_option('duplicate_post_copyformat', 0); + $taxonomies_blacklist = array_diff($taxonomies_blacklist, array('post_format')); + update_option('duplicate_post_taxonomies_blacklist', $taxonomies_blacklist); + } + + $meta_blacklist = explode(",",get_option('duplicate_post_blacklist')); + if ($meta_blacklist == "") $meta_blacklist = array(); + $meta_blacklist = array_map('trim', $meta_blacklist); + if(in_array('_wp_page_template', $meta_blacklist)){ + update_option('duplicate_post_copytemplate', 0); + $meta_blacklist = array_diff($meta_blacklist, array('_wp_page_template')); + } + if(in_array('_thumbnail_id', $meta_blacklist)){ + update_option('duplicate_post_copythumbnail', 0); + $meta_blacklist = array_diff($meta_blacklist, array('_thumbnail_id')); + } + update_option('duplicate_post_blacklist', implode(',',$meta_blacklist)); + + delete_option('duplicate_post_admin_user_level'); + delete_option('duplicate_post_create_user_level'); + delete_option('duplicate_post_view_user_level'); + delete_option('dp_notice'); + + delete_site_option('duplicate_post_version'); + update_option( 'duplicate_post_version', duplicate_post_get_current_version() ); + + delete_option('duplicate_post_show_notice', 0); + update_site_option('duplicate_post_show_notice', 1); + +} + +/** + * Shows the update notice + */ +function duplicate_post_show_update_notice() { + if(!current_user_can( 'manage_options')) return; + $class = 'notice is-dismissible'; + $message = ''.sprintf(__("What's new in Duplicate Post version %s:", 'duplicate-post'), DUPLICATE_POST_CURRENT_VERSION).'
'; + $message .= esc_html__('Simple compatibility with Gutenberg user interface: enable "Admin bar" under the Settings', 'duplicate-post').' โ€” '.esc_html__('"Slug" option unset by default on new installations', 'duplicate-post').'
'; + $message .= ''.esc_html__('Check out the documentation', 'duplicate-post').' โ€” '.sprintf(__('Please review the settings to make sure it works as you expect.', 'duplicate-post'), admin_url('options-general.php?page=duplicatepost')).'
'; + $message .= esc_html__('Serving the WordPress community since November 2007.', 'duplicate-post').' '.sprintf(wp_kses(__('Help me develop the plugin and provide support by donating even a small sum.', 'duplicate-post'), array( 'a' => array( 'href' => array() ) ) ), "https://duplicate-post.lopo.it/donate").''; + global $wp_version; + if( version_compare($wp_version, '4.2') < 0 ){ + $message .= ' | '.__('Dismiss this notice.').''; + } + echo '

'.$message.'

'; + echo ""; +} + +function duplicate_post_dismiss_notice() { + $result = update_site_option('duplicate_post_show_notice', 0); + return $result; + wp_die(); +} + +/** + * Add the link to action list for post_row_actions + */ +function duplicate_post_make_duplicate_link_row($actions, $post) { + if (duplicate_post_is_current_user_allowed_to_copy() && duplicate_post_is_post_type_enabled($post->post_type)) { + $actions['clone'] = '' . esc_html__('Clone', 'duplicate-post') . ''; + $actions['edit_as_new_draft'] = '' . esc_html__('New Draft', 'duplicate-post') . ''; + } + return $actions; +} + +/** + * Add a button in the post/page edit screen to create a clone + */ +function duplicate_post_add_duplicate_post_button() { + if ( isset( $_GET['post'] )){ + $id = $_GET['post']; + $post = get_post($id); + if(duplicate_post_is_current_user_allowed_to_copy() && duplicate_post_is_post_type_enabled($post->post_type)) { + ?> +
+ + +
+ 1, 'ids' => $post->ID), $sendback ) ); + } else { + // Redirect to the edit screen for the new draft post + wp_redirect( add_query_arg( array( 'cloned' => 1, 'ids' => $post->ID), admin_url( 'post.php?action=edit&post=' . $new_id ) ) ); + } + exit; + + } else { + wp_die(esc_html__('Copy creation failed, could not find original:', 'duplicate-post') . ' ' . htmlspecialchars($id)); + } +} + +/** + * Copy the taxonomies of a post to another post + */ +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)){ + $post_taxonomies[] = 'post_format'; + } + + $taxonomies_blacklist = get_option('duplicate_post_taxonomies_blacklist'); + if ($taxonomies_blacklist == "") $taxonomies_blacklist = array(); + if(get_option('duplicate_post_copyformat') == 0){ + $taxonomies_blacklist[] = 'post_format'; + } + $taxonomies = array_diff($post_taxonomies, $taxonomies_blacklist); + foreach ($taxonomies as $taxonomy) { + $post_terms = wp_get_object_terms($post->ID, $taxonomy, array( 'orderby' => 'term_order' )); + $terms = array(); + for ($i=0; $islug; + } + wp_set_object_terms($new_id, $terms, $taxonomy); + } + } +} + +/** + * Copy the meta information of a post to another post +*/ +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 = array(); + } 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 + if(get_option('duplicate_post_copytemplate') == 0){ + $meta_blacklist[] = '_wp_page_template'; + } + if(get_option('duplicate_post_copythumbnail') == 0){ + $meta_blacklist[] = '_thumbnail_id'; + } + + $meta_blacklist = apply_filters( 'duplicate_post_blacklist_filter' , $meta_blacklist ); + + $meta_blacklist_string = '('.implode(')|(',$meta_blacklist).')'; + if(strpos($meta_blacklist_string, '*') !== false){ + $meta_blacklist_string = str_replace(array('*'), array('[a-zA-Z0-9_]*'), $meta_blacklist_string); + + $meta_keys = array(); + 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); + } + + $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) + */ +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 ); + } +} + +function duplicate_post_addslashes_to_strings_only( $value ) { + return is_string( $value ) ? addslashes( $value ) : $value; +} + +function duplicate_post_wp_slash( $value ) { + return duplicate_post_addslashes_deep( $value ); +} + + + +/** + * Copy the attachments +*/ +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(array( '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 ) ) { + @unlink($tmp); + continue; + } + + $desc = wp_slash($child->post_content); + + $file_array = 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 = array( + '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(get_option('duplicate_post_copythumbnail') == 1 && $old_thumbnail_id == $child->ID){ + set_post_thumbnail($new_id, $new_attachment_id); + } + + } +} + +/** + * Copy children posts + */ +function duplicate_post_copy_children($new_id, $post, $status = ''){ + // get children + $children = get_posts(array( '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; + duplicate_post_create_duplicate($child, $status, $new_id); + } +} + +/** + * Copy comments + */ +function duplicate_post_copy_comments($new_id, $post){ + $comments = get_comments(array( + 'post_id' => $post->ID, + 'order' => 'ASC', + 'orderby' => 'comment_date_gmt' + )); + + $old_id_to_new = array(); + foreach ($comments as $comment){ + //do not copy pingbacks or trackbacks + if(!empty($comment->comment_type)) continue; + $parent = ($comment->comment_parent && $old_id_to_new[$comment->comment_parent])?$old_id_to_new[$comment->comment_parent]:0; + $commentdata = array( + '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_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(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); + $old_id_to_new[$comment->comment_ID] = $new_comment_id; + } +} + +/** + * Create a duplicate from a post + */ +function duplicate_post_create_duplicate($post, $status = '', $parent_id = '') { + + do_action('duplicate_post_pre_copy'); + + 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')); + + $new_post_status = (empty($status))? $post->post_status: $status; + + 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')); + $title = ' '; + if (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); + + if ($title == ''){ + // empty title + $title = __('Untitled'); + } + if (get_option('duplicate_post_copystatus') == 0){ + $new_post_status = 'draft'; + } else { + if ( 'publish' == $new_post_status || 'future' == $new_post_status ){ + // 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'; + } + } else { + if(!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 ( 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; + } + } else { + if(current_user_can('edit_others_posts')){ + $new_post_author_id = $post->post_author; + } + } + } + + $menu_order = (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(get_option('duplicate_post_copyslug') != 1){ + $post_name = ''; + } + + $new_post = array( + 'menu_order' => $menu_order, + 'comment_status' => $post->comment_status, + 'ping_status' => $post->ping_status, + 'post_author' => $new_post_author_id, + 'post_content' => (get_option('duplicate_post_copycontent') == '1') ? $post->post_content : "" , + 'post_content_filtered' => (get_option('duplicate_post_copycontent') == '1') ? $post->post_content_filtered : "" , + 'post_excerpt' => (get_option('duplicate_post_copyexcerpt') == '1') ? $post->post_excerpt : "", + 'post_mime_type' => $post->post_mime_type, + 'post_parent' => $new_post_parent = empty($parent_id)? $post->post_parent : $parent_id, + 'post_password' => (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(get_option('duplicate_post_copydate') == 1){ + $new_post['post_date'] = $new_post_date = $post->post_date ; + $new_post['post_date_gmt'] = get_gmt_from_date($new_post_date); + } + + $new_post_id = wp_insert_post(wp_slash($new_post)); + + // 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); + + do_action('duplicate_post_post_copy'); + + } + + return $new_post_id; +} + +//Add some links on the plugin page +function duplicate_post_add_plugin_links($links, $file) { + if ( $file == plugin_basename(dirname(__FILE__).'/duplicate-post.php') ) { + $links[] = '' . esc_html__('Documentation', 'duplicate-post') . ''; + $links[] = '' . esc_html__('Donate', 'duplicate-post') . ''; + } + return $links; +} + +/*** NOTICES ***/ +function duplicate_post_action_admin_notice() { + if ( ! empty( $_REQUEST['cloned'] ) ) { + $copied_posts = intval( $_REQUEST['cloned'] ); + printf( '

' . + _n( '%s item copied.', + '%s items copied.', + $copied_posts, + 'duplicate-post' + ) . '

', $copied_posts ); + remove_query_arg( 'cloned' ); + } +} + + +/*** BULK ACTIONS ***/ +add_action('admin_init', 'duplicate_post_add_bulk_filters_for_enabled_post_types'); + +function duplicate_post_add_bulk_filters_for_enabled_post_types(){ + if(get_option('duplicate_post_show_bulkactions') != 1) return; + $duplicate_post_types_enabled = get_option('duplicate_post_types_enabled', array ('post', 'page')); + if(!is_array($duplicate_post_types_enabled)) $duplicate_post_types_enabled = array($duplicate_post_types_enabled); + foreach($duplicate_post_types_enabled as $duplicate_post_type_enabled){ + add_filter( "bulk_actions-edit-{$duplicate_post_type_enabled}", 'duplicate_post_register_bulk_action' ); + add_filter( "handle_bulk_actions-edit-{$duplicate_post_type_enabled}", 'duplicate_post_action_handler', 10, 3 ); + } +} + +function duplicate_post_register_bulk_action($bulk_actions) { + $bulk_actions['duplicate_post_clone'] = esc_html__( 'Clone', 'duplicate-post'); + return $bulk_actions; +} + +function duplicate_post_action_handler( $redirect_to, $doaction, $post_ids ) { + if ( $doaction !== 'duplicate_post_clone' ) { + return $redirect_to; + } + $counter = 0; + foreach ( $post_ids as $post_id ) { + $post = get_post($post_id); + if(!empty($post)){ + if( get_option('duplicate_post_copychildren') != 1 + || !is_post_type_hierarchical( $post->post_type ) + || (is_post_type_hierarchical( $post->post_type ) && !duplicate_post_has_ancestors_marked($post, $post_ids))){ + if(duplicate_post_create_duplicate($post)){ + $counter++; + } + } + } + } + $redirect_to = add_query_arg( 'cloned', $counter, $redirect_to ); + return $redirect_to; +} + +function duplicate_post_has_ancestors_marked($post, $post_ids){ + $ancestors_in_array = 0; + $parent = $post->ID; + while ($parent = wp_get_post_parent_id($parent)){ + if(in_array($parent, $post_ids)){ + $ancestors_in_array++; + } + } + return ($ancestors_in_array !== 0); +} diff --git a/duplicate-post-common.php b/duplicate-post-common.php new file mode 100644 index 0000000..a102d37 --- /dev/null +++ b/duplicate-post-common.php @@ -0,0 +1,171 @@ +post_type)) + return; + + if ($draft) + $action_name = "duplicate_post_save_as_new_post_draft"; + else + $action_name = "duplicate_post_save_as_new_post"; + + if ( 'display' == $context ) + $action = '?action='.$action_name.'&post='.$post->ID; + else + $action = '?action='.$action_name.'&post='.$post->ID; + + $post_type_object = get_post_type_object( $post->post_type ); + if ( !$post_type_object ) + return; + + return wp_nonce_url(apply_filters( 'duplicate_post_get_clone_post_link', admin_url( "admin.php". $action ), $post->ID, $context ), 'duplicate-post_' . $post->ID); +} +/** + * Display duplicate post link for post. + * + * @param string $link Optional. Anchor text. + * @param string $before Optional. Display before edit link. + * @param string $after Optional. Display after edit link. + * @param int $id Optional. Post ID. + */ +function duplicate_post_clone_post_link( $link = null, $before = '', $after = '', $id = 0 ) { + if ( !$post = get_post( $id ) ) + return; + + if ( !$url = duplicate_post_get_clone_post_link( $post->ID ) ) + return; + + if ( null === $link ) + $link = esc_html__('Copy to a new draft', 'duplicate-post'); + + $link = '' . $link . ''; + echo $before . apply_filters( 'duplicate_post_clone_post_link', $link, $post->ID ) . $after; +} +/** + * Get original post . + * + * @param int $post Optional. Post ID or Post object. + * @param string $output Optional, default is Object. Either OBJECT, ARRAY_A, or ARRAY_N. + * @return mixed Post data + */ +function duplicate_post_get_original($post = null , $output = OBJECT){ + if ( !$post = get_post( $post ) ) + return; + $original_ID = get_post_meta( $post->ID, '_dp_original'); + if (empty($original_ID)) return null; + $original_post = get_post($original_ID[0], $output); + return $original_post; +} + +// Admin bar +function duplicate_post_admin_bar_render() { + if(!is_admin_bar_showing()) return; + global $wp_admin_bar; + $current_object = get_queried_object(); + if ( !empty($current_object) ){ + if ( ! empty( $current_object->post_type ) + && ( $post_type_object = get_post_type_object( $current_object->post_type ) ) + && duplicate_post_is_current_user_allowed_to_copy() + && ( $post_type_object->show_ui || 'attachment' == $current_object->post_type ) + && (duplicate_post_is_post_type_enabled($current_object->post_type) ) ) + { + $wp_admin_bar->add_menu( array( + 'id' => 'new_draft', + 'title' => esc_attr__("Copy to a new draft", 'duplicate-post'), + 'href' => duplicate_post_get_clone_post_link( $current_object->ID ) + ) ); + } + } else if ( is_admin() && isset( $_GET['post'] )){ + $id = $_GET['post']; + $post = get_post($id); + if( duplicate_post_is_current_user_allowed_to_copy() + && duplicate_post_is_post_type_enabled($post->post_type)) { + $wp_admin_bar->add_menu( array( + 'id' => 'new_draft', + 'title' => esc_attr__("Copy to a new draft", 'duplicate-post'), + 'href' => duplicate_post_get_clone_post_link( $id ) + ) ); + } + } +} + +function duplicate_post_add_css() { + if(!is_admin_bar_showing()) return; + $current_object = get_queried_object(); + if ( !empty($current_object) ){ + if ( ! empty( $current_object->post_type ) + && ( $post_type_object = get_post_type_object( $current_object->post_type ) ) + && duplicate_post_is_current_user_allowed_to_copy() + && ( $post_type_object->show_ui || 'attachment' == $current_object->post_type ) + && (duplicate_post_is_post_type_enabled($current_object->post_type) ) ) + { + wp_enqueue_style ( 'duplicate-post', plugins_url('/duplicate-post.css', __FILE__)); + } + } else if ( is_admin() && isset( $_GET['post'] )){ + $id = $_GET['post']; + $post = get_post($id); + if( duplicate_post_is_current_user_allowed_to_copy() + && duplicate_post_is_post_type_enabled($post->post_type)) { + wp_enqueue_style ( 'duplicate-post', plugins_url('/duplicate-post.css', __FILE__)); + } + } +} + + +add_action('init', 'duplicate_post_init'); + +function duplicate_post_init(){ + if (get_option ( 'duplicate_post_show_adminbar' ) == 1) { + add_action ( 'wp_before_admin_bar_render', 'duplicate_post_admin_bar_render' ); + add_action ( 'wp_enqueue_scripts', 'duplicate_post_add_css' ); + add_action ( 'admin_enqueue_scripts', 'duplicate_post_add_css' ); + } +} + +/** + * Sort taxonomy objects: first public, then private + */ +function duplicate_post_tax_obj_cmp($a, $b) { + return ($a->public < $b->public); +} \ No newline at end of file diff --git a/duplicate-post-options.php b/duplicate-post-options.php new file mode 100644 index 0000000..b55900d --- /dev/null +++ b/duplicate-post-options.php @@ -0,0 +1,395 @@ +get_names(); + + $dp_roles = get_option('duplicate_post_roles'); + if ( $dp_roles == "" ) $dp_roles = array(); + + foreach ($roles as $name => $display_name){ + $role = get_role($name); + + // role should have at least edit_posts capability + if ( !$role->has_cap('edit_posts') ) continue; + + /* If the role doesn't have the capability and it was selected, add it. */ + if ( !$role->has_cap( 'copy_posts' ) && in_array($name, $dp_roles) ) + $role->add_cap( 'copy_posts' ); + + /* If the role has the capability and it wasn't selected, remove it. */ + elseif ( $role->has_cap( 'copy_posts' ) && !in_array($name, $dp_roles) ) + $role->remove_cap( 'copy_posts' ); + } + } + ?> +
+
+
+
+

+ +

+ +
+

+ +
+ +
+ +
+ + - + - +

+
+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ + + +
+ + + +
+
+ +
+

+ + +
name == 'post_format'){ + continue; + } + ?> + +
+
+
+ + + + + + + + + + + +
+ get_names(); + foreach ($roles as $name => $display_name): $role = get_role($name); + if ( !$role->has_cap('edit_posts') ) continue; ?>
+ +
+
+ true),'objects'); + foreach ($post_types as $post_type_object ) : + if ($post_type_object->name == 'attachment') continue; ?> +
+
+
+
+
+ + + + + + + + + + + + +
+ + + + = 0 ){ ?> + + +
+
here', 'duplicate-post'), 'https://duplicate-post.lopo.it/docs/developers-guide/functions-template-tags/duplicate_post_clone_post_link/'); ?> +
+
+ "/> +
+
+

+ +

+ +
+
+ \ No newline at end of file diff --git a/duplicate-post.css b/duplicate-post.css new file mode 100644 index 0000000..64b9e7b --- /dev/null +++ b/duplicate-post.css @@ -0,0 +1,32 @@ +#wpadminbar #wp-admin-bar-new_draft > .ab-item::before { + content: url("data:image/svg+xml;utf8,"); + top: 2px; +} + +@media screen and (max-width: 782px){ + #wpadminbar li#wp-admin-bar-new_draft{ + display: block; + } + + #wpadminbar #wp-admin-bar-new_draft > .ab-item { + text-indent: 100%; + white-space: nowrap; + overflow: hidden; + width: 52px; + padding: 0; + color: #999; + position: relative; + } + + #wpadminbar #wp-admin-bar-new_draft > .ab-item::before { + display: block; + text-indent: 0; + font: 400 32px/1 dashicons; + speak: none; + top: 0px; + width: 52px; + text-align: center; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } +} \ No newline at end of file diff --git a/duplicate-post.php b/duplicate-post.php new file mode 100644 index 0000000..299fd23 --- /dev/null +++ b/duplicate-post.php @@ -0,0 +1,57 @@ +".esc_html__("Settings").""); + return $actions; +} + +require_once (dirname(__FILE__).'/duplicate-post-common.php'); + +if (is_admin()){ + require_once (dirname(__FILE__).'/duplicate-post-admin.php'); +} \ No newline at end of file diff --git a/gpl-2.0.txt b/gpl-2.0.txt new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/gpl-2.0.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..c62d4bf --- /dev/null +++ b/readme.txt @@ -0,0 +1,313 @@ +=== Duplicate Post === +Contributors: lopo +Donate link: https://duplicate-post.lopo.it/ +Tags: duplicate post, copy, clone +Requires at least: 3.6 +Tested up to: 4.9 +Stable tag: 3.2.2 +Requires PHP: 5.2.4 +License: GPLv2 or later +License URI: http://www.gnu.org/licenses/gpl-2.0.html + +Copy posts of any type with a click! + +== Description == + +This plugin allows users to clone posts of any type, or copy them to new drafts for further editing. +If you find this useful, [**please consider donating**](https://duplicate-post.lopo.it/) whatever sum you choose, **even just 10 cents**. Just a few cents from every user would help me develop the plugin and improve support. + +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 [the plugin's site](https://duplicate-post.lopo.it). + +**If you're a plugin developer**, I suggest you to read the [Developer's Guide](https://duplicate-post.lopo.it/docs/developers-guide/) to ensure compatibility between your plugin(s) and mine. Feel free to [contact me](https://duplicate-post.lopo.it/contact) so we can keep in touch and collaborate. + +Duplicate Post does not collect any information outside your WordPress installation, therefore it's 100% GDPR compliant. + +Thanks for all the suggestions, bug reports, translations and donations, they're frankly too many to be listed here! + +== 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 untraslated strings, you can help traslating to your language [here](https://translate.wordpress.org/projects/wp-plugins/duplicate-post): you only need a WordPress.org account. +[Contact me](https://duplicate-post.lopo.it/contact) if you wish to become an editor for your language. + +== Screenshots == + +1. Here you can copy the post you're editing to a new draft. +2. By clicking on "Clone" the post is cloned immediately. "New draft" leads to the edit screen. +3. The options page. +4. The template tag manually added to Twenty Ten theme. Click on the "Copy to a new draft" link and you're redirected to the edit screen for a new draft copy of your post. +5. The admin bar link. +6. Bulk clone action. + +== Upgrade Notice == + += 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 == + += 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 three ways: + + 1. You can [write me](https://duplicate-post.lopo.it/contact) and submit your bug reports, suggestions and requests for features; + 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); + 3. Using the plugin is free, but if you want you can support my efforts by donating with PayPal [here](https://duplicate-post.lopo.it/donate)