Добавление атрибутов страницы Metabox и шаблонов страниц на страницу редактирования сообщений?


14

( Примечание модераторов: заголовок изначально был «Как добавить селектор« Атрибуты страницы »и / или« Атрибуты страницы> Шаблон »в редактор POSTS»)

В настоящее время WP разрешает присваивать «шаблоны» только страницам (т post_type=='page'. Е. ). Я бы хотел расширить эту функциональность и на посты (т post_type=='post'. Е. )

Как добавить мета-поле «Атрибуты страницы» и, в частности, переключатель шаблонов в редактор сообщений?

Я предполагаю, что это код, который я добавлю в functions.phpмою тему.

ОБНОВЛЕНИЕ: мне удалось добавить выпадающее меню жестко запрограммированных шаблонов в мой редактор сообщений, просто добавив html окна выбора в существующее поле пользовательских мета-параметров. Вот код, который я использую для этого ...

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

А вот функция, которая записывает параметры и поле выбора шаблона ...

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

И, наконец, код для захвата выбранных значений при сохранении ...

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

Теперь я считаю, что осталось только (1) захватить выбранный шаблон и добавить его к мета поста для этого поста и (2) изменить index.php и single.php, чтобы он использовал выбранный шаблон.


@ Скотт Б : Ну, я написал весь свой ответ прежде, чем увидел, что вы тоже над ним работали, и, кажется, вы взяли его в несколько ином направлении, чем ваш первоначальный вопрос, в котором нет подписки и вариантов индекса. Надеюсь, то, что я сделал, все еще имеет ценность для тебя. Если нет, возможно, это поможет другим.
MikeSchinkel

Да, вы ответили на вопрос. Я сделал несколько иной шаг, когда понял, что мне не нужно анализировать каталог и могу жестко закодировать значения для моих конкретных шаблонов. Мне все еще, вероятно, придется позаимствовать часть вашего кода для того, чтобы заставить WP использовать правильный назначенный шаблон для поста.
Скотт Б

Ответы:


12

Ненавижу быть носителем плохих новостей, но WordPress жестко кодирует функциональность шаблона страницы в тип публикации "страница" , по крайней мере, в версии 3.0 (это может измениться в будущих версиях, но я не знаю какой-либо конкретной инициативы по ее изменению). пока что. Так что это один из немногих случаев, когда я пытаюсь понять, как обойти что-то без взлома ядра.)

Решение, которое я придумала, заключается в том, чтобы в основном скопировать соответствующий код из ядра WordPress и модифицировать его для наших нужд. Вот шаги (номера строк взяты из версии 3.0.1):

  1. Скопируйте page_attributes_meta_box()функцию из строки 535 /wp-admin/includes/meta-boxes.phpи измените ее в соответствии с требованиями.

  2. Кодекс add_meta_boxesхук, чтобы добавить метабокс, созданный в # 1.

  3. Скопируйте get_page_templates()функцию из строки 166 /wp-admin/includes/theme.php и измените ее в соответствии с требованиями.

  4. Скопируйте page_template_dropdown()функцию из строки 2550 /wp-admin/includes/template.phpи измените ее в соответствии с требованиями.

  5. Добавьте шаблон сообщения в вашу тему.

  6. Код save_postхук, чтобы включить сохранение имени файла шаблона поста при сохранении.

  7. Код single_templateхук, чтобы разрешить загрузку шаблона сообщения для связанных сообщений.

Теперь с этим!


1. Скопируйте page_attributes_meta_box()функцию

В качестве первого шага вам нужно скопировать page_attributes_meta_box()функцию из строки 535, /wp-admin/includes/meta-boxes.phpи я решил переименовать ее post_template_meta_box(). Поскольку вы запрашивали только шаблоны страниц, я пропустил код для указания родительского поста и для определения порядка, который делает код намного проще. Я также решил использовать postmeta для этого, а не пытаться повторно использовать page_templateсвойство объекта, чтобы избежать и потенциальных несовместимостей, вызванных непреднамеренной связью. Итак, вот код:

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. Код add_meta_boxesкрючок

