Modelos de tipo de postagem personalizados da pasta Plugin?

57

Gostaria de oferecer meu tipo de postagem personalizado como um plug-in, para que as pessoas possam usá-lo sem tocar na pasta de temas. Porém, modelos personalizados de tipo de postagem - como single-movies.php - residem na pasta do tema. Existe uma maneira de fazer com que o WP procure um single-movies.php na pasta do plugin? Conectando uma função à hierarquia de arquivadores ? Ou get_template_directory (); ?

nathanbweb
fonte

Respostas:

90

Você pode usar o single_templategancho de filtro.

/* Filter the single_template with our custom function*/
add_filter('single_template', 'my_custom_template');

function my_custom_template($single) {

    global $post;

    /* Checks for single template by post type */
    if ( $post->post_type == 'POST TYPE NAME' ) {
        if ( file_exists( PLUGIN_PATH . '/Custom_File.php' ) ) {
            return PLUGIN_PATH . '/Custom_File.php';
        }
    }

    return $single;

}
Bainternet
fonte
É uma resposta incrível. Por favor, compartilhe onde posso obter todos os ganchos disponíveis do modelo, como single_template.
Gowri
6
@gowri O filtro é chamado pela get_query_template()função. Como um gancho variável, a primeira parte {$type}_templatemuda dependendo do parâmetro que é passado para essa função. Veja wp-includes / template.php para alguns dos mais comuns
de karité
Este tutorial aborda o gancho single_template com uma boa explicação. Depois de entender os ganchos, o comentário de @ shea sugere uma abordagem mais simples que a resposta de @ Bainternet, usando add_filter( 'single-movies_template', 'my_custom_template' );como no tutorial vinculado. (Esta questão está fechada para novas respostas, então eu não pode adicioná-lo por conta própria.)
Greg Perham
2
Você pode substituir PLUGIN_PATHpor plugin_dir_path( __FILE__ )e remover a primeira barra do seu nome de arquivo. O caminho completo seria algo parecido com isto:return plugin_dir_path( __FILE__ ) . 'Custom_File.php';
Frits
11
PLUGIN_PATH lançou um erro, aqui está um ótimo post que mostra como fazer isso e funcionou para mim imediatamente
Nathan
22

Resposta atualizada

Versão mais limpa e mais curta.

function load_movie_template( $template ) {
    global $post;

    if ( 'movie' === $post->post_type && locate_template( array( 'single-movie.php' ) ) !== $template ) {
        /*
         * This is a 'movie' post
         * AND a 'single movie template' is not found on
         * theme or child theme directories, so load it
         * from our plugin directory.
         */
        return plugin_dir_path( __FILE__ ) . 'single-movie.php';
    }

    return $template;
}

add_filter( 'single_template', 'load_movie_template' );

Resposta antiga

Foi adicionada uma verificação de um modelo específico de tipo de postagem personalizado na pasta do tema à resposta @Brainternet.

function load_cpt_template($template) {
    global $post;

    // Is this a "my-custom-post-type" post?
    if ($post->post_type == "my-custom-post-type"){

        //Your plugin path 
        $plugin_path = plugin_dir_path( __FILE__ );

        // The name of custom post type single template
        $template_name = 'single-my-custom-post-type.php';

        // A specific single template for my custom post type exists in theme folder? Or it also doesn't exist in my plugin?
        if($template === get_stylesheet_directory() . '/' . $template_name
            || !file_exists($plugin_path . $template_name)) {

            //Then return "single.php" or "single-my-custom-post-type.php" from theme directory.
            return $template;
        }

        // If not, return my plugin custom post type template.
        return $plugin_path . $template_name;
    }

    //This is not my custom post type, do nothing with $template
    return $template;
}
add_filter('single_template', 'load_cpt_template');

Agora você pode permitir que os usuários do plugin copiem o modelo do seu plugin para o tema deles para substituí-lo.

Neste exemplo, os modelos devem estar no diretório raiz do plug-in e do tema.

acampamentos
fonte
11
Usar em locate_templatevez de get_stylesheet_directorysoa como a opção mais limpa para mim (encontrada aqui: code.tutsplus.com/tutorials/… ).
Felix
11
A resposta atualizada não funcionou, a resposta aceita (ou sua resposta antiga) funciona.
31418 Edward Edward
2
Você está certo, Edward, que foi uma atualização horrenda. Eu o atualizei novamente com a sugestão de Felix. Também desta vez eu testei o código antes de postar ele :)
campsjos
4

Gostaria de salientar que, quando você estiver usando o método de filtro para isso, é extremamente importante priorizar o filtro da seguinte forma:

add_filter('single_template', 'my_custom_template', 99);

Se você não fizer isso, algumas vezes o WP tentará verificar novamente após esse filtro. Estava puxando meu cabelo por causa disso por 2 horas.

RBizzle
fonte
0

Existe uma maneira muito melhor de fazer isso que eu estou usando para meus plugins.

Como o @campsjos menciona aqui , em vez da verificação da existência do arquivo, você pode verificar locate_templatese o arquivo de modelo de substituição de tema será verificado. O que é bastante óbvio.

function my_plugin_templates() {
    if (is_singular('movie')) {
        if (file_exists($this->template_dir . 'single-movie.php')) {
            return $this->template_dir . 'single-movie.php';
        }
    }
}

Use o template_includegancho de filtro para carregar o código acima.

add_filter('template_include' , 'my_plugin_templates');
pixelngrain
fonte
0

Graças a esta página, consegui resolver a mesma pergunta para mim.

Para referência, é isso que eu acabei com:

function pluginName_myposttype_single_template($single_template) {
  $myposttype_template = PLUGIN_DIR . 'templates/single-myposttype.php';
  return get_post_type() === 'myposttype' && file_exists($myposttype_template) ? $myposttype_template : $single_template;
}
add_filter('single_template', 'pluginName_myposttype_single_template');

o gancho do filtro {$ type} _template não funcionou para mim

function pluginName_myposttype_single_template($single_template) {
  $myposttype_template = PLUGIN_DIR . 'templates/single-myposttype.php';

  if ( file_exists($myposttype_template) ) {
    $single_template = $myposttype_template;
  }
  return $single_template;
}
add_filter('single-myposttype_template', 'pluginName_myposttype_single_template');
Thomas Fellinger
fonte
-2

Acima está uma ótima resposta, mas verificar o $ single var permite que o modelo substitua um modelo, se um for fornecido pelo tema / tema filho.

/* Filter the single_template with our custom function*/
add_filter('single_template', 'your_cpt_custom_template');

function your_cpt_custom_template( $single ) {
    global $wp_query, $post;
    /* Checks for single template by post type */
    if ( !$single && $post->post_type == 'cpt' ) {
        if( file_exists( plugin_dir_path( __FILE__ ) . 'single-cpt.php' ) )
            return plugin_dir_path( __FILE__ ) . 'single-cpt.php';
    }
    return $single;
}
DigitalDesignDj
fonte
11
Isso não verifica se o single-cpt.php está presente em um filho ou no tema. Ele verifica apenas o single.php, que sempre estará presente em qualquer tema.
Newpxsn 28/10/2015
É isso mesmo, quando escrevi isso, eu estava usando um tema realmente simples, tem que haver uma maneira melhor!
DigitalDesignDj