web-dev-qa-db-fra.com

Ajout d'éléments au menu déroulant de modèle de page sur l'écran d'édition de page

Je développe un thème WP avec l'approche MVC. Il n'y a que index.php, functions.php et styles.css dans le répertoire parent. Par conséquent, je ne souhaite pas y placer de modèles de page, mais plutôt les fournir par programmation à partir de classes View tandis que les fonctionnalités à partir de l'écran d'édition restent inchangées.

Les utilisateurs doivent avoir l'option de sélection des modèles de page sur l'écran d'édition. Comment ajouter des éléments au menu déroulant du modèle?

J'ai essayé de me connecter à theme_page_templates filter.

Exemple de code:

add_filter( 'theme_page_templates', function($templates){

    $templates['my-page-template.php'] = "My Page Template";

    return $templates;

});

Cela ne fonctionne pas à cause de l'utilisation de array_intersect_assoc() sur le tableau filtré, ce qui supprime l'élément de modèle de page ajouté. Je ne comprends pas pourquoi cette fonction est utilisée. Il semble que vous ne pouvez supprimer que le modèle de page de la liste, mais vous ne pouvez pas en ajouter un nouveau à l'aide du filtre donné.

Y a-t-il un autre moyen?

4
Sisir

Je pensais vous proposer une autre approche. C'est aussi un peu hackish, mais il est d'usage général et vous permet d'enregistrer simplement le nom de fichier et l'étiquette que vous souhaitez utiliser, comme suit:

if ( class_exists( 'WPSE_196995_Page_Templates' ) ) {   
    WPSE_196995_Page_Templates::register_page_template(
        'My Page Template',
        'my-page-template.php'
    );
}

Vous pouvez ajouter le code ci-dessus au fichier functions.php de votre thème.

Pour que ce qui précède fonctionne réellement, j'ai mis en place une classe autonome pouvant être utilisée comme plug-in ou simplement copiée dans functions.php:

<?php   
/**
 * Plugin Name: WPSE 196995 Page Templates
 *
 * Class WPSE_196995_Page_Templates
 *
 * Allows registering page templates via code.
 */
class WPSE_196995_Page_Templates {

    static $registered_templates = array();

    static function on_load() {

        /**
         * Add registered page templates to 'page_template' cache.
         * @note This hook is called just before page templates are loaded
         */
        add_action( 'default_page_template_title', array( __CLASS__, '_default_page_template_title' ) );
    }

    /**
     * Register page templates
     *
     * @param string $label
     * @param string $filename
     */
    static function register_page_template( $label, $filename ) {

        self::$registered_templates[ $filename ] = $label;

    }

    /**
     * Add registered page templates to 'page_template' cache.
     *
     * @param string $title
     *
     * @return string mixed
     */
    static function _default_page_template_title( $title ) {

        /**
         * @var WP_Theme $theme
         */
        $theme = wp_get_theme();

        /**
         * Access the cache the hard way since WP_Theme makes almost everything private
         */
        $cache_hash = md5( $theme->get_stylesheet_directory() );

        /**
         * Get the page templates as the 'page_templates' cache will already be primed
         */
        $page_templates = wp_cache_get( $key = "page_templates-{$cache_hash}", $group = 'themes' );

        /**
         * Add in registered page templates
         */
        $page_templates += self::$registered_templates;

        /**
         * Now update the cache, which is what the get_page_templates() uses.
         */
        wp_cache_set( $key, $page_templates, $group, 1800 );

        /**
         * We are using this hook as if it were an action.
         * So do not modify $title, just return it.
         */
        return $title;

    }

}
WPSE_196995_Page_Templates::on_load();

La classe fournit la méthode register_page_template(), bien sûr, mais pour ajouter votre modèle de page, elle met à jour la valeur de 'page_templates' définie dans le cache d'objets.

C'est un peu compliqué parce que WordPress a créé la plupart des méthodes et propriétés de la classe WP_Theme de la classe private, mais heureusement, ils ont utilisé le cache d'objets WordPress, accessible au public, pour stocker les valeurs. Et en mettant à jour le cache d'objets dans le crochet 'default_page_template_title', appelé juste avant que le menu déroulant des modèles de page ne soit généré et envoyé au navigateur, nous pouvons faire en sorte que WordPress affiche votre ou vos modèles de page, comme vous le souhaitez.

5
MikeSchinkel

J'ai eu un truc moche: - /. Je vais mettre à jour la réponse si je vais avec jQuery plus tard. La solution nécessite toujours d'avoir des fichiers de modèle mais le code pour le fichier de modèle se charge à partir du index.php

  1. J'ai créé un nouveau répertoire template/ et y ai placé tous les modèles de page.
  2. Tous les modèles de page sont vides. Nous en avons besoin seulement pour qu'ils apparaissent dans le menu déroulant.
  3. Utilisez le filtre template_include pour rediriger vers index.php

Code

Exemple de modèle de page vierge

<?php
/*
Template Name: No Sidebar
 *
 * */

Filtre

add_filter( 'template_include', function ($template ) {

    if ( !is_page_template()  )
        return $template;

    return locate_template( array( 'index.php' ), true );

}, 99);

J'ai créé un ticket Trac pour permettre l'ajout de modèles via un filtre.

1
Sisir