Aggiungere programmaticamente una pagina con template personalizzato
Sto cercando di aggiungere un template di pagina da un plugin, e il mio file template si trova nella cartella del plugin. È possibile? Ecco il mio codice:
global $user_ID;
$new_post = array(
'post_title' => 'Pagina Template di Test',
'post_content' => 'Un po\' di testo',
'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('Errore nella creazione della pagina template');
} else {
update_post_meta($post_id, '_wp_page_template', 'tp-file.php');
}
tp-file.php è la mia pagina template personalizzata. Quando metto quel file nella cartella my-theme, funziona bene, ma voglio farlo con il file dalla cartella del plugin così non devo costringere gli utenti a copiare quel file dalla cartella del plugin alla cartella del template. È possibile? Qualche idea?

L'articolo linkato è sulla strada giusta, ma lo semplificherò per te.. ;)
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;
}
Il filtro fondamentalmente verifica se il tuo template di pagina speciale è impostato per la pagina corrente, se lo è, aggiorna il percorso per puntare al template del tuo plugin.
Assicurati solo che il percorso sia corretto, altrimenti vedrai errori di inclusione... :)
Follow-up #1
Ok, il primo problema è che WordPress convalida qualsiasi template impostato come template di pagina, cioè verifica se il file si trova nella cartella del tema ed è un file di template valido, altrimenti lo salta e include un template più generico, come page.php...
Tuttavia, questo non cambia il fatto che il campo meta conservi ancora il valore del tuo template personalizzato, e anche is_page_template( 'tp-file.php' )
restituirà correttamente true se usato al posto della mia precedente condizione, ad esempio..
// Filtra il template di pagina
add_filter('page_template', 'catch_plugin_template');
// Callback del filtro per il template di pagina
function catch_plugin_template($template) {
// Se tp-file.php è il template impostato
if( is_page_template('tp-file.php') )
// Aggiorna il percorso (deve essere un percorso, usa WP_PLUGIN_DIR e non WP_PLUGIN_URL)
$template = WP_PLUGIN_DIR . '/tp-test/tp-file.php';
// Restituisci
return $template;
}
NOTA: Ho modificato il codice per usare WP_PLUGIN_DIR
poiché la costante WP_PLUGIN_URL
non è adatta per i percorsi... (gli include devono usare un percorso, non un URL).
Un problema, e questo non è qualcosa che puoi risolvere, è che quando visualizzi la pagina dall'area di amministrazione, durante la modifica della pagina, il template non sarà elencato come template attivo, e salvare le modifiche potrebbe ovviamente cambiare il template attivo. Non c'è molto che possiamo fare lì, il menu a discesa dei template di pagina è generato da una funzione che scandisce i file del tema, non ci sono hook che permetterebbero di estendere la lista con i template dei plugin.
Personalmente, quello che suggerirei, come soluzione alternativa, sarebbe salvare un campo meta aggiuntivo per ogni pagina creata usando la tua pagina speciale del plugin, poi aggiungere un hook su save_post
o wp_insert_post_data
e verificare se questo campo meta esiste, se esiste, verificare anche che il template di pagina sia impostato su tp-file.php
, e se non lo è, aggiornarlo a tp-file.php
. Il campo meta aggiuntivo sarebbe solo un flag, per indicare quali pagine devono avere il template del plugin associato.
Ecco il tuo plugin che funziona nella sua forma più basilare (sì, l'ho testato)... :)
<?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( 'Questo plugin richiede WordPress 2.9 o più recente. <a href="http://codex.wordpress.org/Upgrading_WordPress">Aggiorna per favore!</a>' );
// Aggiungi callback al menu di amministrazione
add_action('admin_menu', 'create_tp_menu');
// Callback per aggiungere voci di menu
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' => 'Qualche testo',
'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('Errore nella creazione della pagina template');
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">Crea Pagina Template</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="Crea Pagina Template" name="btn_submit" />
</form>
</fieldset>
<?php
}
// Filtra il template di pagina
add_filter('page_template', 'catch_plugin_template');
// Callback del filtro per il template di pagina
function catch_plugin_template($template) {
// Se tp-file.php è il template impostato
if( is_page_template('tp-file.php') )
// Aggiorna il percorso (deve essere un percorso, usa WP_PLUGIN_DIR e non WP_PLUGIN_URL)
$template = WP_PLUGIN_DIR . '/tp-test/tp-file.php';
// Restituisci
return $template;
}
Spero che questo aiuti a chiarire le cose.. :)

Grazie @t31os ho provato ma non ha funzionato, poi ho trovato questo http://adambrown.info/p/wp_hooks/hook/page_template che è deprecato, qualche altra idea?

Ho anche provato qualcosa del genere, ma non ha funzionato: $pt = get_page_templates(); $pt['TP testing'] = WP_PLUGIN_URL . '/tp-test/tp-file.php';

