Skip to main content
Signocore
// signocore clone docs

Hooks

Every filter and action in Signocore Clone, with examples for excluding meta keys and changing clone titles.

Signocore Clone passes the data of every clone through filters and fires an action once a clone is made, so a theme or a small plugin can change what gets copied without editing the plugin. Add callbacks with add_filter() and add_action() from your theme's functions.php or a must-use plugin. Every hook name starts with signocore_clone_.

The hooks run the same way whether a clone starts from the Clone link, the bulk action or the editor box, and in a bulk action they run once for each post. WooCommerce products are the exception: WooCommerce's own duplicate feature clones them, so the post hooks below do not run for products. To act on a cloned product, use WooCommerce's woocommerce_product_duplicate action, which fires after each product clone with the new and the original product.

Return the type listed for each filter. When signocore_clone_post_data or signocore_clone_term_data returns something other than an array, the clone is not created and the user sees an error notice.

No hooks match "".

Posts

These hooks run for posts, pages, custom post types and WooCommerce coupons. The meta key and taxonomy filters only run when Meta data and Taxonomies are on under Settings → Signocore Clone.

Filters the post data the clone is created with.

The array is passed to wp_insert_post(). It holds post_title (the original title with " (Copy)" added, where "Copy" follows the admin language), post_content, post_status (draft), post_type, post_author, post_excerpt, post_password, post_content_filtered, post_parent, menu_order, post_mime_type, comment_status and ping_status. You can change these or add other wp_insert_post() arguments. Pass values unslashed: the plugin slashes the array before it is saved. Return an array; any other value stops the clone with the notice "We were unable to create the cloned post." Custom fields and terms are copied after the post is created, so they are not part of this array.

Parameter Type Description
$data array Arguments for wp_insert_post().
$original WP_Post The post being cloned.

Returns array The arguments to create the clone with.

add_filter('signocore_clone_post_data', function (array $data, WP_Post $original): array {
    // "Copy of Pricing" instead of "Pricing (Copy)".
    $data['post_title'] = 'Copy of ' . $original->post_title;

    return $data;
}, 10, 2);

Filters the custom field keys that are not copied to a cloned post.

The default list holds editor and trash bookkeeping (_edit_lock, _edit_last, _wp_old_slug, _wp_old_date, _wp_desired_post_slug and the _wp_trash_meta_* keys), WPML's _icl_lang_duplicate_of, Elementor's generated _elementor_css, _elementor_page_assets, _elementor_controls_usage and _elementor_screenshot, and _used_by when the post is a WooCommerce coupon. Add your keys to the list instead of replacing it. Keys are compared exactly, with no wildcards, so list every key you want to skip. Advanced Custom Fields saves each field under its field name and a second key with an underscore in front that points to the field definition, so exclude both. A value that is not an array counts as an empty list, and then every custom field is copied.

Parameter Type Description
$keys array Meta keys to skip.
$original WP_Post The post being cloned.

Returns array Meta keys to skip.

add_filter('signocore_clone_excluded_meta_keys', function (array $keys, WP_Post $original): array {
    // An ACF field named "event_date": its value and its field reference.
    $keys[] = 'event_date';
    $keys[] = '_event_date';

    // A view counter that should start from zero on the clone.
    $keys[] = 'view_count';

    return $keys;
}, 10, 2);

Filters the taxonomies whose terms are not assigned to a cloned post.

By default the list holds Polylang's hidden taxonomies language, post_translations, term_language and term_translations, whether or not Polylang is active. Keep them: copying them would add the clone to the original's translation group. The clone is assigned to the original's existing terms in every other taxonomy of its post type. A value that is not an array counts as an empty list.

Parameter Type Description
$taxonomies array Taxonomy names to skip.
$original WP_Post The post being cloned.

Returns array Taxonomy names to skip.

add_filter('signocore_clone_excluded_taxonomies', function (array $taxonomies, WP_Post $original): array {
    // Cloned blog posts keep their categories but start without tags.
    if ($original->post_type === 'post') {
        $taxonomies[] = 'post_tag';
    }

    return $taxonomies;
}, 10, 2);

Fires after a post has been cloned.

At this point the clone exists, its custom fields and terms are copied as the settings decide, and on a multilingual site its language is set. The action fires once for every clone, including each post in a bulk action, but not for WooCommerce products.

