web-dev-qa-db-fra.com

Comment puis-je ajouter une option à la liste des modèles de page à partir d'un plugin?

Au cours des dernières heures, je cherchais un moyen de créer un modèle de page personnalisé à partir d'un plugin, mais je n'ai pas encore eu de chance.

Ce que j’essaie précisément de faire, c’est d’ajouter une option à la liste des modèles de page disponibles lors de la modification d’une page, et pas d’utiliser une autre méthode telle que if( is_page( 'page-slug' ) ) { /* etc */ }.

Y at-il une variable globale que je peux modifier pour faire cela?

Modifier:

J'utilise ce code actuellement, basé sur le lien que @ m0r7if3r m'a donné dans un commentaire, le problème est que cette fonction sera exécutée lors de l'affichage de la page, mais pas lors de la modification de la page (pour remplir la liste déroulante avec les modèles de page) :

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

}

Edit 2:

Il semble que cette fonctionnalité sera disponible dans une future mise à jour, j'ai lu pas mal de tickets de trac à ce sujet et il y a eu quelques discussions mais aucune réponse réelle (en espérant une version 3.4). La liste des URL des tickets de trac sera-t-elle ici dans un instant?.

Edit 3:

Le code ci-dessus fonctionne, MAIS, le seul problème que je rencontre à ce stade est qu'aucun modèle n'est ajouté à la liste déroulante lors de la modification/l'ajout d'une nouvelle page. J'essaie quelques choses et mettrai à jour ma question bientôt.

10
Jared

Des filtres? N'importe qui?

Il y a non filtre pour vous aider: page_template_dropdown($template); est utilisé pour créer le menu déroulant et il n'est pas filtrable.

Se faufiler dans le tableau de modèles?

Pour créer le contenu des listes déroulantes, la méta-boîte principale utilise get_page_templates(). De l'intérieur, la fonction ressemble à ceci:

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

Mais quand on cherche dans get_themes();, alors il semble qu'il n'y ait aucune possibilité d'intercepter la liste des modèles. De plus, le problème est qu’il n’ya aucune chance d’obtenir un modèle en dehors du répertoire des thèmes…

... simulant un thème!

La théorie et ses inconvénients…

Vous pouvez utiliser register_theme_directory() pour ajouter un répertoire de thème supplémentaire dans lequel vous pouvez placer des modèles. Donc, le plus simple serait d’enregistrer également votre plugin en tant que dossier de thèmes:

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

_ {Remarque: c'est là que je ne suis pas sûr que cela fonctionnera).

Au cours de l'activation du plugin: Ensuite, placez un fichier style.css.php dans votre dossier templates. Cela vous permettrait d'ajouter des variables à votre fichier. Cette variable serait alors le thème parent. Et le thème parent devrait simplement être le thème actuellement actif. Puis mettez à jour votre thème actif sur votre plugin.

Inconvénient n ° 2: à propos de la "Apparence" UI… Peut-être ajouter une note indiquant que ce "thème" n'est pas destiné à être utilisé comme thème réel. Je laisse le reste de "Evitez d'activer ce thème" à la hauteur de votre imagination. Quoi qu'il en soit: ça devrait marcher.

Inconvénient n ° 2: Ce astuce évitera avec succès les thèmes enfants. Vous êtes autorisé à avoir un thème pour un seul parent. Rien de plus.

4
kaiser

En guise de suggestion de solution de contournement, avez-vous envisagé d'utiliser le système de fichiers WordPress pour écrire un fichier de modèle de page à partir de votre plug-in dans votre répertoire de thème actif actuel? En fonction du contrôle que vous souhaitez sur ce processus, vous pouvez demander à votre plug-in d'écrire le fichier lors de l'activation et de le supprimer lors de la désinstallation. Vous pouvez également créer des modèles de page de manière dynamique à partir de votre interface utilisateur de plug-in en utilisant un formulaire pour transmettre certaines valeurs, telles que le nom du modèle de page qui doit apparaître dans la liste déroulante de l'écran de modification. En théorie, vous pouvez également supprimer le modèle de page de votre interface utilisateur de plug-in en cliquant sur un bouton et ajouter de la même manière plusieurs modèles à des fins différentes. Il y a un bon article sur l'utilisation du système de fichiers sur le blog d'Otto. Je n'ai pas le lien avec moi maintenant mais vous pouvez le rechercher.

J'espère qu'ils publieront ce que vous avez l'intention de faire en guise de crochet dans la prochaine version principale.

2
userabuser

J'ai déjà réalisé cela par le passé en supprimant la métabox de modèle de page par défaut, puis en ajoutant votre propre métabox. La nouvelle métabox a utilisé la méthode get_page_templates intégrée, puis les autres dont j'avais besoin par programmation. Lors d'une sauvegarde, vous pouvez mettre à jour le modèle de page, comme le fait Wordpress.

1
gruvii

Découvrez le hook theme_page_templates, utilisé par la fonction get_page_templates, filtre ajouté depuis la version 3.9 mise à jour en 4.4:

apply_filters( 'theme_page_templates', $page_templates, $this, $post );
1
William Gu

J'ai parcouru la source, et il est choquant de constater que cela ne semble pas être un moyen de le faire! Mon hack suggéré serait d'ajouter une deuxième boîte méta avec un menu déroulant de remplacement de thème/deuxième thème. Puis accrochez-vous à ce filtre:

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

pour retourner votre fichier de thème s'il a été remplacé. Bien sûr, vous ne voudriez add_filter que si c'est le post que vous voulez.

Si vous voulez être chic, vous pouvez supprimer la boîte d'origine et la recréer (via des filtres bien sûr, sans modifier le code principal).

Je suggèrerais également d'ajouter un ticket trac demandant cette fonctionnalité (s'il n'y en a pas déjà un pour cela).

1
Matthew Boynes