Erstellen Sie eine benutzerdefinierte Archivseite für einen benutzerdefinierten Beitragstyp in einem Plugin

11

Ich schreibe ein Plugin, das einen benutzerdefinierten Beitragstyp mit dem Namen "my_plugin_lesson" erstellt:

$args = array (
    'public' => true,
    'has_archive' => true,
    'rewrite' => array('slug' => 'lessons', 'with_front' => false)
);
register_post_type ('my_plugin_lesson', $args);

Der benutzerdefinierte Beitragstyp verfügt über ein Archiv und die URL des Archivs lautet:

http://example.com/lessons

Ich möchte das Aussehen dieses Archivs anpassen. Ich möchte die Beiträge in einem Tabellenformat auflisten und nicht im Standardarchiv für WordPress-Blogbeiträge. Ich verstehe, dass eine benutzerdefinierte Archivvorlage im Thema erstellt werden kann, indem die archive-my_plugin_lesson.phpDatei erstellt wird. Ich möchte jedoch, dass das Plugin mit jedem Thema funktioniert.

Wie kann ich den Inhalt der Archivseite ändern, ohne Themendateien hinzuzufügen oder zu ändern?

Bearbeiten: Ich verstehe, dass ich den archive_templateFilterhaken verwenden könnte. Dies ersetzt jedoch nur die Themenvorlage, die noch themenspezifisch sein muss. Zum Beispiel gerade über jedes Thema Vorlage muß das get_header, get_sidebarund get_footerFunktionen, aber was sollte die ID des Inhalts <div>sein? Dies ist in jedem Thema anders.

Ich möchte den Inhalt selbst durch meinen eigenen Inhalt ersetzen und diesen anstelle der Archivseite für meinen benutzerdefinierten Beitragstyp verwenden.

Ben Miller - Erinnere dich an Monica
quelle

Antworten:

12

Was Sie brauchen, ist template_includeFilter einbinden und selektiv Ihre Vorlage in Plugin laden.

Wenn Sie Ihr Plugin verteilen möchten, sollten Sie als bewährte Methode prüfen, ob archive-my_plugin_lesson.php(oder möglicherweise myplugin/archive-lesson.php) ein Thema vorhanden ist, wenn Sie die Plugin-Version nicht verwenden.

Auf diese Weise können Benutzer die Vorlage einfach über ein Thema (oder ein untergeordnetes Thema) ersetzen, ohne den Plugin-Code zu bearbeiten.

Dies ist die Methode, die von gängigen Plugins, z. B. WooCommmerce, verwendet wird, um nur einen Namen zu nennen.

add_filter('template_include', 'lessons_template');

function lessons_template( $template ) {
  if ( is_post_type_archive('my_plugin_lesson') ) {
    $theme_files = array('archive-my_plugin_lesson.php', 'myplugin/archive-lesson.php');
    $exists_in_theme = locate_template($theme_files, false);
    if ( $exists_in_theme != '' ) {
      return $exists_in_theme;
    } else {
      return plugin_dir_path(__FILE__) . 'archive-lesson.php';
    }
  }
  return $template;
}

Weitere Infos zum Codex für

gmazzap
quelle
Dies ersetzt immer noch nur die Vorlagendatei des Themas, oder? Was füge ich in die Datei archive-Lesson.php meines Plugins ein? Es müsste anders sein, um mit jedem Thema zu arbeiten. Selbst die Standardthemen "Zwanzig" stimmen nicht darin überein, welche Div / Section-Container den Inhalt umgeben.
Ben Miller - Erinnern Sie sich an Monica
7

Sie können den archive_templateHook verwenden, um den Inhalt der Archivvorlage eines Themas mithilfe des folgenden Schemas zu verarbeiten. Natürlich können Sie jedoch immer nur einen Bruchteil der dortigen Themen verarbeiten, da eine Vorlage im Grunde genommen alles Alte enthalten kann .

