it-swarm.com.de

Hinzufügen eines benutzerdefinierten Inhaltsvorlagenteils für einen benutzerdefinierten Beitragstyp in der Hauptabfrage mithilfe eines Plugins

Ich habe einen benutzerdefinierten Beitragstyp paper in meinem WordPress-Plugin definiert, den ich zusammen mit Standardbeiträgen in der Hauptabfrage zeige:

function add_custom_post_types_to_query( $query ) {
    if ( is_home() && $query->is_main_query() )
        $query->set( 'post_type', array( 'post', 'paper' ) );
    // As was pointed out by Ihor Vorotnov this return is not necessary. 
    // return $query;
}
add_action( 'pre_get_posts', 'add_custom_post_types_to_query' );

Ich konnte auch eine benutzerdefinierte single-paper.php-Vorlage aus dem Plugin-Verzeichnis für meinen Beitragstyp registrieren:

function get_custom_post_type_single_template( $single_template ) {
     global $post;

     if ( $post->post_type == 'paper' ) {
          $single_template = dirname( __FILE__ ) . '/single-paper.php';
     }
     return $single_template;
}
add_filter( 'single_template', 'get_custom_post_type_single_template' );

Ich möchte etwas Ähnliches für die Vorlage content-____.php tun, die von meinem Thema (onepress) verwendet wird, um zu steuern, wie meine Beiträge in der Hauptabfrage angezeigt werden.

Der index.php des Themas sagt sogar:

<?php /* Start the Loop */ ?>
<?php while ( have_posts() ) : the_post(); ?>

<?php

    /*
     * Include the Post-Format-specific template for the content.
     * If you want to override this in a child theme, then include a file
     * called content-___.php (where ___ is the Post Format name) and that will be used instead.
     */
    get_template_part( 'template-parts/content', get_post_format() );
    ?>

<?php endwhile; ?>

aber ich möchte lieber kein untergeordnetes Thema dafür implementieren und den gesamten Code, der sich auf den benutzerdefinierten Beitragstyp bezieht, im Plugin behalten.

Gibt es eine Möglichkeit, einen Filter so hinzuzufügen, dass get_template_part( 'template-parts/content', get_post_format() ); eine benutzerdefinierte Vorlage verwendet, die von meinem Plugin für paper Posts bereitgestellt wird, und die Standardvorlage des Themas für normale Posts?

Ich habe verschiedene Varianten des Codes ausprobiert, den ich oben für den 'single_template' verwendet habe, aber ohne Erfolg.

6
cgogolin

Hintergrund

Leider hat get_template_part() function keinen geeigneten Filter, um das zu erreichen, was Sie wollen. Es ist möglich, den Aktions-Hook get_template_part_{$slug} zum Einfügen von Vorlagenteilen zu verwenden. Ohne Änderungen an Ihrem Thema oder einem untergeordneten Thema wird der ursprüngliche Vorlagenteil jedoch trotzdem hinzugefügt. Auf diese Weise können Sie vorhandene Schablonenteile nicht ersetzen.

Sie können jedoch das gewünschte Ergebnis erzielen, indem Sie eine der folgenden Optionen wählen:


Option 1: Verwenden Sie die Standard-CSS-Klassen:

Wenn Sie nur den Stil für den benutzerdefinierten Beitragstyp paper ändern möchten, können Sie einfach die von WordPress generierte CSS-Klasse verwenden. Jedes Standardthema in WordPress generiert $post_type- und type-{$post_type}-CSS-Klassen für den Beitragsinhalt. Der benutzerdefinierte Beitragstyp paper hat beispielsweise paper & type-paper CSS-Klassen, und der allgemeine post hat post und type-post CSS-Klassen. Auch auf der Homepage befindet sich die CSS-Klasse home im Body. Um paper-Einträge auf der Homepage auszurichten, können Sie die folgenden CSS-Regeln verwenden:

body.home .type-paper {
    /* Custom CSS for paper entries in the home page */
}

Option 2: CSS-Klassen ändern:

Wenn Ihnen die Standard-CSS-Klassen nicht ausreichen, können Sie CSS-Klassen auch mit dem post_class filter-Hook in Ihrem Plugin ändern (hinzufügen/entfernen). So was:

