Adăugarea metabox-ului „Atribute Pagină” și a șabloanelor de pagină în editorul de articole?

10 oct. 2010, 20:40:15
Vizualizări: 34K
Voturi: 14

(Notă moderator: Titlul original era „Cum pot adăuga selectorul „Atribute Pagină” și/sau „Atribute Pagină > Șablon” în editorul de ARTICOLE”)

WordPress permite în prezent atribuirea unui „șablon” doar pentru Pagini (adică post_type=='page'). Aș dori să extind această funcționalitate și la Articole (adică post_type=='post').

Cum pot adăuga metabox-ul „Atribute Pagină” și mai precis, selectorul de șabloane în editorul de articole?

Presupun că acesta este un cod pe care îl voi plasa în functions.php al temei mele.

ACTUALIZARE: Am reușit să adaug meniul derulant cu șabloane hardcodate în editorul de articole, prin simpla adăugare a codului HTML pentru caseta de selectie în caseta mea existentă de opțiuni meta personalizate. Iată codul pe care îl folosesc pentru asta...

add_meta_box('categorydiv2', __('Opțiuni Articol'), 'post_categories_meta_box_modified', 'post', 'side', 'high');

Și iată funcția care afișează opțiunile și caseta de selectare a șablonului...

//adaugă caseta personalizată de categorii
function post_categories_meta_box_modified() {
    global $post;
    if( get_post_meta($post->ID, '_noindex', true) ) $noindexChecked = " checked='checked'";
    if( get_post_meta($post->ID, '_nofollow', true) ) $nofollowChecked = " checked='checked'";
?>
<div id="categories-all" class="ui-tabs-panel">
    <ul id="categorychecklist" class="list:category categorychecklist form-no-clear">
        <li id='noIndex' class="popular-category"><label class="selectit"><input value="noIndex" type="checkbox" name="chk_noIndex" id="chk_noIndex"<?php echo $noindexChecked ?> /> noindex</label></li> 
        <li id='noFollow' class="popular-category"><label class="selectit"><input value="noFollow" type="checkbox" name="chk_noFollow" id="chk_noFollow"<?php echo $nofollowChecked ?> /> nofollow</label></li>
    </ul>

    <p><strong>Șablon</strong></p> 
    <label class="screen-reader-text" for="page_template">Șablon Articol</label><select name="page_template" id="page_template"> 
    <option value='default'>Șablon Implicit</option> 
    <option value='template-wide.php' >Fără Bara Laterală</option>
    <option value='template-salespage.php' >Pagina de Vânzări</option>
    </select>
</div>
<?php
}

Și în final, codul pentru captarea valorilor selectate la salvare...

function save_post_categories_meta($post_id) {
    if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return $post_id;
    $noIndex = $_POST['chk_noIndex'];
    $noFollow = $_POST['chk_noFollow'];
    update_post_meta( $post_id, '_noindex', $noIndex );
    update_post_meta( $post_id, '_nofollow', $noFollow );
    return $post_id;
}

Acum, cred că tot ce mai rămâne este (1) captarea șablonului selectat și adăugarea lui în meta-ul articolului și (2) modificarea fișierelor index.php și single.php astfel încât să folosească șablonul ales.

2
Comentarii

@Scott B: Ei bine, am scris întregul meu răspuns înainte să văd că și tu lucrai la el, și se pare că ai abordat-o într-o direcție oarecum diferită față de întrebarea ta originală cu opțiunile tale de no follow și no index. Sper că ceea ce am făcut încă are valoare pentru tine. Dacă nu, poate va ajuta pe alții.

MikeSchinkel MikeSchinkel
11 oct. 2010 02:14:37

Da, ai răspuns la întrebare. Am abordat-o puțin diferit odată ce am realizat că nu trebuie să analizez directorul și puteam hardcoda valorile pentru șabloanele mele specifice. Probabil că tot voi avea nevoie să împrumut o parte din codul tău pentru a face ca WP să folosească șablonul corect atribuit pentru postare.

Scott B Scott B
11 oct. 2010 19:36:46
Toate răspunsurile la întrebare 2
7
15

Nu-mi place să fiu cel care aduce vești proaste, dar WordPress codifică funcționalitatea Șablonului de Pagină doar pentru tipul de postare "page", cel puțin în versiunea 3.0 (acest lucru s-ar putea schimba în versiunile viitoare, dar nu există încă o inițiativă concretă despre care să știu. Așadar, acesta este unul dintre puținele momente când mă chinui să găsesc o soluție fără a modifica nucleul.)