Das Schema besteht darin, die Vorlage in eine Zeichenfolge ( $tpl_str) im archive_templateFilter zu laden , Ihren Inhalt zu ersetzen, die Zeichenfolge einzuschließen (mit dem Trick eval( '?>' . $tpl_str );) und dann eine leere Datei zurückzugeben, sodass die Datei includein "wp-includes / template-loader.php" wird ein No-Op.

Im Folgenden finden Sie eine gehackte Version des Codes, den ich in einem Plugin verwende. Diese Version zielt auf "klassische" Vorlagen ab, die diese verwenden, get_template_partund befasst sich mehr mit der Verarbeitung einzelner Vorlagen als mit der Archivierung, soll Ihnen jedoch den Einstieg erleichtern. Das Setup besteht darin, dass das Plugin ein Unterverzeichnis namens "Templates" hat, das eine leere Datei ("null.php") und Inhaltsvorlagen (z. B. "content-single-posttype1.php", "content-archive-postype1.php") enthält. sowie eine Fallback-Vorlage "single.php" für den Einzelfall und verwendet eine benutzerdefinierte Version davon get_template_part, die in diesem Verzeichnis angezeigt wird .

define( 'MYPLUGIN_FOLDER', dirname( __FILE__ ) . '/' );
define( 'MYPLUGIN_BASENAME', basename( MYPLUGIN_FOLDER ) );

add_filter( 'single_template', 'myplugin_single_template' );
add_filter( 'archive_template', 'myplugin_archive_template' );

function myplugin_single_template( $template ) {
    static $using_null = array();

    // Adjust with your custom post types.
    $post_types = array( 'posttype1', );

    if ( is_single() || is_archive() ) {
        $template_basename = basename( $template );
        // This check can be removed.
        if ( $template == '' || substr( $template_basename, 0, 4 ) == 'sing' || substr( $template_basename, 0, 4 ) == 'arch' ) {
            $post_type = get_post_type();
            $slug = is_archive() ? 'archive' : 'single';
            if ( in_array( $post_type, $post_types ) ) {
                // Allow user to override.
                if ( $single_template = myplugin_get_template( $slug, $post_type ) ) {
                    $template = $single_template;
                } else {
                    // If haven't gone through all this before...
                    if ( empty( $using_null[$slug][$post_type] ) ) {
                        if ( $template && ( $content_template = myplugin_get_template( 'content-' . $slug, $post_type ) ) ) {
                            $tpl_str = file_get_contents( $template );
                            // You'll have to adjust these regexs to your own case - good luck!
                            if ( preg_match( '/get_template_part\s*\(\s*\'content\'\s*,\s*\'' . $slug . '\'\s*\)/', $tpl_str, $matches, PREG_OFFSET_CAPTURE )
                            || preg_match( '/get_template_part\s*\(\s*\'content\'\s*,\s*get_post_format\s*\(\s*\)\s*\)/', $tpl_str, $matches, PREG_OFFSET_CAPTURE )
                            || preg_match( '/get_template_part\s*\(\s*\'content\'\s*\)/', $tpl_str, $matches, PREG_OFFSET_CAPTURE )
                            || preg_match( '/get_template_part\s*\(\s*\'[^\']+\'\s*,\s*\'' . $slug . '\'\s*\)/', $tpl_str, $matches, PREG_OFFSET_CAPTURE ) ) {
                                $using_null[$slug][$post_type] = true;
                                $tpl_str = substr( $tpl_str, 0, $matches[0][1] ) . 'include \'' . $content_template . '\'' . substr( $tpl_str, $matches[0][1] + strlen( $matches[0][0] ) );
                                // This trick includes the $tpl_str.
                                eval( '?>' . $tpl_str );
                            }
                        }
                    }
                    if ( empty( $using_null[$slug][$post_type] ) ) {
                        // Failed to parse - look for fall back template.
                        if ( file_exists( MYPLUGIN_FOLDER . 'templates/' . $slug . '.php' ) ) {
                            $template = MYPLUGIN_FOLDER . 'templates/' . $slug . '.php';
                        }
                    } else {
                        // Success! "null.php" is just a blank zero-byte file.
                        $template = MYPLUGIN_FOLDER . 'templates/null.php';
                    }
                }
            }
        }
    }
    return $template;
}