add_filter( 'post_class', 'paper_post_class' );
function paper_post_class( $class ) {
    if ( get_post_type() === 'paper' && is_home() ) {

        // remove these classes
        $remove = array( 'css-class-to-remove', 'another-class-to-remove' );
        $class = array_diff( $class, $remove );

        // add these classes
        $add = array( 'custom-paper', 'my-paper-class' );
        $class = array_merge( $add, $class );
    }
    return $class;
}

Auf diese Weise können Sie nicht benötigte CSS-Klassen für paper -Einträge entfernen und neue CSS-Klassen für paper -Einträge hinzufügen, ohne die Designdateien zu ändern. Verwenden Sie dann diese CSS-Klassen, um den Stil von paper-Einträgen nach Bedarf zu ändern.


Option 3: Ändern der Vorlage und der Vorlagenteile

Wenn Ihr gewünschter Stil nicht nur durch Targeting von CSS-Klassen geändert werden kann, können Sie die Template-Teile auch über Ihr Plugin ändern. Da das Ersetzen von durch get_template_part() hinzugefügten Vorlagenteilen durch Hooks nicht möglich ist, müssen Sie die Vorlage so ändern, dass Sie den Aufruf von get_template_part() über das Plugin ändern können.

Zu diesem Zweck können Sie Ihre Hook-Funktion auf pre_get_posts ausrichten und mit template_include filter hook die Homepage-Vorlage wie folgt ändern:

function add_custom_post_types_to_query( $query ) {
    if ( is_home() && $query->is_main_query() ) {
        $query->set( 'post_type', array( 'post', 'paper' ) );

        // now also change the home page template, but only when this condition matches
        add_filter( 'template_include', 'wpse258844_custom_template', 999 );
    }
}
add_action( 'pre_get_posts', 'add_custom_post_types_to_query' ); 

Verwenden Sie dann den folgenden CODE (ändern Sie ihn nach Bedarf):

// for better file management, use a separate "theme-{$theme_name_slug}" directory within your plugin directory
// so if the active theme name is "OnePress", the directory name will be "theme-onepress"
// This will save you a ton of headache if you change the theme,
// as different themes may use different function calls within the templates, which other themes may not have
define( 'wpse258844_TEMPLATE_DIR', plugin_dir_path( __FILE__ ) . sprintf( 'theme-%s/', sanitize_title( wp_get_theme() ) ) );

function wpse258844_custom_template( $template ) {
    // this file will replace your homepage template file
    $index_paper = wpse258844_TEMPLATE_DIR . 'custom-home.php';

    // file_exists() check may need clearing stat cache if you change file name, delete the file etc.
    // Once you are done, comment out or remove clearstatcache(); in production
    clearstatcache();

    if ( file_exists( $index_paper ) ) {
        $template = $index_paper;
    }
    return $template;
}

function wpse258844_get_template_part( $slug, $name = null ) {
    if( get_post_type() === 'paper' ) {

        // just to be consistant with get_template_part() function
        do_action( "get_template_part_{$slug}", $slug, $name );

        $located = '';
        $name = (string) $name;

        // file_exists() check may need clearing stat cache if you change file name, delete the file etc.
        // Once you are done, comment out or remove clearstatcache(); in production
        clearstatcache();

        if ( '' !== $name && file_exists( wpse258844_TEMPLATE_DIR . "{$slug}-{$name}.php" ) ) {
            $located = wpse258844_TEMPLATE_DIR . "{$slug}-{$name}.php";
        }
        else if ( file_exists( wpse258844_TEMPLATE_DIR . "{$slug}.php" ) ) {
            $located = wpse258844_TEMPLATE_DIR . "{$slug}.php";
        }

        if ( '' != $located ) {
            load_template( $located, false );
            return;
        }
    }

    get_template_part( $slug, $name );
}