Parameter Type Description
$newPostId int ID of the clone.
$original WP_Post The post that was cloned.
add_action('signocore_clone_post_cloned', function (int $newPostId, WP_Post $original): void {
    // Remember where the clone came from.
    update_post_meta($newPostId, 'cloned_from', $original->ID);

    // Leave the featured image for the editor to choose.
    delete_post_thumbnail($newPostId);
}, 10, 2);

Terms

These hooks run when a category, tag or term of another public taxonomy is cloned. The term meta filter only runs when Meta data is on.

Filters the arguments the cloned term is created with.

The array is passed as $args to wp_insert_term() and holds the original's description and parent. The name is not part of it: the plugin tries "Name (Clone)" first, then "Name (Clone 2)", "Name (Clone 3)" and so on until the name is free. Return an array; any other value stops the clone with the notice "We were unable to create the cloned term."

Parameter Type Description
$args array Arguments for wp_insert_term().
$original WP_Term The term being cloned.

Returns array The arguments to create the clone with.

add_filter('signocore_clone_term_data', function (array $args, WP_Term $original): array {
    // Start every cloned term at the top level, without a description.
    $args['parent'] = 0;
    $args['description'] = '';

    return $args;
}, 10, 2);

Filters the term meta keys that are not copied to a cloned term.

The default list is empty, so every term meta key is copied. Keys are compared exactly, with no wildcards. A value that is not an array counts as an empty list.

Parameter Type Description
$keys array Term meta keys to skip.
$original WP_Term The term being cloned.

Returns array Term meta keys to skip.

add_filter('signocore_clone_excluded_term_meta_keys', function (array $keys, WP_Term $original): array {
    // Cloned product categories start without the category image.
    if ($original->taxonomy === 'product_cat') {
        $keys[] = 'thumbnail_id';
    }

    return $keys;
}, 10, 2);

Fires after a term has been cloned.

At this point the term exists under its new name, its term meta is copied when Meta data is on, and on a multilingual site its language is set. No posts are assigned to it.

Parameter Type Description
$newTermId int ID of the cloned term.
$original WP_Term The term that was cloned.
add_action('signocore_clone_term_cloned', function (int $newTermId, WP_Term $original): void {
    // Remember which term the clone was made from.
    update_term_meta($newTermId, 'cloned_from', $original->term_id);
}, 10, 2);

Policy

These filters decide where cloning is offered and how much one bulk action does. Who may clone is decided by WordPress capabilities: users need to be able to create items of the post type and edit the original.

Filters the post types that are never offered for cloning.

Only post types with an admin screen are considered. The default list holds attachment, WooCommerce's shop_order, shop_order_refund, shop_order_placehold and shop_subscription, and the ACF definitions acf-field-group, acf-field, acf-post-type, acf-taxonomy and acf-ui-options-page. An excluded post type gets no Clone link, bulk action or editor box, and it disappears from Post types in the settings. To switch a post type off without code, use those settings instead. Add to the list rather than replacing it; a value that is not an array restores the default list.

Parameter Type Description
$postTypes array Post type names that can never be cloned.

Returns array Post type names that can never be cloned.

add_filter('signocore_clone_excluded_post_types', function (array $postTypes): array {
    // Invoices are numbered records and must never be duplicated.
    $postTypes[] = 'invoice';

    return $postTypes;
});

Filters the maximum number of posts cloned in one bulk action.

The default is 50, and values below 1 count as 1. Posts selected beyond the limit are not cloned, and the result notice tells the user how many were left. Every post in a bulk action is cloned in the same request, so a high limit can make the request run longer than the server allows. Raise it in small steps.

Parameter Type Description
$limit int Maximum number of posts per bulk action.
$postType string The post type of the list the bulk action runs on.

Returns int The maximum number of posts per bulk action.

add_filter('signocore_clone_bulk_limit', function (int $limit, string $postType): int {
    // Pages are short on this site, so clone up to 100 at a time.
    return $postType === 'page' ? 100 : $limit;
}, 10, 2);

Stuck on something the docs don't cover?

Questions go straight to the developer who builds the plugins. Replies usually within a day.

September Sale

€20 off Signocore SEO Pro

Pay €49 instead of €69, one time for unlimited sites. code SEP20