Adaugă pagină cu șablon personalizat programatic
Încerc să adaug o pagină cu șablon dintr-un plugin, iar fișierul șablonului se află în folderul plugin-ului. Este posibil acest lucru? Iată codul meu:
global $user_ID;
$new_post = array(
'post_title' => 'Pagină Șablon Test', // Titlul paginii de test
'post_content' => 'Un text oarecare', // Conținutul
'post_status' => 'publish', // Status publicat
'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('Eroare la crearea paginii șablon');
} else {
update_post_meta($post_id, '_wp_page_template', 'tp-file.php');
}
tp-file.php este pagina mea șablon personalizată. Când pun acel fișier în folderul temei (my-theme), funcționează bine, dar vreau să fac acest lucru cu fișierul din folderul plugin-ului astfel încât să nu fie nevoie ca utilizatorii să copieze acel fișier din folderul plugin-ului în folderul șablonului. Este posibil acest lucru? Aveți vreo idee?

Articolul menționat este pe drumul cel bun, dar voi simplifica lucrurile pentru tine.. ;)
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;
}
Filtrul verifică în esență dacă șablonul tău special este setat pentru pagina curentă și, dacă da, actualizează calea pentru a indica către șablonul din pluginul tău.
Doar asigură-te că calea este corectă, altfel vei întâmpina erori de includere... :)
Urmărire #1
Prima problemă este că WordPress validează orice șablon setat ca șablon de pagină, adică verifică dacă fișierul se află în directorul temei și dacă este un fișier de șablon valid. Dacă nu, trece peste el și include un șablon mai generic, cum ar fi page.php...
Totuși, acest lucru nu schimbă faptul că câmpul meta păstrează valoarea șablonului tău personalizat, iar is_page_template( 'tp-file.php' )
va returna corect „true” dacă este folosit în locul condiției mele anterioare, de exemplu...
// Filtrează șablonul paginii
add_filter('page_template', 'catch_plugin_template');
// Callback pentru filtrul de șablon
function catch_plugin_template($template) {
// Dacă tp-file.php este șablonul setat
if( is_page_template('tp-file.php') )
// Actualizează calea (trebuie să fie o cale, folosește WP_PLUGIN_DIR și nu WP_PLUGIN_URL)
$template = WP_PLUGIN_DIR . '/tp-test/tp-file.php';
// Returnează
return $template;
}
NOTĂ: Am modificat codul să folosească WP_PLUGIN_DIR
, deoarece constanta WP_PLUGIN_URL
nu este potrivită pentru căi... (includerile trebuie să folosească o cale, nu un URL).
O problemă, și aceasta nu este ceva ce poți repara, este că atunci când vizualizezi pagina din zona de administrare, în timpul editării, șablonul nu va fi listat ca activ, iar salvarea modificărilor ar putea schimba șablonul activ. Nu putem face prea multe în acest sens, deoarece dropdown-ul pentru șabloane este generat de o funcție care scanează fișierele temei și nu există hook-uri care să ne permită extinderea listei cu șabloane din plugin.
Personal, aș sugera ca soluție alternativă să salvezi un câmp meta suplimentar pentru fiecare pagină creată folosind pluginul tău special, apoi să adaugi un hook la save_post
sau wp_insert_post_data
pentru a verifica dacă acest câmp meta există. Dacă există, verifică și dacă șablonul paginii este setat la tp-file.php
, iar dacă nu, îl actualizează. Câmpul meta suplimentar ar funcționa ca un „flag” pentru a indica care pagini necesită șablonul din plugin.
Iată pluginul tău funcționând în forma sa cea mai simplă (da, l-am testat)... :)
<?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( 'Acest plugin necesită WordPress 2.9 sau mai nou. <a href="http://codex.wordpress.org/Upgrading_WordPress">Te rog actualizează!</a>' );
// Adaugă callback pentru meniul de administrare
add_action('admin_menu', 'create_tp_menu');
// Callback pentru adăugarea elementelor de meniu
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' => 'Text exemplu',
'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('Eroare la crearea paginii de șablon');
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">Creează Pagină de Șablon</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="Creează Pagină de Șablon" name="btn_submit" />
</form>
</fieldset>
<?php
}
// Filtrează șablonul paginii
add_filter('page_template', 'catch_plugin_template');
// Callback pentru filtrul de șablon
function catch_plugin_template($template) {
// Dacă tp-file.php este șablonul setat
if( is_page_template('tp-file.php') )
// Actualizează calea (trebuie să fie o cale, folosește WP_PLUGIN_DIR și nu WP_PLUGIN_URL)
$template = WP_PLUGIN_DIR . '/tp-test/tp-file.php';
// Returnează
return $template;
}
Sper că acest lucru clarifică lucrurile.. :)

Mulțumesc @t31os Am încercat și nu a funcționat, apoi am găsit acest http://adambrown.info/p/wp_hooks/hook/page_template care este învechit, ai alte idei?