Следующим шагом является добавление метабокса с помощью add_meta_boxesхука:

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. Скопируйте get_page_templates()функцию

Я предположил, что будет иметь смысл только различать шаблоны страниц и шаблоны сообщений, таким образом, необходимость в get_post_templates()функции, основанной на get_page_templates()строке 166 /wp-admin/includes/theme.php. Но вместо использования Template Name:маркера, какие шаблоны страниц используют эту функцию, Post Template:вместо этого используется маркер, который вы можете увидеть ниже.

Я также отфильтровываюсь осмотр functions.php (не знаю , как get_page_templates()никогда правильно работали без этого, но что угодно!) И единственное , что осталось сделать ссылки изменения на слово pageк postдля обслуживания читаемости вниз по дороге:

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. Скопируйте page_template_dropdown()функцию

Аналогично скопируйте page_template_dropdown()строку 2550 /wp-admin/includes/template.phpдля создания post_template_dropdown()и просто измените ее на вызов 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. Добавить шаблон сообщения

Следующим шагом является добавление шаблона сообщения для тестирования. Используя Post Template:маркер, упомянутый в шаге 3, скопируйте single.phpиз своей темы single-test.phpи добавьте следующий заголовок комментария ( обязательно измените что-то, single-test.phpчтобы вы могли сказать, что он загружается вместо single.php) :

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

После того, как вы сделали шаги с 1 по 5, вы можете увидеть, что ваше метабокс «Шаблоны сообщений» появится на странице вашего редактора сообщений:

Как выглядел Metabox пост-шаблонов при добавлении в WordPress 3.0
(источник: mikeschinkel.com )

6. Код save_postкрючка

Теперь, когда у вас есть редактор, вы должны сохранить имя файла шаблона страницы в postmeta, когда пользователь нажимает «Опубликовать». Вот код для этого:

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. Код single_templateкрючок

И, наконец, вам нужно заставить WordPress использовать ваши новые шаблоны сообщений. Вы делаете это, перехватывая single_templateи возвращая желаемое имя шаблона для тех сообщений, которым назначен один:

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

И это все!

Примечание , что я не принимать во внимание ТАМОЖЕННЫЙ ПОСТ типы , только post_type=='post'. По моему мнению, обращение к пользовательским типам постов потребовало бы разграничения между разными типами постов, и, хотя это было не слишком сложно, я не пытался сделать это здесь.


Большой! Я пошел спать с почти полным кодом в моем редакторе с тем же подходом копирования функций WordPress по умолчанию (это было завершено, но я не буду публиковать его, так как я не тестировал). :)
sorich87 11.10.10

@ sorich87 - Вы знаете старую поговорку: «Вы дремлет, вы потеряете! Если серьезно, ТОЛЬКО шучу. На самом деле есть только один разумный способ заставить его работать, поэтому не удивительно, что ваш код будет таким же!
MikeSchinkel

Майк, ты продолжаешь удивлять. Большое спасибо, что нашли время, чтобы выработать это.
Скотт Б

@ sorich87 - Спасибо за работу над этим. Я действительно ценю усилия.
Скотт Б

1
@ Скотт Б : Нет проблем, рад, что смог помочь. Я ищу достаточно общие вопросы, которые потенциально могут помочь многим людям, и пытаюсь ответить на них не только для человека, задающего вопрос, но и для тех, кто может прийти после.
MikeSchinkel

0

Wordpress позволяет добавлять Meta к категориям с помощью плагина:

Для этого вам нужно добавить одно из различных расширений, которое добавляет мета к категориям (имитируя, какие страницы выходят из коробки), Simple Term Meta прекрасно справляется со своей задачей.

NB WordPress 3.x необходим для расширения категорий.

После этого вы можете использовать:

  • add_term_meta
  • update_term_meta
  • get_term_meta

Используйте Functions.php для добавления методов, чтобы делать то, что вы хотите, например

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']);                  
}

Называть новые поля в темах легко:

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

Более подробная информация и примеры: http://www.wphub.com/adding-metadata-taxonomy-terms/

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.