Crea una pagina di archivio personalizzata per un tipo di post personalizzato in un plug-in


11

Sto scrivendo un plugin che crea un tipo di post personalizzato denominato "my_plugin_lesson":

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

Il tipo di post personalizzato ha un archivio e l'URL dell'archivio è:

http://example.com/lessons

Voglio personalizzare l'aspetto di questo archivio; Voglio elencare i post in un formato tabella, piuttosto che nell'archivio dei post sul blog di WordPress standard. Comprendo che è possibile creare un modello di archivio personalizzato nel tema creando il archive-my_plugin_lesson.phpfile; tuttavia, vorrei che il plugin funzionasse con qualsiasi tema.

Come posso alterare il contenuto della pagina di archivio senza aggiungere o modificare i file dei temi?

Modifica: capisco che potrei usare il archive_templategancio del filtro. Tuttavia, tutto ciò che fa è sostituire il modello del tema, che deve ancora essere specifico del tema. Ad esempio, quasi ogni modello di tema avrà bisogno i get_header, get_sidebare le get_footerfunzioni, ma che cosa dovrebbe l'id del contenuto <div>essere? Questo è diverso in ogni tema.

Quello che vorrei fare è sostituire il contenuto stesso con il mio contenuto e usarlo al posto della pagina di archivio per il mio tipo di post personalizzato.

Risposte:


12

Ciò di cui hai bisogno è agganciare il template_includefiltro e caricare selettivamente il tuo modello all'interno del plugin.

Come buona pratica, se prevedi di distribuire il tuo plugin, dovresti controllare se archive-my_plugin_lesson.php(o forse myplugin/archive-lesson.php) esiste nel tema, se non usare la versione del plugin.

In questo modo è facile per gli utenti sostituire il modello tramite tema (o tema figlio) senza modificare il codice del plugin.

Questo è il metodo utilizzato dai plugin più diffusi, ad esempio WooCommmerce, solo per dire un nome.

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

Maggiori informazioni su Codex per


Questo continua a sostituire il file modello del tema, giusto? Cosa metto nel file archive-lezione.php del mio plugin? Dovrebbe essere diverso per lavorare con ciascun tema. Persino i temi "Venti" predefiniti non concordano su quali contenitori div / section siano circondati dal contenuto.
Ben Miller - Ricorda Monica il

7

Puoi usare l' archive_templatehook per elaborare il contenuto del modello di archivio di un tema, usando lo schema seguente, ma ovviamente sarai in grado di elaborare solo una parte dei temi là fuori, dato che un modello può praticamente contenere qualsiasi cosa vecchia .

Lo schema consiste nel caricare il modello in una stringa ( $tpl_str) nel archive_templatefiltro, sostituire il contenuto, includere la stringa (usando il trucco eval( '?>' . $tpl_str );) e quindi restituire un file vuoto in modo che includein "wp-Includes / template-loader.php" diventa un no-op.

Di seguito è riportata una versione compromessa del codice che utilizzo in un plug-in, che si rivolge a modelli "classici" che utilizzano get_template_parte si occupa più dell'elaborazione di singoli modelli che dell'archivio, ma dovrebbe aiutarti a iniziare. L'impostazione è che il plugin ha una sottodirectory denominata "modelli" che contiene un file vuoto ("null.php") e modelli di contenuto (ad esempio "content-single-posttype1.php", "content-archive-postype1.php") così come un modello di fallback "single.php" per il singolo caso, e utilizza una versione personalizzata get_template_partche appare in questa directory.

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

L'abitudine 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;
}

Per completezza ecco il fallback "single.php", che usa l'usanza 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(); ?>

1

Ho riflettuto sulla stessa domanda, e questa è l'ipotetica soluzione che mi è venuta in mente:

  • All'interno del plug-in, crea un shortcode che produca il tuo ciclo di archiviazione come desideri.
  • Quando si crea il tipo di post personalizzato, non abilitare l'opzione 'archivio'.
  • Aggiungi un foglio di stile che controlla tutti gli stili dei contenuti del tuo ciclo.

Dopo l'attivazione del plug-in, crea una pagina utilizzando wp_insert_post con il nome come tipo di post e il contenuto come shortcode.

È possibile fornire opzioni nel shortcode per ulteriori considerazioni sullo stile o aggiungere classi al contenitore di post per abbinare stili specifici o personalizzati per temi. L'utente può anche aggiungere contenuti aggiuntivi prima / dopo il ciclo modificando la pagina.


Nonostante non sia il PO, stavo cercando una soluzione allo stesso problema. Ho seguito la tua ipotetica soluzione e ora posso confermare che funziona anche in pratica.
Lucio Crusca,

Ehi fantastico! Sono contento che sia stato utile per qualcuno. Me ne ero completamente dimenticato.
SkyShab,

0

Puoi usare il filtro single_template. Un esempio di base tratto dal Codice :

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

Penso che l'hook del filtro per un modello di archivio sia archive_template, ma non credo che funzionerà per quello che sto cercando di fare. Ho modificato la mia domanda con ulteriori informazioni.
Ben Miller - Ricorda Monica, il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.