Soluția pe care am găsit-o este să copiez codul relevant din nucleul WordPress și să-l modific pentru nevoile noastre. Iată pașii (numerele de linii sunt din versiunea 3.0.1):

  1. Copiați funcția page_attributes_meta_box() de la linia 535 din /wp-admin/includes/meta-boxes.php și modificați-o conform nevoilor.

  2. Scrieți un hook add_meta_boxes pentru a adăuga metabox-ul creat la pasul #1.

  3. Copiați funcția get_page_templates() de la linia 166 din /wp-admin/includes/theme.php și modificați-o conform nevoilor.

  4. Copiați funcția page_template_dropdown() de la linia 2550 din /wp-admin/includes/template.php și modificați-o conform nevoilor.

  5. Adăugați un Șablon de Postare în tema dumneavoastră.

  6. Scrieți un hook save_post pentru a permite salvarea numelui fișierului de șablon la salvare.

  7. Scrieți un hook single_template pentru a permite încărcarea șablonului de postare pentru postările asociate.

Să începem!


1. Copiați funcția page_attributes_meta_box()

Ca prim pas, trebuie să copiați funcția page_attributes_meta_box() de la linia 535 din /wp-admin/includes/meta-boxes.php și am ales să o redenumesc post_template_meta_box(). Deoarece ați cerut doar șabloane de pagini, am omis codul pentru specificarea unei postări părinte și pentru specificarea ordinii, ceea ce simplifică codul. De asemenea, am ales să folosesc postmeta pentru aceasta în loc să încerc să reutilizez proprietatea page_template pentru a evita potențiale incompatibilități. Iată codul:

function post_template_meta_box($post) {
  if ( 'post' == $post->post_type && 0 != count( get_post_templates() ) ) {
    $template = get_post_meta($post->ID,'_post_template',true);
    ?>
<label class="screen-reader-text" for="post_template"><?php _e('Șablon de Postare') ?></label><select name="post_template" id="post_template">
<option value='default'><?php _e('Șablon Implicit'); ?></option>
<?php post_template_dropdown($template); ?>
</select>
<?php
  } ?>
<?php
}

2. Scrieți un hook add_meta_boxes

Următorul pas este să adăugați metabox-ul folosind hook-ul add_meta_boxes:

add_action('add_meta_boxes','add_post_template_metabox');
function add_post_template_metabox() {
    add_meta_box('postparentdiv', __('Șablon de Postare'), 'post_template_meta_box', 'post', 'side', 'core');
}

3. Copiați funcția get_page_templates()

Am presupus că ar avea sens să diferențiem între șabloanele de pagini și cele de postări, de unde necesitatea unei funcții get_post_templates() bazată pe get_page_templates() de la linia 166 din /wp-admin/includes/theme.php. În loc să folosim markerul Template Name: pe care îl folosesc șabloanele de pagini, această funcție folosește un marker Post Template:, așa cum vedeți mai jos.

De asemenea, am filtrat inspectarea functions.php (nu sunt sigur cum a funcționat vreodată corect get_page_templates() fără asta, dar în fine!). Singurul lucru rămas este să schimbăm referințele la cuvântul page în post pentru lizibilitate în viitor:

function get_post_templates() {
  $themes = get_themes();
  $theme = get_current_theme();
  $templates = $themes[$theme]['Template Files'];
  $post_templates = array();

  if ( is_array( $templates ) ) {
    $base = array( trailingslashit(get_template_directory()), trailingslashit(get_stylesheet_directory()) );

    foreach ( $templates as $template ) {
      $basename = str_replace($base, '', $template);
      if ($basename != 'functions.php') {
        // nu permite fișiere de șablon în subdirectoare
        if ( false !== strpos($basename, '/') )
          continue;

        $template_data = implode( '', file( $template ));

        $name = '';
        if ( preg_match( '|Post Template:(.*)$|mi', $template_data, $name ) )
          $name = _cleanup_header_comment($name[1]);

        if ( !empty( $name ) ) {
          $post_templates[trim( $name )] = $basename;
        }
      }
    }
  }

  return $post_templates;
}

4. Copiați funcția page_template_dropdown()

La fel, copiați page_template_dropdown() de la linia 2550 din /wp-admin/includes/template.php pentru a crea post_template_dropdown() și schimbați-o să apeleze get_post_templates():

function post_template_dropdown( $default = '' ) {
  $templates = get_post_templates();
  ksort( $templates );
  foreach (array_keys( $templates ) as $template )
    : if ( $default == $templates[$template] )
      $selected = " selected='selected'";
    else
      $selected = '';
  echo "\n\t<option value='".$templates[$template]."' $selected>$template</option>";
  endforeach;
}

5. Adăugați un Șablon de Postare

Următorul pas este să adăugați un șablon de postare pentru testare. Folosind markerul Post Template: menționat la pasul #3, copiați single.php din tema dumneavoastră în single-test.php și adăugați următorul antet de comentariu (asigurați-vă că modificați ceva în single-test.php pentru a putea observa că se încarcă în loc de single.php):

/**
 * Post Template: Șablonul Meu de Test
 */