Am încercat și ceva de genul acesta, dar nu a funcționat: $pt = get_page_templates(); $pt['TP testing'] = WP_PLUGIN_URL . '/tp-test/tp-file.php';

Funcționează perfect la mine... Am nevoie de mai multe detalii decât "nu a funcționat"...

Se pare că fișierele de șablon nu sunt activate în subdirector, am observat asta în funcția get_page_templates din theme.php, ai alte idei?

Nu este relevant, codul pe care l-am furnizat va funcționa perfect, cu condiția ca calea să fie setată corect și ca pagina solicitată să aibă _wp_page_template
setat la tp-file.php
... Tocmai l-am testat din nou pentru a fi sigur și am confirmat că funcționează (va trebui să văd mai multe detalii din codul tău dacă vrei să te ajut să înțelegi de ce nu funcționează în configurația ta).

Mulțumesc pentru timpul acordat, codul meu nu s-a schimbat, singurul lucru este că am adăugat codul tău în fișierul principal al plugin-ului meu, aruncă o privire aici: http://pastebin.com/sNR9s0sP

De asemenea, am verificat din nou tabelul wp_postmeta, pare în regulă

Ok, dar ce se întâmplă când încarci o pagină care are _wp_page_template
setat la tp-file.php
? Vezi vreo eroare de include, vezi o pagină goală sau vezi altceva? Ajută-mă să te ajut... ;)

Văd "Un text" ca pe o pagină normală, iar dacă merg în backend, văd că șablonul paginii este setat la cel implicit și nu apare în listă fișierul meu de șablon

Mă pregătesc să merg la culcare în următoarele minute, dar voi clarifica problema mâine pentru tine. Atâta timp cât câmpul meta _wp_page_template
rămâne setat corect, ar trebui să funcționeze, indiferent că nu apare în partea de administrare (ceea ce este de așteptat - voi explica în actualizarea răspunsului mâine).

Hei, este ciudat, codul nu funcționează când formularul este într-un fișier separat, dar dacă este împreună, atunci funcționează.

Încearcă să setezi o acțiune pe formularul tău, de ex. action="<?php admin_url( '/?page=tp-teste' ) ?>"
, pentru a te asigura că se trimite corect către pagina ta de plugin.

Filtrul page_template
este acum învechit. (http://adambrown.info/p/wp_hooks/hook/page_template)
Încercați să utilizați single_template
(sau archive_template
pentru șabloanele de arhivă) în schimb.
Bazat pe răspunsul lui @t31os:
// Filtru pentru șablonul de pagină
add_filter('single_template', 'catch_plugin_template');
// Funcția de callback pentru filtrul de șablon
function catch_plugin_template($template) {
// Dacă tp-file.php este șablonul setat
if( is_page_template('tp-file.php') )
// Actualizează calea (trebuie să fie o cale, folosește WP_PLUGIN_DIR și nu WP_PLUGIN_URL)
$template = WP_PLUGIN_DIR . '/tp-test/tp-file.php';
// Returnează
return $template;
}

dacă filtrul single_template
nu a funcționat, poți folosi acest filtru;
add_filter('template_include', 'catch_plugin_template');
luat de aici; https://www.pradipdebnath.com/2019/08/17/how-to-add-page-template-from-plugin-in-wordpress/

Nu sunt sigur dacă este învechit, doar s-a schimbat începând cu versiunea 4.7. https://developer.wordpress.org/reference/hooks/type_template/.Argumentul este gol dacă tema(ele) nu oferă șablonul, nu dacă pagina l-a selectat (l-a salvat) în baza de date din meniul dropdown.

O problemă, și aceasta nu este ceva ce poți repara, este că atunci când vizualizezi pagina din zona de administrare, în timpul editării paginii, șablonul nu va fi listat ca șablonul activ, iar salvarea modificărilor ar putea, desigur, să schimbe șablonul activ. Nu prea putem face ceva în acest sens, meniul derulant cu șabloane de pagină este generat de o funcție care scanează fișierele temei, nu există hook-uri disponibile care să ne permită să extindem lista cu șabloane din plugin-uri.
De fapt, am găsit un hook într-un alt thread care face exact asta:
WordPress: Poți crea șabloane de pagină programatic?
Lipesc codul aici pentru comoditate:
CONST CUSTOM_PAGE_TEMPLATES = array(
array('slug' => 'home', 'label' => 'Acasă'),
array('slug' => 'content-page', 'label' => 'Pagină de conținut'),
array('slug' => 'ordering', 'label' => 'Comandă'),
array('slug' => 'reviews', 'label' => 'Recenzii')
);
/**
* Adaugă șabloane de pagină fără fișiere în meniul derulant de șabloane
*/
add_filter('theme_page_templates', function($page_templates, $wp_theme, $post) {
foreach(CUSTOM_PAGE_TEMPLATES as $template) {
// Adaugă dacă nu există deja
if (!isset($page_templates[$template['slug']])) {
$page_templates[$template['slug']] = $template['label'];
}
}
return $page_templates;
}, PHP_INT_MAX, 3);
Sper că acest lucru ajută pe cineva.
