¿Cómo puedo agregar una opción a la lista de plantillas de página desde un complemento?

10

He estado buscando durante las últimas dos horas una forma de crear una plantilla de página personalizada desde un complemento, pero aún no he tenido suerte.

Lo que estoy tratando específicamente de hacer es agregar una opción a la lista de plantillas de página disponibles al editar una página, y no usar otro método comoif( is_page( 'page-slug' ) ) { /* etc */ }

¿Hay una variable global que pueda modificar para hacer esto?

Editar:

Actualmente estoy usando este código, basado en el enlace que @ m0r7if3r me dio en un comentario, el problema es que ejecutará esta función cuando vea la página, pero no cuando edite la página (para completar la lista desplegable con las plantillas de página) :

class JW_SiteGrader {

    private static $instance;

    private function __construct() {


        add_action( 'template_redirect', array( &$this, 'sitegrader_template_redirect' ), 20 );

    }

    public static function getInstance() {

        // Return the class data in a Singleton fashion
        if (self::$instance == null)
            self::$instance = new JW_SiteGrader();
        return self::$instance;

    }

    public function sitegrader_template_redirect() {

        add_filter( 'page_template', array( &$this, 'sitegrader_page_template' ), 10, 1 );

    }

    public function locate_plugin_template( $template_names, $load = false, $require_once = true ) {

        if ( !is_array( $template_names ) )
            return '';

        $located = '';

        $this_plugin_dir = WP_PLUGIN_DIR . '/' . str_replace( basename( __FILE__ ), '', plugin_basename( __FILE__ ) );

        foreach ( $template_names as $template_name ) {

            if ( !$template_name )
                continue;

            if ( file_exists( STYLESHEETPATH . '/' . $template_name ) ) {

                $located = STYLESHEETPATH . '/' . $template_name;
                break;

            } else if ( file_exists( TEMPLATEPATH . '/' . $template_name ) ) {

                $located = TEMPLATEPATH . '/' . $template_name;
                break;

            } else if ( file_exists( $this_plugin_dir .  $template_name ) ) {

                $located =  $this_plugin_dir . $template_name;
                break;

            }

        }

        if ( $load && '' != $located )
            load_template( $located, $require_once );

        return $located;
    }

    public function sitegrader_page_template( $template ) {

        $object = get_queried_object();

        if ( 'page' == $object->post_type ) {

            // New 
            $templates[] = "page-sitegrader.php";
            // Like in core
            $templates[] = "page-{$object->post_type}.php";
            $templates[] = "page.php";

            return locate_template( $templates );  

        }

        // return apply_filters('page_template', $template);
        return $template;
    }

}

Edición 2:

Parece que esta funcionalidad se lanzará en una actualización futura, leí bastantes tickets de seguimiento sobre esto y ha habido algunas discusiones pero no hubo una respuesta real (esperando 3.4). Enumerará aquí las URL de tickets de seguimiento aquí en un momento.

Edición 3:

El código anterior funciona, PERO, el único problema que tengo en este momento es que no se agrega ninguna plantilla a la lista desplegable al editar / agregar una nueva página. Estoy intentando algunas cosas y actualizaré mi pregunta pronto.

Jared
fuente
2
¿Has probado algo como esto ?
mor7ifer
@ m0r7if3r (Si lo intentas, deja un mensaje sobre cómo funcionó - ¡Gracias!)
kaiser
@kaiser Probé el código que me recomendó, el único enlace que falta es obtener el cuadro meta para agregar la plantilla a la lista desplegable (¡hasta donde yo sé!).
Jared
@ Jared Mira esta respuesta por mí a una Q similar y los tickets de tráco relacionados en la parte inferior de la a. Agregue su código) Si no se muestra en todas las páginas, está utilizando los ganchos incorrectos para ejecutar la instancia. ¿Qué ganchos estás usando?
kaiser
@kaiser Estoy usando el page_templategancho, el código anterior en mi edición es lo que se está utilizando actualmente. ¿Necesito usar el template_redirectgancho y luego agregar el page_templatefiltro allí?
Jared

Respuestas:

4

Filtros? ¿Nadie?

No hay ningún filtro para ayudar: page_template_dropdown($template);se usa para construir el menú desplegable y no se puede filtrar.

¿Furtivamente en la matriz de plantillas?

Para compilar los contenidos desplegables, se usa el meta cuadro principal get_page_templates(). Desde adentro, la función tiene el siguiente aspecto:

$themes = get_themes();
$theme = get_current_theme();
$templates = $themes[$theme]['Template Files'];

Pero al mirar, parece que get_themes();no hay posibilidad de interceptar la lista de plantillas. Además, tenemos el problema, que no hay posibilidad de obtener una plantilla desde fuera del directorio de temas ...

... Fingiendo un tema!

La teoría y sus inconvenientes ...

Puede usar register_theme_directory()para agregar un directorio de temas adicional donde puede colocar plantillas. Entonces, lo más fácil sería registrar su complemento como carpeta de temas también:

// Register during init hook:
register_theme_directory( plugin_dir_path( __FILE__ ).'templates' );

Nota: Aquí es donde no estoy seguro de si funcionará .

Durante la activación del complemento: entonces debe colocar un style.css.phparchivo dentro de su templatescarpeta. Esto le permitiría agregar variables a su archivo. Esta variable sería el tema principal. Y el tema principal simplemente debería ser el tema actualmente activo. Luego actualice su tema activo a su complemento.

Desventaja n. ° 2: Acerca de la interfaz de usuario »Apariencia« ... Tal vez agregue una nota de que este "Tema" no debe usarse como un Tema real. Os dejo el resto de "Evita activar este tema" cosas hasta tu imaginación. De todos modos: debería funcionar.

