Dodawanie atrybutów strony Metabox i szablonów stron do strony edycji postów?

14

( Uwaga moderatorów: tytuł pierwotnie brzmiał „Jak dodać„ Edytory strony ”i / lub„ Atrybuty strony> Szablon ”do edytora POSTS”)

WP obecnie pozwala na przypisanie „szablonu” do stron (tj post_type=='page'.) Chciałbym rozszerzyć tę funkcjonalność również na posty (tj post_type=='post'.)

Jak mogę dodać meta box „Atrybuty strony” , a dokładniej przełącznik szablonów do edytora postów?

Zakładam, że to kod, który umieszczę w functions.phpmoim temacie.

AKTUALIZACJA: Udało mi się dodać menu rozwijane szablonów na stałe do mojego edytora postów, po prostu dodając pole wyboru HTML do mojego istniejącego niestandardowego okna opcji meta. Oto kod, którego używam do tego ...

add_meta_box('categorydiv2', __('Post Options'), 'post_categories_meta_box_modified', 'post', 'side', 'high');

A oto funkcja, która wypisuje opcje i pole wyboru szablonu ...

//adds the custom categories box
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>Template</strong></p> 
    <label class="screen-reader-text" for="page_template">Post Template</label><select name="page_template" id="page_template"> 
    <option value='default'>Default Template</option> 
    <option value='template-wide.php' >No Sidebar</option>
    <option value='template-salespage.php' >Salespage</option>
    </select>
</div>
<?php
}

I na koniec kod do przechwytywania wybranych wartości przy zapisie ...

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

Teraz wierzę, że wszystko, co zostało, to (1) przechwycenie wybranego szablonu i dodanie go do meta postu dla tego postu oraz (2) modyfikacja index.php i single.php, aby używał wybranego szablonu.

Scott B.
źródło
@ Scott B : Cóż, napisałem całą odpowiedź, zanim zobaczyłem, że też nad nią pracujesz, i wygląda na to, że podjąłeś ją w nieco innym kierunku niż twoje pierwotne pytanie bez odpowiedzi i bez opcji indeksu. Mam nadzieję, że to, co zrobiłem, wciąż ma dla ciebie wartość. Jeśli nie, może pomoże innym.
MikeSchinkel,
Tak, odpowiedziałeś na pytanie. Kiedy zdałem sobie sprawę, że nie muszę analizować katalogu, wybrałem nieco inny sposób. Nadal prawdopodobnie będę potrzebować pożyczyć trochę twojego kodu, aby WP mógł użyć poprawnego przypisanego szablonu dla posta.
Scott B,

Odpowiedzi:

12

Nienawidzę być nosicielem złych wiadomości, ale WordPress zakoduje na stałe funkcjonalność szablonu strony na typ postu „stronicowego” , przynajmniej w wersji 3.0 (co może się zmienić w przyszłych wersjach, ale nie ma konkretnej inicjatywy, o której istnieniu wiem, aby to zmienić jeszcze. Więc to jeden z niewielu razy, kiedy próbuję wymyślić, jak obejść coś bez rąbania rdzenia.)

Rozwiązaniem, które wymyśliłem, jest w zasadzie skopiowanie odpowiedniego kodu z rdzenia WordPress i zmodyfikowanie go do naszych potrzeb. Oto kroki (numery linii pochodzą z wersji 3.0.1):

  1. Skopiuj page_attributes_meta_box()funkcję z wiersza 535 /wp-admin/includes/meta-boxes.phpi zmodyfikuj odpowiednio.

  2. Kod add_meta_boxeshaka, aby dodać metaboks utworzony w # 1.

  3. Skopiuj get_page_templates()funkcję z wiersza 166 /wp-admin/includes/theme.php i zmodyfikuj w celu dopasowania.

  4. Skopiuj page_template_dropdown()funkcję z wiersza 2550 /wp-admin/includes/template.phpi zmodyfikuj w celu dopasowania.

  5. Dodaj szablon posta do swojego motywu.

  6. Kod save_posthaka, aby umożliwić zapisywanie nazwy pliku szablonu postu po zapisaniu.

  7. Kod single_templatehaka, aby umożliwić ładowanie szablonu postu dla powiązanych postów.

Teraz z tym!


1. Skopiuj page_attributes_meta_box()funkcję

Naszym pierwszym krokiem jest skopiowanie page_attributes_meta_box()funkcji z wiersza 535 /wp-admin/includes/meta-boxes.phpi postanowiłem ją zmienić post_template_meta_box(). Ponieważ poprosiłeś tylko o szablony stron, pominąłem kod określający post nadrzędny i określający kolejność, co znacznie upraszcza kod. Zdecydowałem się również użyć do tego postmeta, niż próbować ponownie użyć page_templatewłaściwości obiektu, aby uniknąć potencjalnych niezgodności spowodowanych przypadkowym sprzężeniem. Oto kod:

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('Post Template') ?></label><select name="post_template" id="post_template">
<option value='default'><?php _e('Default Template'); ?></option>
<?php post_template_dropdown($template); ?>
</select>
<?php
  } ?>