function myplugin_archive_template( $template ) {
    return myplugin_single_template( $template );
}

Der Brauch get_template_part:

/*
 * Version of WP get_template_part() that looks in theme, then parent theme, and finally in plugin template directory (sub-directory "templates").
 * Also looks initially in "myplugin" sub-directory if any in theme and parent theme directories so that plugin templates can be kept separate.
 */
function myplugin_get_template( $slug, $part = '' ) {
    $template = $slug . ( $part ? '-' . $part : '' ) . '.php';

    $dirs = array();

    if ( is_child_theme() ) {
        $child_dir = get_stylesheet_directory() . '/';
        $dirs[] = $child_dir . MYPLUGIN_BASENAME . '/';
        $dirs[] = $child_dir;
    }

    $template_dir = get_template_directory() . '/';
    $dirs[] = $template_dir . MYPLUGIN_BASENAME . '/';
    $dirs[] = $template_dir;
    $dirs[] = MYPLUGIN_FOLDER . 'templates/';

    foreach ( $dirs as $dir ) {
        if ( file_exists( $dir . $template ) ) {
            return $dir . $template;
        }
    }
    return false;
}

Der Vollständigkeit halber hier das Fallback "single.php", das den Brauch verwendet get_template_part:

<?php
get_header(); ?>

    <div id="primary" class="content-area">
        <div id="content" class="clearfix">
            <?php while ( have_posts() ) : the_post(); ?>

            <?php if ( $template = myplugin_get_template( 'content-single', get_post_type() ) ) include $template; else get_template_part( 'content', 'single' ); ?>

                <?php
                    // If comments are open or we have at least one comment, load up the comment template
                    if ( comments_open() || '0' != get_comments_number() ) :
                        comments_template();
                    endif;
                ?>

            <?php endwhile; ?>

        </div><!-- #content -->
    </div><!-- #primary -->

<?php get_sidebar(); ?>
<?php get_footer(); ?>
Bonger
quelle
1

Ich habe über dieselbe Frage nachgedacht, und dies ist die hypothetische Lösung, die ich mir ausgedacht habe:

  • Erstellen Sie im Plugin einen Shortcode, der Ihre Archivschleife wie gewünscht ausgibt.
  • Aktivieren Sie beim Erstellen des benutzerdefinierten Beitragstyps nicht die Option "Archivieren".
  • Fügen Sie ein Stylesheet hinzu, das alle Stile Ihres Loop-Inhalts steuert.

Erstellen Sie bei der Plugin-Aktivierung eine Seite mit wp_insert_post, wobei der Name der Beitragstyp und der Inhalt der Shortcode ist.

Sie können im Shortcode Optionen für zusätzliche Stilüberlegungen bereitstellen oder dem Postcontainer Klassen hinzufügen, die themenspezifischen oder benutzerdefinierten Stilen entsprechen. Der Benutzer kann auch zusätzlichen Inhalt vor / nach der Schleife hinzufügen, indem er die Seite bearbeitet.

SkyShab
quelle
Obwohl ich nicht der OP bin, suchte ich nach einer Lösung für das gleiche Problem. Ich habe Ihre hypotetische Lösung befolgt und kann jetzt bestätigen, dass sie auch in der Praxis funktioniert.
Lucio Crusca
Hey toll! Ich bin froh, dass dies für jemanden nützlich war. Ich hatte das völlig vergessen.
SkyShab
0

Sie können den Filter verwenden single_template. Ein grundlegendes Beispiel aus dem Codex :

function get_custom_post_type_template($single_template) {
     global $post;

     if ($post->post_type == 'my_post_type') {
          $single_template = dirname( __FILE__ ) . '/post-type-template.php';
     }
     return $single_template;
}

add_filter( "single_template", "get_custom_post_type_template" );
Eyal
quelle
Ich denke, der Filterhaken für eine Archivvorlage ist archive_template, aber ich denke nicht, dass dies für das funktioniert, was ich versuche zu tun. Ich habe meine Frage mit weiteren Informationen bearbeitet.
Ben Miller - Erinnern Sie sich an Monica