Desventaja n. ° 2: este truco evitará con éxito los temas secundarios. Se le permite tener un tema principal. Nada mas.

emperador
fuente
Entonces, supongo que no hay una forma real de usar plantillas de página personalizadas de ningún tema inactivo, ¿correcto? Podría registrar un directorio de temas, pero las plantillas, sin embargo, no están disponibles para su uso a menos que ese tema esté activo.
Jared
1
Realmente no. Simplemente no se supone que sea y, por lo tanto, una falta de núcleo. ¿Has probado el enlace a ipstenu arriba? Ya intenté seguir esa ruta, pero terminé en un camino muerto, con otra solución. La mejor opción sería seguir los boletos, presionarlos y vincularlos donde sea que esté. : /
kaiser
2

Como sugerencia para una posible solución alternativa, ¿ha considerado usar el sistema de archivos de WordPress para escribir un archivo de plantilla de página desde su complemento a su directorio de tema activo actual? Dependiendo de cuánto control desee sobre este proceso, puede hacer que su complemento escriba el archivo en la activación y lo elimine en la desinstalación. Alternativamente, podría crear archivos de plantilla de página dinámicamente desde la interfaz de usuario de su complemento utilizando un formulario para pasar ciertos valores, como el nombre de la plantilla de página que aparecerá en el cuadro desplegable de la pantalla de edición posterior. En teoría, también podría eliminar la plantilla de página de la interfaz de usuario de su complemento con solo hacer clic en un botón y, de manera similar, agregar varias plantillas para diferentes propósitos. Hay una buena publicación sobre el uso del sistema de archivos en el blog de Otto. No tengo el enlace conmigo ahora, pero puedes buscarlo.

Espero que publiquen lo que pretendías hacer a través de un gancho en la próxima versión principal.

Adán
fuente
1
Tenía un método exactamente como este funcionando antes, pero tuve muchos problemas cuando lo probé, porque cuando un usuario cambiaba de tema, no eliminaba el archivo de plantilla y si copiaba su tema activo y lo colocaba en un sitio diferente , correrían el riesgo de cargar un archivo de plantilla personalizado que no funcionaría. Sé que hay varias soluciones para eso, pero realmente quiero que esto sea automático . +1 para la sugerencia sin embargo.
Jared
1
Hola Jared, también estaba preocupado por el mismo problema. La única solución que podría pensar para extender aún más este método alternativo sería hacer que el complemento, una vez activado, obtenga el nombre del tema actual y, si un usuario desactiva / cambia temas, puede eliminar el archivo de plantilla de ese tema y reescribirlo al recién activado tema. Eche un vistazo a este enlace donde creó sus propios ganchos de activación / desactivación para verificar temas. Con un pequeño código adicional, siento que esto es factible.
Adam
Absolutamente, creo que eso puede funcionar. Lo intentaré y publicaré los resultados en mi pregunta. Gracias por el enlace, ¡ayuda!
Jared
1

Eché un vistazo a la fuente y, sorprendentemente, ¡no parece haber una forma de hacerlo! Mi truco sugerido sería agregar un segundo cuadro de meta con una anulación de tema / desplegable de segundo tema. Luego enganche este filtro:

# wp-includes/theme.php line 751 in 3.3.1:
return apply_filters( "{$type}_template", locate_template( $templates ) );

para devolver su archivo de tema si se ha anulado. Por supuesto, solo querrás agregar_filtro si es la publicación que deseas.

Si desea ser elegante, puede desechar la caja original y volver a crearla (a través de filtros, por supuesto, sin modificar el código central).

También sugeriría agregar un ticket de trac solicitando esa funcionalidad (si no hay uno ya disponible).

Matthew Boynes
fuente
1
Estoy de acuerdo con sugerir esto para trac.
helgatheviking
Ya parece estar en el trac: core.trac.wordpress.org/ticket/15803
Jared
1
Acabo de investigar esto para otra Q sobre plantillas de tipo de publicación única . Puedes encontrar los tickets de Trac al final de la respuesta. Vamos esperanza de 3.4.
kaiser
1

He logrado esto en el pasado eliminando el metabox de la plantilla de página predeterminada y luego agregando su propio metabox. Hice que el nuevo metabox usara las plantillas get_page_templates incorporadas y luego agregué las otras que necesitaba programáticamente. Al guardarlo, puede actualizar la plantilla de la página al igual que WordPress.

gruvii
fuente
¿Te importaría mostrar el código completo? Actualmente es solo un concepto aproximado. Gracias.
kaiser
1

Echa un vistazo al gancho theme_page_templates, utilizado por la get_page_templatesfunción, filtro agregado desde 3.9 actualizado en 4.4:

apply_filters( 'theme_page_templates', $page_templates, $this, $post );
William Gu
fuente
explicado más completamente aquí: wordpress.stackexchange.com/a/255820/75495
cjbj
-2

Un resultado de búsqueda con DuckDuckGo agregando una plantilla de página de WordPress me dio la respuesta en una página de wpmu.org titulada Tutorial de plantilla de página personalizada de WordPress .

Esencialmente, dentro del directorio de temas, wp-content / themes / your-theme , copie una plantilla de página existente a un nuevo nombre de archivo php de su elección. Edite el nuevo archivo, teniendo cuidado de cambiar el valor mágico de la propiedad "Nombre de plantilla:" en el comentario en la parte superior del archivo.

Eso era todo lo que habia al respecto. Es posible que esta sea una característica que fecha la pregunta. Estoy usando WP 3.5 con el tema twenty_eleven.

También es posible que haya formas más limpias de extender un tema. Ediciones como esta podrían sobrescribirse por actualizaciones de temas. Mea culpa.

Douglas Lovell
fuente
Necesito una solución para agregar la plantilla a la lista desplegable desde un complemento, no un tema. :(
Jared