Crie uma página de arquivamento personalizada para um tipo de postagem personalizado em um plug-in

11

Estou escrevendo um plugin que cria um tipo de postagem personalizado chamado "my_plugin_lesson":

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

O tipo de postagem personalizada possui um arquivo e a URL do arquivo é:

http://example.com/lessons

Quero personalizar a aparência deste arquivo; Quero listar as postagens em um formato de tabela, em vez do arquivo padrão de postagem do blog WordPress. Entendo que um modelo de arquivo personalizado pode ser criado no tema criando o archive-my_plugin_lesson.phparquivo; no entanto, gostaria que o plugin funcionasse com qualquer tema.

Como posso alterar o conteúdo da página de arquivo sem adicionar ou modificar arquivos de tema?

Edit: Eu entendo que eu poderia usar o archive_templategancho de filtro. No entanto, tudo isso faz é substituir o modelo de tema, que ainda precisa ser específico do tema. Por exemplo, apenas sobre cada tema modelo terá os get_header, get_sidebare get_footerfunções, mas o que deve o id do conteúdo <div>ser? Isso é diferente em todos os temas.

O que eu gostaria de fazer é substituir o conteúdo em si pelo meu próprio conteúdo e usá-lo no lugar da página de arquivo para o meu tipo de postagem personalizado.

Ben Miller - Lembre-se de Monica
fonte

Respostas:

12

O que você precisa é conectar o template_includefiltro e carregar seletivamente o seu modelo dentro do plug-in.

Como boa prática, se você planeja distribuir seu plug-in, verifique se archive-my_plugin_lesson.php(ou talvez myplugin/archive-lesson.php) existe no tema, se não usar a versão do plug-in.

Dessa maneira, é fácil para os usuários substituirem o modelo por tema (ou tema filho) sem editar o código do plug-in.

Este é o método usado por plugins populares, por exemplo, WooCommmerce, apenas para dizer um 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;
}

Mais informações sobre o Codex for

gmazzap
fonte
Isso ainda substitui o arquivo de modelo do tema, certo? O que coloco no arquivo archive-lesson.php do meu plugin? Seria diferente trabalhar com cada tema. Até os "Vinte" temas padrão não concordam com o que são os contêineres de div / seção que cercam o conteúdo.
Ben Miller - Lembre-se de Monica
7

Você pode usar o archive_templategancho para processar o conteúdo do modelo de arquivo morto de um tema, usando o esquema abaixo, mas obviamente você só poderá processar uma fração dos temas existentes, já que um modelo pode conter basicamente qualquer coisa antiga .

O esquema é carregar o modelo em uma string ( $tpl_str) no archive_templatefiltro, substituir seu conteúdo, incluir a string (usando o truque eval( '?>' . $tpl_str );) e retornar um arquivo em branco para que o includeitem "wp-includes / template-loader.php" torna-se um não-op.

Abaixo está uma versão hackeada do código que uso em um plug-in, que tem como alvo modelos "clássicos" que usam get_template_parte se preocupa mais com o processamento de modelos únicos do que com o arquivo morto , mas deve ajudar você a começar. A configuração é que o plug-in possui um subdiretório chamado "modelos", que contém um arquivo em branco ("null.php") e modelos de conteúdo (por exemplo, "content-single-posttype1.php", "content-archive-postype1.php") bem como um modelo alternativo "single.php" para o caso único e utiliza uma versão personalizada da get_template_partaparência neste diretório.

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

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

Para completar, aqui está o "single.php", que usa o costume 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
fonte
1

Eu tenho pensado na mesma pergunta, e esta é a solução hipotética que eu vim com:

  • Dentro do plug-in, crie um código de acesso que produza seu loop de arquivamento da maneira que você deseja.
  • Ao criar o tipo de postagem personalizado, não ative a opção 'arquivar'.
  • Adicione uma folha de estilo que controla todos os estilos do conteúdo do seu loop.

Após a ativação do plug-in, crie uma página usando wp_insert_post com o nome no tipo de postagem e o conteúdo no código de acesso.

Você pode fornecer opções no código de acesso para considerações adicionais sobre o estilo ou adicionar classes ao contêiner de postagem para corresponder aos estilos específicos ou personalizados do tema. O usuário também pode adicionar conteúdo adicional antes / depois do loop, editando a página.

SkyShab
fonte
Apesar de não ser o OP, estava procurando uma solução para o mesmo problema. Eu segui sua solução hipotética e agora posso confirmar que também funciona na prática.
Lucio Crusca
Ei, ótimo! Ainda bem que isso foi útil para alguém. Eu tinha esquecido completamente disso.
SkyShab
0

Você pode usar o filtro single_template. Um exemplo básico retirado do 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
fonte
Acho que o gancho de filtro para um modelo de arquivo é archive_template, mas não acho que isso funcione para o que estou tentando fazer. Editei minha pergunta com mais informações.
Ben Miller - Lembre-se de Monica