Sobald du den obigen CODE in deinem Plugin hast (lies die Kommentare im CODE):

  1. Erstellen Sie ein neues Verzeichnis in Ihrem Plugin-Verzeichnis, um die Theme-Vorlagendateien zu speichern, z. theme-onepress. Dies wird Ihnen in Zukunft helfen, wenn Sie Designänderungen mit einem anderen Thema testen möchten (ich nehme an, das ist der Hauptzweck all dieser Probleme;)).

  2. Erstellen Sie im neuen Verzeichnis theme-onepress eine Datei mit dem Namen custom-home.php. Kopieren Sie den CODE der Homepage-Vorlage aus Ihrem Thema (möglicherweise index.php oder home.php oder was auch immer Ihr Thema für die Homepage-Vorlage verwendet).

  3. Ändern Sie jetzt in custom-home.php den gesamten Aufruf von get_template_part in wpse258844_get_template_part. Der Parameter muss nicht geändert werden, nur der Funktionsname. Die Funktion wpse258844_get_template_part() im obigen CODE ist identisch mit der Funktion get_template_part() und greift auf das Standardverhalten zurück, wenn der benutzerdefinierte Vorlagenteil nicht im Verzeichnis theme-{$theme_name_slug} (z. B. theme-onepress) Ihres Plugins gefunden wird.

  4. Ersetzen Sie abschließend die Vorlagenteile, die Sie ersetzen möchten, im Verzeichnis theme-{$theme_name_slug} Ihres Plugins.

    Wenn der ursprüngliche Aufruf beispielsweise get_template_part( 'template-parts/content', get_post_format() ) war und Sie den content.php-Vorlagenteil ersetzen möchten, platzieren Sie einfach eine Datei mit dem Namen content.php im theme-onepress/template-parts-Verzeichnis Ihres Plugins. Das heißt, das Verzeichnis theme-onepress verhält sich wie ein untergeordnetes Thema für Vorlagenteile - d. H. Einfaches Ersetzen durch Drop-In.

7
Fayaz

erstelle deine eigene Funktion dafür:

function get_template_part_custom($content_name) {
     global $post;
     //its paper type?
     if ($post->post_type == 'paper') {
         //get template-parts/content-paper.php
         get_template_part( 'template-parts/content', $content_name );
     }else{
         //fallback to the default
         get_template_part( 'template-parts/content', get_post_format($post) );
     }
}

benutze es so:

get_template_part_custom('paper');

wenn der Beitrag vom Typ paper ist, wird versucht, eine Datei mit dem Namen content-paper.php in einen Ordner mit dem Namen template-parts im Stammverzeichnis zu laden. Wenn die Datei nicht vorhanden ist, wird versucht, content.php zu laden, überprüfen Sie die Vorlagenhierarchie . Ich glaube nicht, dass Sie Ihre Vorlage registrieren müssen single-paper.php, WordPress wird es für Sie abholen.

BEARBEITEN:

So laden Sie eine Vorlage aus einem Plugin:

//load a custom file from the plugin
add_filter( 'template_include', 'return_our_template');

//Returns template file
function return_our_template( $template ) {

    // Post ID
    $post_id = get_the_ID();

    // For all other Types that arent ours
    if ( get_post_type( $post_id ) != 'paper' ) {
        return $template;
    }

    // Else use our custom template
    if ( is_single() ) {
        return get_custom_template( 'single' );
    }

}

//Get the custom template if is set
function get_custom_template( $template ) {

    // Get the slug
    $template_slug = rtrim( $template, '.php' );
    $template = $template_slug . '.php';

    // Check if a custom template exists in the theme folder, if not, load the plugin template file
    if ( $theme_file = locate_template( array( 'plugin_template/' . $template ) ) ) {
        $file = $theme_file;
    }
    else {
        //here path to '/single-paper.php'
        $file = PATH_TO_YOUR_BASE_DIR . $template;
    }
    //create a new filter so the devs can filter this
    return apply_filters( 'filter_template_' . $template, $file );
}
0
David Lee

Soweit ich aus dem Quellcode ersehen kann, können Sie get_template_part() nicht so filtern, wie Sie es normalerweise tun würden. Bitte lesen Sie diesen Thread für einige Lösungen.

0
Ihor Vorotnov

Hier ist ein weiterer "Hack", um das zu erreichen, wonach gefragt wurde:

