Añadir página de plantilla personalizada programáticamente

29 mar 2011, 14:14:31
Vistas: 24.6K
Votos: 7

Estoy intentando añadir una página de plantilla desde un plugin, y mi archivo de plantilla está en la carpeta del plugin. ¿Es esto posible? Aquí está mi código:

global $user_ID;
    $new_post = array(
        'post_title' => 'Test Template Page',
        'post_content' => 'Some text', 
        'post_status' => 'publish',
        'post_date' => date('Y-m-d H:i:s'),
        'post_author' => $user_ID,
        'post_type' => 'page',
        'post_category' => array(0)
    );
    $post_id = wp_insert_post($new_post);
    if (!$post_id) {
        wp_die('Error creating template page');
    } else {
        update_post_meta($post_id, '_wp_page_template', 'tp-file.php');
    }

tp-file.php es mi página de plantilla personalizada. Cuando coloco ese archivo en la carpeta my-theme, funciona bien, pero quiero hacer esto con el archivo desde la carpeta del plugin para no tener que obligar a los usuarios a copiar ese archivo desde la carpeta del plugin a la carpeta del tema. ¿Es esto posible? ¿Alguna idea?

4
Comentarios

http://www.unfocus.com/2010/08/10/including-page-templates-from-a-wordpress-plugin/ Parece tratar este tema. No estoy muy familiarizado con ello, así que no puedo decir si funciona o no.

Rev. Voodoo Rev. Voodoo
29 mar 2011 14:45:02

Gracias @Rev.Voodoo, le echaré un vistazo.

user1147 user1147
29 mar 2011 15:11:20

@Rev.Voodoo no, eso no ayudó

user1147 user1147
30 mar 2011 00:54:26

¿Cuál es el contenido de tp-file.php?

User User
1 ene 2012 11:27:46
Todas las respuestas a la pregunta 3
15
13

El artículo enlazado va por buen camino, pero lo haré más simple para ti.. ;)

add_filter( 'page_template', 'catch_plugin_template' );

function catch_plugin_template( $template ) {
    if( 'tp-file.php' == basename( $template ) )
        $template = WP_PLUGIN_DIR . '/yourpluginname/tp-file.php';
    return $template;
}

El filtro básicamente verifica si tu plantilla de página especial está configurada para la página actual, si es así, actualiza la ruta para apuntar a la plantilla de tu plugin.

Solo asegúrate de que la ruta sea correcta, de lo contrario verás errores de inclusión... :)

Seguimiento #1

Ok, el primer problema es que WordPress valida cualquier plantilla configurada como plantilla de página, es decir, verifica si el archivo está en la carpeta del tema y es un archivo de plantilla válido, si no, lo omite e incluye una plantilla más genérica, como page.php...

Sin embargo, esto no cambia el hecho de que el campo meta aún contiene el valor de tu plantilla personalizada, y también is_page_template( 'tp-file.php' ) devolverá correctamente true si se usa en lugar de mi declaración condicional anterior, por ejemplo..

// Filtro de plantilla de página
add_filter('page_template', 'catch_plugin_template');

// Callback del filtro de plantilla de página
function catch_plugin_template($template) {
    // Si tp-file.php es la plantilla configurada
    if( is_page_template('tp-file.php') )
        // Actualizar ruta (debe ser una ruta, usa WP_PLUGIN_DIR y no WP_PLUGIN_URL) 
        $template = WP_PLUGIN_DIR . '/tp-test/tp-file.php';
    // Devolver
    return $template;
}

NOTA: He cambiado el código para usar WP_PLUGIN_DIR ya que la constante WP_PLUGIN_URL no es adecuada para rutas... (los includes deben usar una ruta, no una URL).

Un problema, y esto realmente no es algo que puedas solucionar, es que al ver la página desde el área de administración, al editar la página, la plantilla no aparecerá como la plantilla activa, y guardar cambios podría, por supuesto, cambiar la plantilla activa. No hay mucho que podamos hacer allí, el menú desplegable de plantillas de página se genera a partir de una función que escanea los archivos del tema, no hay hooks disponibles que permitan extender la lista con plantillas de plugins.

Personalmente, lo que sugeriría, como solución alternativa, sería guardar un campo meta adicional con cada página creada usando tu plugin especial, luego agregar un hook a save_post o wp_insert_post_data y verificar si este campo meta existe, si existe, también verificar que la plantilla de página esté configurada como tp-file.php, y si no, actualizarla a tp-file.php. El campo meta adicional sería simplemente una bandera, por así decirlo, para indicar qué páginas necesitan tener adjunta la plantilla de tu plugin.

