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

10

Je cherche depuis quelques heures 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 spécifiquement de faire est d'ajouter une option à la liste des modèles de page disponibles lors de la modification d'une page, et de ne pas utiliser une autre méthode commeif( is_page( 'page-slug' ) ) { /* etc */ }

Existe-t-il une variable globale que je peux modifier pour ce faire?

Éditer:

J'utilise actuellement ce code, basé sur le lien @ m0r7if3r m'a donné dans un commentaire, le problème est qu'il exécutera cette fonction 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;
    }

}

Modifier 2:

Il semble que cette fonctionnalité sera publiée dans une future mise à jour, j'ai lu pas mal de tickets Trac à ce sujet et il y a eu des discussions mais pas de vraie réponse (en espérant 3.4). Répertoriera ici les URL des tickets Trac.

Modifier 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 / ajout d'une nouvelle page. J'essaye quelques choses et mettrai à jour ma question bientôt.

Jared
la source
2
Avez-vous essayé quelque chose comme ça ?
mor7ifer
@ m0r7if3r (Si vous essayez cela, veuillez laisser un message comment cela a fonctionné - Merci!)
kaiser
@kaiser J'ai essayé le code qu'il a recommandé, le seul lien manquant est d'obtenir la meta box pour ajouter le modèle à la liste déroulante (pour autant que je sache!).
Jared
@Jared Regardez cette réponse de moi à un Q similaire et aux tickets de trac associés en bas du a. Ajoutez votre code) S'il n'apparaît pas sur chaque page, vous utilisez les mauvais crochets pour exécuter l'instance. Quels crochets utilisez-vous?
kaiser
@kaiser J'utilise le page_templatehook, le code ci-dessus dans ma modification est ce qui est actuellement utilisé. Dois-je utiliser le template_redirectcrochet puis y ajouter le page_templatefiltre?
Jared

Réponses:

4

Filtres? N'importe qui?

Il n'y a pas de filtre pour vous aider: page_template_dropdown($template);est utilisé pour créer la liste déroulante et il n'est pas filtrable.

Vous vous glissez dans le tableau des 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 lors de l'examen, get_themes();il n'y a aucune possibilité d'intercepter la liste des modèles. De plus, nous avons le problème, qu'il n'y a aucune chance d'obtenir un modèle en dehors du répertoire des thèmes…

... truquer 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, la chose la plus simple serait d'enregistrer 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 sais pas si cela fonctionnera .

Pendant l'activation du plugin: vous devez ensuite placer un style.css.phpfichier dans votre templatesdossier. 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. Mettez ensuite à jour votre thème actif vers votre plugin.

Inconvénient n ° 2: à propos de l'interface utilisateur «Apparence«… Peut-être ajouter une note que ce «thème» n'est pas destiné à être utilisé comme thème réel. Je laisse le reste de «Évitez d'activer ce thème» à votre imagination. Quoi qu'il en soit: cela devrait fonctionner.

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

kaiser
la source
Je suppose donc qu'il n'existe aucun moyen réel d'utiliser des modèles de page personnalisés à partir d'un thème inactif, n'est-ce pas? Je pourrais enregistrer un répertoire de thèmes mais les modèles ne sont cependant pas disponibles à moins que ce thème ne soit actif.
Jared
1
Pas vraiment. Ce n'est tout simplement pas censé être et donc un manque de noyau. Avez-vous essayé le lien vers ipstenu ci-dessus? J'ai déjà essayé de suivre cette voie, mais je me suis retrouvé dans une voie morte - avec une autre solution. Le mieux serait de suivre les tickets, de les pousser et de les lier où que vous soyez. : /
kaiser
2

À titre de suggestion pour un travail potentiel, avez-vous envisagé d'utiliser le système de fichiers WordPress pour écrire un fichier de modèle de page de votre plugin dans votre répertoire de thème actif actuel? Selon le degré de contrôle que vous souhaitez sur ce processus, votre plugin peut écrire le fichier lors de l'activation et le supprimer lors de la désinstallation. Alternativement, vous pouvez créer des fichiers de modèle de page de manière dynamique à partir de l'interface utilisateur de votre 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 post-édition. En théorie, vous pouvez également supprimer le modèle de page de votre interface utilisateur de plugin en cliquant sur un bouton et ajouter de manière similaire 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 aviez l'intention de faire au moyen d'un crochet dans la prochaine version principale.

