Buat halaman arsip khusus untuk jenis posting khusus dalam sebuah plugin

11

Saya sedang menulis plugin yang membuat jenis posting khusus bernama "my_plugin_lesson":

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

Jenis pos khusus memiliki arsip, dan URL arsipnya adalah:

http://example.com/lessons

Saya ingin menyesuaikan tampilan arsip ini; Saya ingin daftar posting dalam format tabel, daripada arsip posting blog WordPress standar. Saya mengerti bahwa templat arsip khusus dapat dibuat dalam tema dengan membuat archive-my_plugin_lesson.phpfile; namun, saya ingin plugin berfungsi dengan tema apa pun.

Bagaimana saya bisa mengubah konten halaman arsip tanpa menambahkan atau memodifikasi file tema?

Sunting: Saya mengerti bahwa saya bisa menggunakan archive_templatehook filter. Namun, semua ini dilakukan adalah mengganti templat tema, yang masih harus spesifik tema. Sebagai contoh, hampir setiap tema template yang akan membutuhkan get_header, get_sidebardan get_footerfungsi, tapi apa yang harus id konten <div>menjadi? Ini berbeda di setiap tema.

Yang ingin saya lakukan adalah mengganti konten itu sendiri dengan konten saya sendiri, dan menggunakannya sebagai ganti halaman arsip untuk jenis posting kustom saya.

Ben Miller - Ingat Monica
sumber

Jawaban:

12

Yang Anda butuhkan adalah hooking template_includefilter dan memuat template Anda secara selektif di dalam plugin.

Sebagai praktik yang baik, jika Anda berencana untuk mendistribusikan plugin Anda, Anda harus memeriksa apakah archive-my_plugin_lesson.php(atau mungkin myplugin/archive-lesson.php) ada tema, jika tidak menggunakan versi plugin.

Dengan cara ini mudah bagi pengguna mengganti templat melalui tema (atau tema anak) tanpa mengedit kode plugin.

Ini adalah metode yang digunakan oleh plugin populer, misalnya WooCommmerce, hanya untuk mengatakan satu nama.

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;
}

Info lebih lanjut tentang Codex untuk

gmazzap
sumber
Ini masih hanya menggantikan file templat tema, kan? Apa yang saya masukkan ke file archive-lesson.php plugin saya? Harus berbeda untuk bekerja dengan masing-masing tema. Bahkan tema "Dua Puluh" default tidak menyetujui wadah div / bagian apa yang mengelilingi konten.
Ben Miller - Ingat Monica
7

Anda dapat menggunakan archive_templatekait untuk memproses konten templat arsip tema, dengan menggunakan skema di bawah ini, tetapi jelas Anda hanya akan dapat memproses sebagian kecil dari tema di luar sana, mengingat bahwa templat pada dasarnya dapat berisi benda lama apa pun .

Skema ini memuat template ke string ( $tpl_str) di archive_templatefilter, mengganti konten Anda, memasukkan string (menggunakan trik eval( '?>' . $tpl_str );), dan kemudian mengembalikan file kosong sehingga includedi "wp-include / template-loader.php" menjadi no-op.

Di bawah ini adalah versi kode yang diretas yang saya gunakan dalam sebuah plugin, yang menargetkan templat "klasik" yang digunakan get_template_partdan lebih mementingkan pemrosesan templat tunggal daripada arsip, tetapi akan membantu Anda memulai. Penyiapannya adalah plugin memiliki subdirektori yang disebut "templat" yang menampung file kosong ("null.php") dan templat konten (mis. "Content-single-posttype1.php", "content-archive-postype1.php") serta template mundur "single.php" untuk kasus tunggal, dan menggunakan versi kustom get_template_partyang terlihat di direktori ini.

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 );
}

Kebiasaan 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;
}

Untuk kelengkapan, inilah back back "single.php", yang menggunakan custom 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
sumber
1

Saya telah merenungkan pertanyaan yang sama, dan ini adalah solusi hipotetis yang saya buat:

  • Di dalam plugin, buat kode pendek yang menghasilkan loop arsip Anda seperti yang Anda inginkan.
  • Saat membuat jenis posting khusus, jangan aktifkan opsi 'arsip'.
  • Tambahkan lembar gaya yang mengontrol semua gaya konten loop Anda.

Setelah aktivasi plugin, buat halaman menggunakan wp_insert_post dengan nama menjadi jenis posting dan konten menjadi kode pendek.

Anda dapat memberikan opsi dalam kode pendek untuk pertimbangan gaya tambahan, atau menambahkan kelas ke wadah pos untuk mencocokkan gaya khusus atau gaya khusus. Pengguna juga dapat menambahkan konten tambahan sebelum / sesudah loop dengan mengedit halaman.

SkyShab
sumber
Meskipun saya bukan OP, saya mencari solusi untuk masalah yang sama. Saya telah mengikuti solusi hipotetis Anda dan sekarang saya dapat mengonfirmasi bahwa itu berhasil dalam praktiknya juga.
Lucio Crusca
Hai bagus! Senang ini bermanfaat bagi seseorang. Saya benar-benar lupa tentang ini.
SkyShab
0

Anda bisa menggunakan filter single_template. Contoh dasar yang diambil dari 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
sumber
Saya pikir hook filter untuk template arsip adalah archive_template, tetapi saya tidak berpikir ini akan bekerja untuk apa yang saya coba lakukan. Saya telah mengedit pertanyaan saya dengan informasi lebih lanjut.
Ben Miller - Ingat Monica