<?php
}

2. Kod add_meta_boxeshak

Następnym krokiem jest dodanie metaboksu za pomocą add_meta_boxeshaka:

add_action('add_meta_boxes','add_post_template_metabox');
function add_post_template_metabox() {
    add_meta_box('postparentdiv', __('Post Template'), 'post_template_meta_box', 'post', 'side', 'core');
}

3. Skopiuj get_page_templates()funkcję

Zakładałem, że sensowne byłoby jedynie rozróżnienie między szablonami strony a szablonem postu, dlatego potrzeba get_post_templates()funkcji opartej na get_page_templates()linii 166 z /wp-admin/includes/theme.php. Ale zamiast używać Template Name:znacznika, którego szablony stron używają, ta funkcja używa Post Template:znacznika, który można zobaczyć poniżej.

Odfiltrowałem też inspekcję functions.php (nie jestem pewien, jak to get_page_templates()działało bez tego poprawnie, ale cokolwiek!). Pozostało mi tylko zmienić odniesienia do tego słowa w pagecelu postzapewnienia czytelności konserwacji na drodze:

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') {
        // don't allow template files in subdirectories
        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. Skopiuj page_template_dropdown()funkcję

Podobnie skopiuj page_template_dropdown()z linii 2550, /wp-admin/includes/template.phpaby utworzyć post_template_dropdown()i po prostu zmień go na wywołanie get_post_templates()zamiast:

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. Dodaj szablon posta

Następnym krokiem jest dodanie szablonu postu do testowania. Za pomocą Post Template:znacznika wymienionego w kroku 3 skopiuj single.phpz motywu single-test.phpi dodaj następujący nagłówek komentarza ( pamiętaj, aby coś zmodyfikować, single-test.phpaby można było powiedzieć, że ładuje się zamiast single.php) :

/**
 * Post Template: My Test Template
 */

Po wykonaniu kroków od 1 do 5 na stronie edytora postów pojawi się metaboks „Szablony postów :

Jak wyglądał Metabox szablonów postów po dodaniu do WordPress 3.0
(źródło: mikeschinkel.com )

6. Kod save_posthak

Teraz, gdy edytor jest wyrównany, musisz zapisać nazwę pliku szablonu strony na postmeta, gdy użytkownik kliknie „Publikuj”. Oto kod do tego:

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. Zakoduj single_templatehak

I wreszcie, musisz faktycznie przekonać WordPressa do korzystania z nowych szablonów postów. Robisz to, przechwytując single_templatei zwracając żądaną nazwę szablonu dla tych postów, do których przypisano jeden:

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 o to chodzi!

UWAGA , że nie bierze pod uwagę niestandardowe typy post , tylko post_type=='post'. Moim zdaniem adresowanie niestandardowych typów postów wymagałoby rozróżnienia między różnymi typami postów i chociaż nie było to zbyt trudne, nie próbowałem tego tutaj.

MikeSchinkel
źródło
Świetny! Poszedłem spać z prawie kompletnym kodem w moim edytorze z tym samym podejściem do kopiowania domyślnych funkcji WordPressa (było ukończone, ale nie opublikowałem go, ponieważ nie testowałem). :)
sorich87,
@ sorich87 - Znasz stare powiedzenie: Drzemka, przegrywasz !” Poważnie, TYLKO żartowałem. Jest naprawdę tylko jeden rozsądny sposób, aby działał, więc nic dziwnego, że twój kod byłby taki sam!
MikeSchinkel,
Mike, nadal zadziwiasz. Bardzo dziękuję za poświęcenie czasu na to.
Scott B,
@ sorich87 - Dziękujemy za pracę nad tym. Naprawdę doceniam wysiłek.
Scott B,
1
@ Scott B : Nie ma problemu, cieszę się, że mogłem pomóc. Szukam rozsądnie ogólnych pytań, które potencjalnie mogłyby pomóc wielu osobom, i staram się na nie odpowiedzieć nie tylko osobie zadającej pytanie, ale także tym, którzy mogą przyjść później.
MikeSchinkel,
0

Wordpress pozwala dodawać Meta do kategorii za pomocą wtyczki:

Aby to zrobić, musisz dodać jedno z różnych rozszerzeń, które dodają meta do kategorii (naśladując, które strony wychodzą z pudełka), Simple Term Meta robi to dobrze.

Uwaga: WordPress 3.x jest potrzebny do rozszerzenia kategorii.

Następnie możesz użyć:

  • add_term_meta
  • update_term_meta
  • get_term_meta

Użyj Functions.php, aby dodać metody do robienia tego, co chcesz, np

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('Image URL') ?></label>
        <input name="image-url" id="image-url" type="text" value="" size="40" aria-required="true" />
        <p class="description"><?php _e('This image will be the thumbnail shown on the category page.'); ?></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']);                  
}

Wywoływanie nowych pól w motywach jest łatwe:

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

Więcej szczegółów i przykładów: http://www.wphub.com/adding-metadata-taxonomy-terms/

Sójka
źródło