Aquí tienes tu plugin funcionando en su forma más básica (sí, lo probé)... :)

<?php
/*
  Plugin Name: TP Test Plugin
  Plugin URI: 
  Description: TP Test Plugin
  Version: 1.0.0
  Author: 
  Author URI: 
*/

global $wp_version;

if( version_compare( $wp_version, "2.9", "<" ) )
    exit( 'Este plugin requiere WordPress 2.9 o más reciente. <a href="http://codex.wordpress.org/Upgrading_WordPress">¡Por favor actualiza!</a>' );

// Agregar callback al menú de administración
add_action('admin_menu', 'create_tp_menu');

// Callback para agregar elementos al menú
function create_tp_menu() {
    add_management_page('TP Test', 'TP Test', 'manage_options', 'tp-teste', 'wp_tp_test_fnc' );
}

function wp_tp_test_fnc() {

    //include('tp-form-file.php');

    if( !empty( $_POST['tp_name'] ) ) {
        $tp_name = $_POST['tp_name'];

        global $user_ID;
        $new_post = array(
            'post_title' => $tp_name,
            'post_content' => 'Algún texto',
            'post_status' => 'publish',
            'post_date' => date('Y-m-d H:i:s'),
            'post_author' => $user_ID,
            'post_type' => 'page',
        );
        $post_id = wp_insert_post($new_post);

        if( !$post_id )
            wp_die('Error al crear la página de plantilla');
        else
            update_post_meta( $post_id, '_wp_page_template', 'tp-file.php' );
        /*
        $pt = get_page_templates();

        $pt['TP file test'] = WP_PLUGIN_URL . '/tp-test/tp-file.php';

        echo "<pre>";
        print_r($pt);
        echo "</pre>";
        */
    }   
    ?>
    <fieldset style="margin: 50px 100px;background-color: #cccccc;padding: 30px;border: 1px solid #ccc">
         <legend style="background-color: #ccccff;padding: 20px;font-weight: bold;font-size: 18px">Crear Página de Plantilla</legend>
         <form name="frm_main" action="" method="POSt">
              <input class="text" type="text" name="tp_name" size="50" />
              <br />
              <input class="button" type="submit" value="Crear Página de Plantilla" name="btn_submit" />
         </form>
    </fieldset>
    <?php

}


// Filtro de plantilla de página
add_filter('page_template', 'catch_plugin_template');

// Callback del filtro de plantilla de página
function catch_plugin_template($template) {
    // Si tp-file.php es la plantilla configurada
    if( is_page_template('tp-file.php') )
        // Actualizar ruta (debe ser una ruta, usa WP_PLUGIN_DIR y no WP_PLUGIN_URL) 
        $template = WP_PLUGIN_DIR . '/tp-test/tp-file.php';
    // Devolver
    return $template;
}

Espero que eso ayude a aclarar las cosas.. :)

30 mar 2011 02:21:03
Comentarios

Gracias @t31os Lo intenté y no funcionó, luego encontré esto http://adambrown.info/p/wp_hooks/hook/page_template que está obsoleto, ¿alguna otra idea?

user1147 user1147
30 mar 2011 02:31:51

También probé algo como esto, pero no funcionó: $pt = get_page_templates(); $pt['TP testing'] = WP_PLUGIN_URL . '/tp-test/tp-file.php';

user1147 user1147
30 mar 2011 02:38:15

Funciona perfectamente para mí... necesitaré más detalles que simplemente "no funcionó"...

t31os t31os
30 mar 2011 02:46:51

Parece que los archivos de plantilla no están habilitados en la subcarpeta, encontré eso en theme.php en la función get_page_templates, ¿alguna otra idea?

user1147 user1147
30 mar 2011 02:48:09

No es relevante, el código que proporcioné funcionará perfectamente siempre que la ruta esté configurada correctamente y la página solicitada tenga _wp_page_template establecido en tp-file.php... Acabo de volver a probarlo para estar seguro, y nuevamente confirmé que funciona (necesitaré ver más de tu código si quieres que te ayude a descubrir por qué no funciona en tu configuración).

t31os t31os
30 mar 2011 02:53:31

Gracias por tu tiempo, mi código no cambió, lo único es que agregué tu código a mi archivo principal del plugin, échale un vistazo aquí: http://pastebin.com/sNR9s0sP

user1147 user1147
30 mar 2011 03:05:20

También verifiqué dos veces mi tabla wp_postmeta, parece estar bien

user1147 user1147
30 mar 2011 03:07:58