Mit dem post format (nicht zu verwechseln mit dem post type!) Kann eine benutzerdefinierte Vorlage für einen benutzerdefinierten Beitragstyp verwendet werden. Erinnere dich an die Linie

get_template_part( 'template-parts/content', get_post_format() );

im index.php beschrieben in der frage. Durch diese Konstruktion laden die meisten Standard-Themes je nach post format unterschiedliche Vorlagen.

Man kann behaupten, dass alle Beiträge eines bestimmten benutzerdefinierten Beitragstyps, z. B. papername__, ein bestimmtes Beitragsformat haben, z. B. asidename__, indem man aufruft

set_post_format( $post_id, 'aside' )

während der a-Funktion, die in den 'save_post'-Hook eingebunden ist, und indem Sie so etwas wie hinzufügen

function paper_format_terms( $terms, $post_id, $tax ) {
    if ( 'post_format' === $tax && empty( $terms ) && 'paper' === get_post_type( $post_id ) ) {
        $aside = get_term_by( 'slug', 'post-format-aside', $tax );
        $terms = array( $aside );
    }
    return $terms;
}
add_filter( 'get_the_terms', 'paper_format_terms', 10, 3 );

zum 'get_the_terms' hook.

Man kann keine benutzerdefinierten Postformate definieren, aber normalerweise gibt es mindestens ein Postformat, das für nichts anderes verwendet wird. Das "beiseite" -Format kann eine gute Wahl sein.

Ein Standarddesign sucht dann, wenn es auf einen papername__-Beitrag stößt, nach der Vorlage .../template-parts/content-aside.php. Alles, was Sie tun müssen, ist, eine geeignete Vorlage so in das Theme-Verzeichnis zu installieren, dass sie beim Aktualisieren des Themas nicht überschrieben oder gelöscht wird (wir möchten, dass der gesamte Code im Plugin enthalten ist!). Dies kann getan werden, indem eine geeignete Vorlage in das Feld content-aside.php im Plugins-Verzeichnis eingefügt und wie folgt in `'upgrader_process_complete' 'eingebunden wird

function install_aside_template_on_upgrade( $upgrader_object, $options ) {
    if ($options['type'] == 'theme' ) {
        $content_aside = plugin_dir_path( __FILE__ ) . 'content-aside.php';
        $template_parts_content_aside = get_stylesheet_directory() . '/template-parts/content-aside.php';

        copy($content_aside, $template_parts_content_aside);
    }
}
add_action( 'upgrader_process_complete', 'install_aside_template_on_upgrade',10, 2);

Auf diese Weise wird der content-aside.php nach jeder Aktualisierung des Themas in das Themenverzeichnis kopiert.

Denken Sie daran, dass dies ein ziemlich schrecklicher Hack ist und unerwünschte Nebenwirkungen haben kann! Trotzdem dachte ich, dass dies für einige nützlich sein kann ...

0
cgogolin

Obwohl dies keine genaue Antwort auf die gestellte Frage ist, gibt es noch einen anderen, recht übersichtlichen und einfachen Weg, um etwas Ähnliches zu erreichen, das, wie ich vermute, für viele Leute, die auf dieser Seite landen, die tatsächlich optimale Lösung sein wird. Für mich haben sich die Anforderungen geringfügig geändert, nachdem ich diese Frage gestellt hatte, sodass ich mich am Ende für diese Lösung entschieden habe.

Anstatt ein benutzerdefiniertes Thema zu verwenden, reicht es in vielen Fällen aus, zu ändern, was ein benutzerdefinierter Beitragstyp zurückgibt, wenn die Vorlage des Themas the_excerpt() aufruft. Dies kann erreicht werden, indem Sie sich wie folgt in den 'the_excerpt'-Filter einhängen:

function paper_get_the_excerpt ($content) {
    global $post;
    $post_id = $post->ID;
    if ( get_post_type($post_id) === 'paper' ) {
        [do whatever you want with $content]
    }
    return $content;
}
add_filter( 'the_excerpt', 'paper_get_the_excerpt' );

Schön, sauber und einfach und ermöglicht fast so viel Flexibilität wie das Ändern der Vorlage.

0
cgogolin