Per me funziona perfettamente... avrei bisogno di più dettagli oltre a "non ha funzionato"..

Sembra che i file template non siano abilitati nella sottocartella, ho trovato questo nella funzione get_page_templates in theme.php, altre idee?

Non è rilevante, il codice che ho fornito funzionerà perfettamente purché il percorso sia impostato correttamente e la pagina richiesta abbia _wp_page_template
impostato su tp-file.php
... L'ho appena ritestato per sicurezza, e ho confermato nuovamente che funziona (dovrò vedere più del tuo codice se vuoi che ti aiuti a capire perché non funziona nel tuo setup).

Grazie per il tuo tempo, il mio codice non è cambiato, l'unica cosa è che ho aggiunto il tuo codice al mio file principale del plugin, dai un'occhiata qui: http://pastebin.com/sNR9s0sP

Ho anche ricontrollato la mia tabella wp_postmeta, sembra tutto a posto

Ok, ma cosa succede quando carichi una pagina che ha _wp_page_template
impostato su tp-file.php
? Vedi un errore di inclusione, vedi una pagina bianca, vedi qualcos'altro? Aiutami ad aiutarti... ;)

Vedo "Qualche testo" come se fosse una pagina normale, e se vado nel backend vedo che il template della pagina è impostato su predefinito, e non c'è nella lista il mio file template

Tra qualche minuto vado a letto, ma domani ti chiarirò il problema. Finché il campo meta _wp_page_template
rimane impostato correttamente dovrebbe funzionare, indipendentemente dal fatto che non venga visualizzato nella parte amministrativa (cosa che ci si aspetta - spiegherò meglio nell'aggiornamento della risposta domani).

Ehi, è strano, il codice non funziona quando il modulo è in un file separato, ma se è tutto insieme, allora funziona.

Prova a impostare un'azione nel tuo modulo, ad es. action="<?php admin_url( '/?page=tp-teste' ) ?>"
, per assicurarti che venga inviato correttamente alla pagina del tuo plugin.

Il filtro page_template
è ora deprecato. (http://adambrown.info/p/wp_hooks/hook/page_template)
Prova a utilizzare single_template
(o archive_template
per i template di archivio) invece.
Basato sulla risposta di @t31os:
// Filtro per il template della pagina
add_filter('single_template', 'catch_plugin_template');
// Callback per il filtro del template
function catch_plugin_template($template) {
// Se tp-file.php è il template impostato
if( is_page_template('tp-file.php') )
// Aggiorna il percorso (deve essere un percorso, usa WP_PLUGIN_DIR e non WP_PLUGIN_URL)
$template = WP_PLUGIN_DIR . '/tp-test/tp-file.php';
// Restituisci
return $template;
}

se il filtro single_template
non ha funzionato, puoi utilizzare questo filtro;
add_filter('template_include', 'catch_plugin_template');
preso da qui; https://www.pradipdebnath.com/2019/08/17/how-to-add-page-template-from-plugin-in-wordpress/

Non sono sicuro se sia deprecato, è cambiato dalla versione 4.7. https://developer.wordpress.org/reference/hooks/type_template/.L'argomento è vuoto se il/i tema/i non forniscono il template, non se la pagina lo ha selezionato (memorizzato) nel database dal menu a discesa di selezione.

Un problema, e questo non è qualcosa che puoi risolvere, è che quando visualizzi la pagina dall'area di amministrazione, durante la modifica della pagina, il template non verrà elencato come quello attivo, e salvare le modifiche potrebbe naturalmente cambiare il template attivo. Non c'è molto che possiamo fare lì, il menu a discesa dei template di pagina è generato da una funzione che scansiona i file del tema, non ci sono hook disponibili che io possa vedere che ci permettano di estendere la lista con template di plugin.
In realtà ho trovato un hook in un'altra discussione che fa esattamente questo:
WordPress: È possibile creare template di pagina programmaticamente?
Incollerò il codice qui per comodità:
CONST CUSTOM_PAGE_TEMPLATES = array(
array('slug' => 'home', 'label' => 'Home'),
array('slug' => 'content-page', 'label' => 'Pagina Contenuti'),
array('slug' => 'ordering', 'label' => 'Ordini'),
array('slug' => 'reviews', 'label' => 'Recensioni')
);
/**
* Aggiunge template di pagina senza file al menu a discesa dei template
*/
add_filter('theme_page_templates', function($page_templates, $wp_theme, $post) {
foreach(CUSTOM_PAGE_TEMPLATES as $template) {
// Aggiunge se non esiste già
if (!isset($page_templates[$template['slug']])) {
$page_templates[$template['slug']] = $template['label'];
}
}
return $page_templates;
}, PHP_INT_MAX, 3);
Spero che questo possa essere utile a qualcuno.
