# Dupliquer un article ou une page sans extension, métadonnées comprises

> Une extension entière pour dupliquer un article, c'est souvent excessif. Un snippet d'une trentaine de lignes fait le même travail, nonce compris.

- Auteur : Clément Hadrot
- Publié le : 2020-12-30
- Mis à jour le : 2020-12-30
- Catégorie : Tips
- URL : https://wpmoderne.dev.wordpress-developpement.fr/tips/dupliquer-article-page-sans-extension/

## L’essentiel

- Un lien d'action ajouté à la liste des articles
- wp_insert_post recrée le contenu
- Metas et taxonomies sont copiées à la suite

Un client qui publie des fiches produits très proches les unes des autres — même structure, mêmes champs, seul le texte change — finit toujours par demander la même chose : un bouton « Dupliquer ». Les extensions dédiées existent, mais elles ajoutent souvent des réglages inutiles pour un besoin aussi ciblé. Un snippet maison, greffé sur la liste des articles, fait le travail en une trentaine de lignes.

La recette repose sur trois ingrédients : un lien d'action ajouté dans la liste des contenus, une fonction accrochée à `admin_action_{action}` qui reconstruit le contenu avec `wp_insert_post()`, et une copie systématique des métadonnées et des taxonomies associées.

## Ajouter le lien « Dupliquer » dans la liste des articles

Le filtre `post_row_actions` permet d'ajouter une action personnalisée à côté de « Modifier » et « Corbeille » dans la liste des articles. Le lien pointe vers une URL contenant l'identifiant du contenu et un nonce de sécurité.

```
function catalogue_lien_dupliquer( $actions, $post ) {
    if ( ! current_user_can( 'edit_posts' ) ) {
        return $actions;
    }
    $url = wp_nonce_url(
        admin_url( 'admin.php?action=catalogue_dupliquer&post=' . $post->ID ),
        'catalogue_dupliquer_' . $post->ID
    );
    $actions['dupliquer'] = '<a href="' . esc_url( $url ) . '">Dupliquer</a>';
    return $actions;
}
add_filter( 'post_row_actions', 'catalogue_lien_dupliquer', 10, 2 );
```

## Reconstruire le contenu avec wp_insert_post

La fonction accrochée à `admin_action_catalogue_dupliquer` récupère l'article d'origine avec `get_post()`, puis recrée un nouvel article avec les mêmes champs, en préfixant le titre pour distinguer la copie de l'original.

> L'essentiel à retenir : Un lien d'action ajouté à la liste des articles ; wp_insert_post recrée le contenu ; Metas et taxonomies sont copiées à la suite

```
function catalogue_dupliquer_contenu() {
    $post_id = isset( $_GET['post'] ) ? absint( $_GET['post'] ) : 0;
    check_admin_referer( 'catalogue_dupliquer_' . $post_id );

    $original = get_post( $post_id );
    if ( ! $original || ! current_user_can( 'edit_post', $post_id ) ) {
        wp_die( 'Contenu introuvable ou accès refusé.' );
    }

    $nouvel_id = wp_insert_post( array(
        'post_title'   => $original->post_title . ' (copie)',
        'post_content' => $original->post_content,
        'post_excerpt' => $original->post_excerpt,
        'post_status'  => 'draft',
        'post_type'    => $original->post_type,
        'post_author'  => get_current_user_id(),
    ) );

    if ( is_wp_error( $nouvel_id ) ) {
        wp_die( 'Erreur lors de la duplication.' );
    }

    catalogue_copier_metas_et_taxonomies( $post_id, $nouvel_id );

    wp_safe_redirect( admin_url( 'edit.php?post_type=' . $original->post_type ) );
    exit;
}
add_action( 'admin_action_catalogue_dupliquer', 'catalogue_dupliquer_contenu' );
```

## Copier les métadonnées et les taxonomies

Le contenu principal ne suffit pas : les champs personnalisés (prix, référence produit, caractéristiques) et les taxonomies (catégories, étiquettes, taxonomies personnalisées) doivent suivre. WordPress fournit des fonctions dédiées pour chacun.

```
function catalogue_copier_metas_et_taxonomies( $source_id, $cible_id ) {
    // Métadonnées
    $metas = get_post_meta( $source_id );
    foreach ( $metas as $cle => $valeurs ) {
        foreach ( $valeurs as $valeur ) {
            add_post_meta( $cible_id, $cle, maybe_unserialize( $valeur ) );
        }
    }

    // Taxonomies
    $taxonomies = get_object_taxonomies( get_post_type( $source_id ) );
    foreach ( $taxonomies as $taxonomie ) {
        $termes = wp_get_object_terms( $source_id, $taxonomie, array( 'fields' => 'ids' ) );
        wp_set_object_terms( $cible_id, $termes, $taxonomie );
    }
}
```

L'image mise en avant mérite un traitement à part : c'est une simple métadonnée (`_thumbnail_id`), donc elle est déjà copiée par la boucle ci-dessus. Aucun code supplémentaire n'est nécessaire pour elle.

## Éviter les pièges classiques

- Toujours vérifier `current_user_can( 'edit_post', $post_id )` avant la duplication, pas seulement `edit_posts` en général.
- Utiliser `check_admin_referer()` pour valider le nonce, sans quoi n'importe quel lien externe pourrait déclencher une duplication.
- Créer la copie en statut `draft` plutôt qu'en reprenant le statut d'origine, pour éviter de publier accidentellement du contenu en double.

> Sur les CPT avec des champs répétables, je préfère toujours tester la duplication sur un contenu réellement complexe avant de la livrer : c'est là que les métadonnées sérialisées imbriquées font parfois des surprises si `maybe_unserialize()` est oublié.

## En résumé

Trois briques standards de l'API WordPress — `post_row_actions`, `wp_insert_post()` et les fonctions de copie de metas et de taxonomies — suffisent à reproduire l'essentiel d'une extension de duplication, sans dépendance supplémentaire. Le nonce et la vérification de capacité restent les deux points à ne jamais sauter, même sur un snippet qui semble anodin.