După ce ați finalizat pașii #1 până la #5, puteți vedea metabox-ul "Șabloane de Postare" apărând în editorul de postări:

Cum arăta un metabox de Șabloane de Postare adăugat în WordPress 3.0
(sursa: mikeschinkel.com)

6. Scrieți un hook save_post

Acum că editorul este configurat, trebuie să salvați numele fișierului de șablon în postmeta când utilizatorul apasă "Publică". Iată codul pentru asta:

add_action('save_post','save_post_template',10,2);
function save_post_template($post_id,$post) {
  if ($post->post_type=='post' && !empty($_POST['post_template']))
    update_post_meta($post->ID,'_post_template',$_POST['post_template']);
}

7. Scrieți un hook single_template

În final, trebuie să determinați WordPress să folosească noile șabloane de postare. Faceți acest lucru prin conectarea la hook-ul single_template și returnarea numelui de șablon dorit pentru postările care au unul asignat:

add_filter('single_template','get_post_template_for_template_loader');
function get_post_template_for_template_loader($template) {
  global $wp_query;
  $post = $wp_query->get_queried_object();
  if ($post) {
    $post_template = get_post_meta($post->ID,'_post_template',true);
    if (!empty($post_template) && $post_template!='default')
      $template = get_stylesheet_directory() . "/{$post_template}";
  }
  return $template;
}

Și asta e tot!

NOTĂnu am luat în considerare Tipurile Personalizate de Postare, doar post_type=='post'. În opinia mea, abordarea tipurilor personalizate de postare ar necesita diferențierea între diferitele tipuri de postări și, deși nu este foarte dificil, nu am încercat asta aici.

11 oct. 2010 02:11:33
Comentarii

Grozav! Am adormit cu un cod aproape complet în editor, având aceeași abordare de a copia funcțiile implicite din WordPress (era complet, dar nu l-aș fi postat din moment ce nu l-am testat). :)

sorich87 sorich87
11 oct. 2010 10:57:00

@sorich87 - Știi vechea zicală, "Cine doarme, pierde!" Serios acum, glumesc DOAR. Există doar o singură modalitate rezonabilă de a face să funcționeze, așa că nu e de mirare că codul tău ar fi la fel!

MikeSchinkel MikeSchinkel
11 oct. 2010 12:08:41

Mike, continuă să ne uimești. Mulțumesc mult că ți-ai luat timpul să rezolvi asta.

Scott B Scott B
11 oct. 2010 19:33:53

@sorich87 - Mulțumesc pentru implicare. Apreciez cu adevărat efortul depus.

Scott B Scott B
11 oct. 2010 19:34:22

@MikeSchinkel: :) a fost aproape exact la fel. @Scott B: cu plăcere!

sorich87 sorich87
11 oct. 2010 19:47:04

@Scott B: Nicio problemă, mă bucur că am putut ajuta. Caut întrebări relativ generice care ar putea ajuta potențial mulți oameni și încerc să răspund nu doar pentru persoana care pune întrebarea, ci și pentru cei care ar putea veni după.

MikeSchinkel MikeSchinkel
11 oct. 2010 23:12:22

Știe cineva dacă există o soluție mai bună acum în 2016?

JasonDavis JasonDavis
7 iul. 2016 08:59:47
Arată celelalte 2 comentarii
0

WordPress vă permite să adăugați Meta la Categorii utilizând un plugin:

Pentru a face acest lucru, trebuie să adăugați una dintre numeroasele extensii care adaugă meta la categorii (imitând ceea ce paginile primesc implicit), Simple Term Meta face treaba foarte bine.

Notă: Este necesar WordPress 3.x pentru a extinde Categoriile.

După aceea, puteți folosi:

  • add_term_meta
  • update_term_meta
  • get_term_meta

Utilizați Functions.php pentru a adăuga metode care să facă ceea ce doriți, de exemplu:

add_action('category_add_form_fields', 'category_metabox_add', 10, 1);

function category_metabox_add($tag) { ?>
    <div class="form-field">
        <label for="image-url"><?php _e('URL Imagine') ?></label>
        <input name="image-url" id="image-url" type="text" value="" size="40" aria-required="true" />
        <p class="description"><?php _e('Această imagine va fi miniatura afișată pe pagina categoriei.'); ?></p>
    </div>
<?php } 

add_action('created_category', 'save_category_metadata', 10, 1);

function save_category_metadata($term_id)
{
    if (isset($_POST['image-url'])) 
        update_term_meta( $term_id, 'image-url', $_POST['image-url']);                  
}

Apelarea noilor câmpuri în teme este ușoară:

<?php echo get_term_meta(get_query_var('cat'), 'image-url', true); ?>

Mai multe detalii și exemple: http://www.wphub.com/adding-metadata-taxonomy-terms/

14 sept. 2013 17:27:02