WordPress Tipps #6 – Post kopieren/duplizieren

Eine oft vermisste Funktion in WordPress ist das Kopieren/Duplizieren von Beiträgen und Seiten. Da WordPress diese Funktionen standardmässig leider nicht anbietet, muss man diese mit einem Plugin oder ein bisschen Code selber implementieren. In diesem sechsten Teil unserer WordPress-Tipps zeigen wir dir, wie du eine Kopier- bzw. Duplizierfunktion für Beiträge, Seiten und eigene Post-Types implementieren kannst.

Mit den folgenden Tipps werden die Post-Listen um zwei Funktionen erweitert: Einer Bulk-Aktion um mehrere Posts gleichzeitig zu duplizieren und eine Post-Aktion in der Liste für jeden einzelnen Post.

Die folgenden Code-Snippets können im functions.php des gewünschten Themes oder in einem eigenen Plugin hinterlegt werden.

Link für Post-Aktion hinzufügen

Zuerst erstellen wir einen Aktions-Link für die Post-Listen (wie schon in einem älteren Beitrag ausführlich erklärt). Mit dem folgenden Snippet wird bei den bereits vorhandenen Aktionen in der Post-Liste ein „Duplizieren“-Link eingefügt:

<span class="token keyword">function</span> <span class="token function">post_row_actions_duplicate</span><span class="token punctuation">(</span><span class="token variable">$actions</span><span class="token punctuation">,</span> <span class="token variable">$post</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">current_user_can</span><span class="token punctuation">(</span><span class="token string">'edit_posts'</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token variable">$duplicate_link</span> <span class="token operator">=</span> <span class="token function">admin_url</span><span class="token punctuation">(</span><span class="token string">'admin.php?action=duplicate-post&post='</span> <span class="token punctuation">.</span> <span class="token variable">$post</span><span class="token operator">-</span><span class="token operator">></span><span class="token property">ID</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token variable">$actions</span><span class="token punctuation">[</span><span class="token string">'duplicate'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">'<a href="'</span> <span class="token punctuation">.</span> <span class="token variable">$duplicate_link</span> <span class="token punctuation">.</span> <span class="token string">'" title="Dieses Element duplizieren">Duplizieren</a>'</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">return</span> <span class="token variable">$actions</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">add_filter</span><span class="token punctuation">(</span><span class="token string">'post_row_actions'</span><span class="token punctuation">,</span> <span class="token string">'post_row_actions_duplicate'</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Beitrag und eigene, nicht-hierarchische Post-Types</span>
<span class="token comment">//add_filter('page_row_actions', 'post_row_actions_duplicate', 10, 2); // Seiten und eigene, hierarchische Post-Types</span>

Dieser Hook erstellt den Link für alle Post-Types. Wenn er nur für einen bestimmten Post-Type angezeigt werden sollte (z.B. project, kann das if erweitert werden um eine Abfrage wie $post->post_type == 'project'.

Bulk-Aktion hinzufügen

Zusätzlich kann auch eine Bulk-Aktion hinzugefügt werden (auch in einem älteren Beitrag ausführlich erklärt), um mehrere Posts auf einmal zu duplizieren. Der folgende Code fügt eine neue Aktion „Duplizieren“ in die beiden Bulk-Dropdown-Menüs hinzu.

<span class="token keyword">function</span> <span class="token function">bulk_action_add_duplicate</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">echo</span> '<span class="token operator"><</span>script type<span class="token operator">=</span><span class="token string">"text/javascript"</span><span class="token operator">></span>
        <span class="token function">jQuery</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token function">jQuery</span><span class="token punctuation">(</span><span class="token string">'<option value="duplicate">Duplizieren</option>'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">appendTo</span><span class="token punctuation">(</span><span class="token string">'select[name="action"]'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token function">jQuery</span><span class="token punctuation">(</span><span class="token string">'<option value="duplicate">Duplizieren</option>'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">appendTo</span><span class="token punctuation">(</span><span class="token string">'select[name="action2"]'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator"><</span><span class="token operator">/</span>script<span class="token operator">></span>'<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">add_action</span><span class="token punctuation">(</span><span class="token string">'admin_footer-edit.php'</span><span class="token punctuation">,</span> <span class="token string">'bulk_action_add_duplicate'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">bulk_action_duplicate</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// Security check</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">isset</span><span class="token punctuation">(</span><span class="token variable">$_GET</span><span class="token punctuation">[</span><span class="token string">'_wpnonce'</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token operator">!</span><span class="token function">wp_verify_nonce</span><span class="token punctuation">(</span><span class="token variable">$_GET</span><span class="token punctuation">[</span><span class="token string">'_wpnonce'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token string">'bulk-posts'</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">_get_list_table</span><span class="token punctuation">(</span><span class="token string">'WP_Posts_List_Table'</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">current_action</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token string">'duplicate'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// Ein Array mit allen ausgewählten Post IDs</span>
        <span class="token variable">$post_ids</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token function">isset</span><span class="token punctuation">(</span><span class="token variable">$_GET</span><span class="token punctuation">[</span><span class="token string">'post'</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token variable">$_GET</span><span class="token punctuation">[</span><span class="token string">'post'</span><span class="token punctuation">]</span> <span class="token punctuation">:</span> <span class="token keyword">array</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// Zur eigentlichen Aktion weiterleiten</span>
        <span class="token function">wp_redirect</span><span class="token punctuation">(</span><span class="token function">admin_url</span><span class="token punctuation">(</span><span class="token string">'admin.php?action=duplicate-post&post='</span> <span class="token punctuation">.</span> <span class="token function">implode</span><span class="token punctuation">(</span><span class="token string">','</span><span class="token punctuation">,</span> <span class="token variable">$post_ids</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        exit<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token function">add_action</span><span class="token punctuation">(</span><span class="token string">'load-edit.php'</span><span class="token punctuation">,</span> <span class="token string">'bulk_action_duplicate'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

Aktion ausführen

Jetzt müssen wir noch die Aktion selber definieren. Diese Aktion kopiert einen oder mehrere Posts, die dazugehörigen Post-Meta-Daten und die zugewiesenen Taxonomies. Am Ende wird zurück auf die Post-Liste (wenn mehrere Posts dupliziert wurden) oder auf die Edit-Seite des duplizierten Posts (wenn nur ein Post dupliziert wurde) weitergeleitet:

<span class="token keyword">function</span> <span class="token function">admin_action_duplicate_post</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">global</span> <span class="token variable">$wpdb</span><span class="token punctuation">;</span>

    <span class="token comment">// Aktion überspringen wenn keine Berechtigung oder keine Post-IDs definiert wurden</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">current_user_can</span><span class="token punctuation">(</span><span class="token string">'edit_posts'</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token operator">!</span><span class="token function">isset</span><span class="token punctuation">(</span><span class="token variable">$_GET</span><span class="token punctuation">[</span><span class="token string">'post'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">wp_redirect</span><span class="token punctuation">(</span><span class="token variable">$_SERVER</span><span class="token punctuation">[</span><span class="token string">'HTTP_REFERER'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        exit<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// Alle Post-IDs auslesen</span>
    <span class="token variable">$post_ids</span> <span class="token operator">=</span>  <span class="token function">explode</span><span class="token punctuation">(</span><span class="token string">','</span><span class="token punctuation">,</span> <span class="token variable">$_GET</span><span class="token punctuation">[</span><span class="token string">'post'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token variable">$post_duplicate_count</span> <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>

    <span class="token keyword">foreach</span><span class="token punctuation">(</span><span class="token variable">$post_ids</span> <span class="token keyword">as</span> <span class="token variable">$post_id</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token variable">$post</span> <span class="token operator">=</span> <span class="token function">get_post</span><span class="token punctuation">(</span><span class="token variable">$post_id</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// Aktion überspringen wenn Originalpost nicht existiert</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">is_null</span><span class="token punctuation">(</span><span class="token variable">$post</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">continue</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token comment">// Post für das Duplizieren vorbereiten</span>
        <span class="token variable">$post_new</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">array</span><span class="token punctuation">)</span><span class="token variable">$post</span><span class="token punctuation">;</span>

        <span class="token comment">// Suffix "(Kopie)" an Post-Titel anhängen</span>
        <span class="token variable">$post_new</span><span class="token punctuation">[</span><span class="token string">'post_title'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token variable">$post_new</span><span class="token punctuation">[</span><span class="token string">'post_title'</span><span class="token punctuation">]</span> <span class="token punctuation">.</span> <span class="token string">' (Kopie)'</span><span class="token punctuation">;</span>

        <span class="token comment">// Post-Status auf "draft" (Entwurf) setzen</span>
        <span class="token variable">$post_new</span><span class="token punctuation">[</span><span class="token string">'post_status'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">'draft'</span><span class="token punctuation">;</span>

        <span class="token comment">// Post-Infos entfernen die wir nicht übernehmen wollen</span>
        <span class="token function">unset</span><span class="token punctuation">(</span><span class="token variable">$post_new</span><span class="token punctuation">[</span><span class="token string">'ID'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">unset</span><span class="token punctuation">(</span><span class="token variable">$post_new</span><span class="token punctuation">[</span><span class="token string">'post_author'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">unset</span><span class="token punctuation">(</span><span class="token variable">$post_new</span><span class="token punctuation">[</span><span class="token string">'post_date'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">unset</span><span class="token punctuation">(</span><span class="token variable">$post_new</span><span class="token punctuation">[</span><span class="token string">'post_date_gmt'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">unset</span><span class="token punctuation">(</span><span class="token variable">$post_new</span><span class="token punctuation">[</span><span class="token string">'post_name'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">unset</span><span class="token punctuation">(</span><span class="token variable">$post_new</span><span class="token punctuation">[</span><span class="token string">'post_modified'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">unset</span><span class="token punctuation">(</span><span class="token variable">$post_new</span><span class="token punctuation">[</span><span class="token string">'post_modified_gmt'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">unset</span><span class="token punctuation">(</span><span class="token variable">$post_new</span><span class="token punctuation">[</span><span class="token string">'guid'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// Post duplizieren</span>
        <span class="token variable">$post_id_new</span> <span class="token operator">=</span> <span class="token function">wp_insert_post</span><span class="token punctuation">(</span><span class="token variable">$post_new</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// Aktion überspringen wenn das Duplizieren fehlgeschlagen ist</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token variable">$post_id_new</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">continue</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token comment">// Postmeta kopieren und zuweisen</span>
        <span class="token variable">$wpdb</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">query</span><span class="token punctuation">(</span>"
            <span class="token constant">INSERT</span> <span class="token constant">INTO</span> <span class="token variable">$wpdb</span><span class="token operator">-</span><span class="token operator">></span><span class="token property">postmeta</span> <span class="token punctuation">(</span>post_id<span class="token punctuation">,</span> meta_key<span class="token punctuation">,</span> meta_value<span class="token punctuation">)</span>
                <span class="token constant">SELECT</span> <span class="token variable">$post_id_new</span><span class="token punctuation">,</span> meta_key<span class="token punctuation">,</span> meta_value
                <span class="token constant">FROM</span> <span class="token variable">$wpdb</span><span class="token operator">-</span><span class="token operator">></span><span class="token property">postmeta</span>
                <span class="token constant">WHERE</span> post_id <span class="token operator">=</span> <span class="token variable">$post_id</span>
        "<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">// Taxonomies und Terms zuweisen</span>
        <span class="token variable">$post_taxonomies</span> <span class="token operator">=</span> <span class="token function">get_object_taxonomies</span><span class="token punctuation">(</span><span class="token variable">$post</span><span class="token operator">-</span><span class="token operator">></span><span class="token property">post_type</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">foreach</span><span class="token punctuation">(</span><span class="token variable">$post_taxonomies</span> <span class="token keyword">as</span> <span class="token variable">$taxonomy</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token variable">$terms</span> <span class="token operator">=</span> <span class="token function">wp_get_object_terms</span><span class="token punctuation">(</span><span class="token variable">$post_id</span><span class="token punctuation">,</span> <span class="token variable">$taxonomy</span><span class="token punctuation">,</span> <span class="token keyword">array</span><span class="token punctuation">(</span><span class="token string">'fields'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token string">'ids'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token function">wp_set_object_terms</span><span class="token punctuation">(</span><span class="token variable">$post_id_new</span><span class="token punctuation">,</span> <span class="token variable">$terms</span><span class="token punctuation">,</span> <span class="token variable">$taxonomy</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token comment">// Erfolgreiches Duplizieren zählen</span>
        <span class="token variable">$post_duplicate_count</span><span class="token operator">++</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token variable">$post_duplicate_count</span> <span class="token operator">!==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// Zurück zur Liste wenn keiner oder mehr als ein Posts dupliziert wurden</span>
        <span class="token function">wp_redirect</span><span class="token punctuation">(</span><span class="token variable">$_SERVER</span><span class="token punctuation">[</span><span class="token string">'HTTP_REFERER'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        <span class="token comment">// Zur Adminseite des duplizierten Posts weiterleiten</span>
        <span class="token function">wp_redirect</span><span class="token punctuation">(</span><span class="token function">admin_url</span><span class="token punctuation">(</span><span class="token string">'post.php?action=edit&post='</span> <span class="token punctuation">.</span> <span class="token variable">$post_id_new</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    exit<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">add_action</span><span class="token punctuation">(</span><span class="token string">'admin_action_duplicate-post'</span><span class="token punctuation">,</span> <span class="token string">'admin_action_duplicate_post'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

Rekursives Duplizieren

In diesem Beitrag zeigen wir dir nur, wie man einzelne Post ohne Hierarchie dupliziert. Wenn also eine Seite mit Unterseiten dupliziert wird, werden die Unterseiten nicht rekursiv mitkopiert.

Noch mehr Tipps …

… folgen in den nächsten Wochen. Bis dahin stellen wir dir wieder ein paar nützliche WordPress-Tipps zusammen.

Andere WordPress Tipps

Schlagwörter:

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.