Adam
la source
1
J'avais une méthode exactement comme celle-ci qui fonctionnait auparavant, mais j'ai eu de nombreux problèmes lorsque je l'ai essayée, car lorsqu'un utilisateur changeait de thème, il ne supprimait pas le fichier de modèle et s'il copiait son thème actif et le mettait sur un autre site , ils risqueraient de télécharger un fichier de modèle personnalisé qui ne fonctionnerait pas. Je sais qu'il existe plusieurs solutions pour cela, mais je veux vraiment que ce soit automatique . +1 pour la suggestion cependant.
Jared
1
Salut Jared, j'étais également préoccupé par le même problème. La seule solution à laquelle je pourrais penser pour étendre davantage cette méthode alternative serait d'avoir le plugin lors de son activation obtenir le nom du thème actuel, puis si un utilisateur désactive / change de thème, vous pouvez supprimer le fichier modèle de ce thème et le réécrire dans le nouveau activé thème. Jetez un œil à ce lien où il a créé ses propres crochets d'activation / désactivation pour vérifier les thèmes. Avec un peu de code supplémentaire, je pense que c'est faisable.
Adam
Absolument, je pense que cela peut fonctionner. Je vais essayer et publier les résultats dans ma question. Merci pour le lien, ça aide!
Jared
1

J'ai parcouru la source, et de manière assez choquante, il ne semble pas y avoir de moyen de le faire! Mon hack suggéré serait d'ajouter une deuxième boîte de méta avec un menu déroulant de remplacement de thème / deuxième thème. Accrochez-vous ensuite à ce filtre:

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

pour renvoyer votre fichier de thème s'il a été remplacé. Bien sûr, vous ne souhaitez ajouter add_filter que si c'est le message que vous souhaitez.

Si vous voulez être fantaisiste, 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ère également d'ajouter un ticket Trac demandant cette fonctionnalité (s'il n'y en a pas déjà un dedans).

Matthew Boynes
la source
1
d'accord w / suggérant cela pour trac.
helgatheviking
Il semble déjà être dans le trac: core.trac.wordpress.org/ticket/15803
Jared
1
Je viens d'étudier cela pour un autre Q sur les modèles de type de publication unique . Vous pouvez trouver les billets Trac à la fin de la réponse. Let espoir pour 3.4.
kaiser
1

J'ai accompli cela dans le passé en supprimant la métabox de modèle de page par défaut, puis en ajoutant votre propre métabox. J'ai eu la nouvelle metabox utiliser les get_page_templates intégrés et ensuite ajouté les autres dont j'avais besoin par programme. Lors d'une sauvegarde, il peut mettre à jour le modèle de page, tout comme WordPress.

gruvii
la source
Pourriez-vous afficher le code complet? Actuellement, ce n'est qu'un concept approximatif. Merci.
kaiser
1

Découvrez le crochet theme_page_templates, utilisé par la get_page_templatesfonction, filtre ajouté depuis 3.9 mis à jour en 4.4:

apply_filters( 'theme_page_templates', $page_templates, $this, $post );
William Gu
la source
expliqué plus en détail ici: wordpress.stackexchange.com/a/255820/75495
cjbj
-2

Un résultat de recherche avec DuckDuckGo ajouter un modèle de page wordpress a révélé la réponse pour moi sur une page wpmu.org intitulée Tutoriel de modèle de page personnalisée WordPress .

Essentiellement, dans le répertoire du thème, wp-content / themes / your-theme , copiez un modèle de page existant dans un nouveau nom de fichier php de votre choix. Modifiez le nouveau fichier, en prenant soin de modifier la valeur magique de la propriété "Nom du modèle:" dans le commentaire en haut du fichier.

C'était tout ce qu'il y avait à faire. Il est possible que cette fonctionnalité soit postérieure à la question. J'utilise WP 3.5 avec le thème de vingt_eleven.

Il est également possible qu'il existe des moyens plus propres d'étendre un thème. Des modifications comme celle-ci peuvent être remplacées par des mises à jour de thème. Mea culpa.

Douglas Lovell
la source
J'ai besoin d'une solution pour ajouter le modèle à la liste déroulante à partir d'un plugin, pas d'un thème. :(
Jared