Ok, pero ¿qué sucede cuando cargas una página que tiene _wp_page_template configurado como tp-file.php? ¿Ves un error de inclusión, ves una página en blanco, ves algo más? Ayúdame a ayudarte... ;)

t31os t31os
30 mar 2011 03:08:39

Veo "Algún texto" como si fuera una página normal, y si voy al backend veo que la plantilla de página está configurada como predeterminada, y no está en la lista mi archivo de plantilla

user1147 user1147
30 mar 2011 03:10:34

Me voy a la cama en unos minutos, pero aclararé el problema mañana para ti. Mientras el campo meta _wp_page_template permanezca configurado correctamente debería funcionar, independientemente de que no se muestre en el lado del administrador (lo cual es de esperar - lo explicaré en la actualización de la respuesta mañana).

t31os t31os
30 mar 2011 03:17:41

ok, gracias @t31os por la ayuda

user1147 user1147
30 mar 2011 03:19:33

De nada... y acabo de actualizar mi respuesta.. ;)

t31os t31os
30 mar 2011 12:56:21

Oye, esto es extraño, el código no funciona cuando el formulario está en un archivo separado, pero si está junto, entonces sí funciona.

user1147 user1147
30 mar 2011 13:49:03

Intenta establecer una acción en tu formulario, por ejemplo: action="<?php admin_url( '/?page=tp-teste' ) ?>", para asegurarte de que se envía correctamente a la página de tu plugin.

t31os t31os
30 mar 2011 13:54:56

aaaaaaa, dios mío, ese era el problema. Gracias @t31os por tu tiempo.

user1147 user1147
30 mar 2011 14:09:51
Mostrar los 10 comentarios restantes
2

El filtro page_template está obsoleto ahora. (http://adambrown.info/p/wp_hooks/hook/page_template)

Intenta usar single_template (o archive_template para plantillas de archivo) en su lugar.

Basado en la respuesta de @t31os:

// Filtro de plantilla de página
add_filter('single_template', 'catch_plugin_template');

// Callback del filtro de plantilla de página
function catch_plugin_template($template) {
    // Si tp-file.php es la plantilla establecida
    if( is_page_template('tp-file.php') )
        // Actualizar la ruta (debe ser una ruta, usa WP_PLUGIN_DIR y no WP_PLUGIN_URL) 
        $template = WP_PLUGIN_DIR . '/tp-test/tp-file.php';
    // Devolver
    return $template;
}
23 jun 2016 17:20:10
Comentarios

Si el filtro single_template no funciona, puedes usar este filtro: add_filter('template_include', 'catch_plugin_template');

Tomado de aquí: https://www.pradipdebnath.com/2019/08/17/how-to-add-page-template-from-plugin-in-wordpress/

ewroman ewroman
18 abr 2020 07:59:47

No estoy seguro si está obsoleto, solo cambió desde la versión 4.7. https://developer.wordpress.org/reference/hooks/type_template/. El argumento está vacío si el/los temas no proporcionan la plantilla, no si la página la ha seleccionado (almacenada) en la base de datos desde el menú desplegable de selección.

Jonas Lundman Jonas Lundman
4 dic 2021 10:49:31
0

Un problema, y esto realmente no es algo que puedas solucionar, es que cuando visualizas la página desde el área de administración, al editar la página, la plantilla no aparecerá listada como la plantilla activa, y guardar los cambios podría por supuesto cambiar la plantilla activa. No hay mucho que podamos hacer ahí, el desplegable de plantillas de página se genera a partir de una función que escanea los archivos del tema, no hay hooks disponibles que pueda ver que nos permitan extender la lista con plantillas de plugins.

En realidad encontré un hook en otro hilo que hace exactamente eso:

WordPress: ¿Se pueden crear plantillas de página programáticamente?

Pego el código aquí por conveniencia:

CONST CUSTOM_PAGE_TEMPLATES = array(
  array('slug' => 'home', 'label' => 'Inicio'),
  array('slug' => 'content-page', 'label' => 'Página de contenido'),
  array('slug' => 'ordering', 'label' => 'Pedidos'),
  array('slug' => 'reviews', 'label' => 'Reseñas')
); 

/**
 * Añade plantillas de página sin archivo al desplegable de plantillas 
 */
add_filter('theme_page_templates', function($page_templates, $wp_theme, $post) {
  foreach(CUSTOM_PAGE_TEMPLATES as $template) {
    // Añade si no existe ya
    if (!isset($page_templates[$template['slug']])) {
      $page_templates[$template['slug']] = $template['label'];
    }
  }
  return $page_templates;
}, PHP_INT_MAX, 3);

Espero que esto le ayude a alguien.

20 abr 2021 10:06:53