Вывод категорий с миниатюрами и описанием на главной странице

26 дек. 2010 г., 19:01:24
Просмотры: 13.4K
Голосов: 3

Мне действительно нужно комплексное решение, поэтому я предлагаю почти четверть своей репутации в качестве награды :)

Я хотел бы иметь плагин, который создает кастомный список категорий на главной странице. Для этого мне нужно расширить функциональность экрана "Редактирование категории" следующим образом...

  • Добавляет обработчик "Загрузить/Удалить изображение" на экран редактирования категории (это позволит пользователям загружать изображение, которое будет представлять категорию. Идеально, если плагин автоматически изменяет размер изображения до 125 пикселей в ширину при загрузке).
  • Добавляет поле ввода "Заголовок категории" на экран редактирования категории (в дополнение к стандартному полю "Название").
  • Добавляет чекбокс "Показывать в списке на главной" для выборочного отображения категорий в списке на главной странице.
  • При просмотре главной страницы плагин добавляет к the_content кастомный список категорий, включая миниатюру и заголовок каждой категории.

Результирующая разметка должна быть неупорядоченным списком без вложений, например:

<ul class="custom-categories">
    <li>
        <span><a href="link-to-category-1"><img src="the-category-1-image" /></a></span>
        <a href="link-to-category-1">Название категории 1</a> Текст описания категории
    </li>
    <li>
        <span><a href="link-to-category-2"><img src="the-category-2-image" /></a></span>
        <a href="link-to-category-2">Название категории 2</a> Текст описания категории
    </li>
    и т.д...
</ul>

Вот заготовка кода, с которой я начал...

add_filter( 'the_content', 'cb_category_listing' );

function cb_category_listing( $content )
{
    if ( is_home() ) {
        $cat_args['title_li'] = '';
        $cat_args['exclude_tree'] = 1;
        $cat_args['exclude'] = 1;
        $myContent = wp_list_categories(apply_filters('widget_categories_args', $cat_args)); 
        $content .= $myContent;
    }
    return $content;
}
0
Все ответы на вопрос 3
4

Примечание: Это для старых версий WP < 3.9 до внедрения новой загрузки медиафайлов

Вот как добавить поля и сохранить значения на экране редактирования категорий, а также метод добавления поля загрузки изображения.

Добавление полей на экран редактирования категории

Для начала нам нужно отобразить некоторый код на экране редактирования категории.

add_action( 'edit_category_form_fields', 'my_category_custom_fields' );
add_action( 'edit_category', 'save_my_category_custom_fields' );

function my_category_custom_fields( $tag ) {
    // здесь будет ваш HTML для пользовательских полей
    // переменная $tag - это объект термина таксономии со свойствами $tag->name, $tag->term_id и т.д.

    // нам нужно знать значения существующих записей, если они есть
    $category_meta = get_option( 'category_meta' );
    ?>
    <tr class="form-field">
        <th scope="row" valign="top"><label for="category-title"><?php _e("Заголовок"); ?></label></th>
        <td>
            <input id="category-title" name="category_meta[<?php echo $tag->term_id ?>][title]" value="<?php if ( isset( $category_meta[ $tag->term_id ] ) ) esc_attr_e( $category_meta[ $tag->term_id ]['title'] ); ?>" />
            <span class="description"><?php _e('Введите альтернативный заголовок для этой категории.'); ?></span>
        </td>
    </tr>
    <!-- повторяем для других необходимых полей -->
    <?php
}

Самый простой способ хранить наши пользовательские значения - в таблице опций (на самом деле должна быть таблица таксономия-мета, но неважно). Таким образом, нам нужно выполнить только один запрос, чтобы получить метаданные для всех наших категорий. Если у кого-то есть лучшая идея для хранения, высказывайтесь!

function save_my_category_custom_fields() {
    if ( isset( $_POST['category_meta'] ) && !update_option('category_meta', $_POST['category_meta']) )
        add_option('category_meta', $_POST['category_meta']);
}

Для чекбокса вы просто храните true или false, поэтому используйте category_extras[$tag->term_id][show_on_home] для атрибута name и используйте значение, хранящееся в $category_meta, чтобы определить, отмечен он или нет.

Вы можете добавить дополнительную обработку или санитацию в функцию сохранения - мой пример просто быстрый и грязный.

Поле изображения

Это довольно много кода и довольно сложно, поэтому я не буду объяснять все здесь, но комментарии описывают назначение каждой функции. Мы можем обсудить в комментариях, если хотите.

Следующие функции добавляют ссылку на экран редактирования категории, которая вызывает всплывающее окно медиабиблиотеки WordPress/загрузки изображений. Затем вы можете загрузить картинку и нажать, чтобы использовать ее. Затем у вас будет доступен ID изображения и URL миниатюры вместе с другими метаданными выше.

// добавляем нужный размер изображения
add_image_size( 'category_thumb', 125, 125, true );

// настраиваем наше поле изображения и методы обработки
function setup_category_image_handling() {
    // добавляем поле изображения к остальным
    add_action( 'edit_category_form_fields', 'category_image' );

    global $pagenow;
    if ( is_admin() ) {
    add_action( 'admin_init', 'fix_async_upload_image' );
    if ( 'edit-tags.php' == $pagenow ) {
        add_thickbox();
        add_action('admin_print_footer_scripts', 'category_image_send_script', 1000);
    } elseif ( 'media-upload.php' == $pagenow || 'async-upload.php' == $pagenow ) {
        add_filter( 'media_send_to_editor', 'category_image_send_to_editor', 1, 8 );
        add_filter( 'gettext', 'category_image_replace_text_in_thickbox', 1, 3 );
    }
    }
}
add_action( 'admin_init', 'setup_category_image_handling' );

// поле изображения на экране редактирования таксономии
function category_image( $tag ) {
    // получаем наши метаданные категории
    $category_meta = get_option('category_meta');
    ?>
           <tr class="form-field hide-if-no-js">
               <th scope="row" valign="top"><label for="taxonomy-image"><?php _e("Изображение"); ?></label></th>
               <td>
                   <div id="taxonomy-image-holder">
               <?php if( !empty($category_meta[$tag->term_id]['image']) ) { ?>
                   <img style="max-width:100%;display:block;" src="<?php echo esc_attr( $category_meta[ $tag->term_id ]['image']['thumb'] ); ?>" alt="Миниатюра категории" title="Миниатюра категории" />
                   <a id="taxonomy-image-select" class="thickbox" href="media-upload.php?is_term=true&amp;type=image&amp;TB_iframe=1"><?php _e('Изменить изображение'); ?></a>
                   <a class="deletion" id="taxonomy-image-remove" href="#remove-image">Удалить изображение</a>
               <?php } else { ?>
                   <a id="taxonomy-image-select" class="thickbox" href="media-upload.php?is_term=true&amp;type=image&amp;TB_iframe=1"><?php _e('Выбрать изображение'); ?></a>
               <?php } ?>
                   </div>
                   <input type="hidden" name="category_meta[<?php echo $tag->term_id ?>][image][id]" value="<?php if( isset($category_meta[ $tag->term_id ]['image']['id']) ) echo esc_attr($category_meta[ $tag->term_id ]['image']['id']); ?>" class="tax-image-id" />
                   <input type="hidden" name="category_meta[<?php echo $tag->term_id ?>][image][thumb]" value="<?php if( isset($category_meta[ $tag->term_id ]['image']['thumb']) ) echo esc_attr($category_meta[ $tag->term_id ]['image']['thumb']); ?>" class="tax-image-thumb" />
               <span class="description"><?php _e('Изображение категории.'); ?></span></td>
           </tr>
    <?php
}

   // необходимо для загрузки изображений на экранах, не связанных с записями/страницами
   function fix_async_upload_image() {
       if(isset($_REQUEST['attachment_id'])) {
           $GLOBALS['post'] = get_post($_REQUEST['attachment_id']);
       }
   }

   // работаем с экраном редактирования таксономии?
   function is_category_context() {
       if ( isset($_SERVER['HTTP_REFERER']) && strpos($_SERVER['HTTP_REFERER'],'is_term') !== false ) {
           return true;
       } elseif ( isset($_REQUEST['_wp_http_referer']) && strpos($_REQUEST['_wp_http_referer'],'is_term') !== false ) {
           return true;
       } elseif ( isset($_REQUEST['is_term']) && $_REQUEST['is_term'] !== false ) {
           return true;
       }
       return false;
   }

   // заменяем текст "Вставить в запись" на более подходящий
   function category_image_replace_text_in_thickbox($translated_text, $source_text, $domain) {
       if ( is_category_context() ) {
           if ('Insert into Post' == $source_text) {
               return __('Использовать это изображение', MB_DOM );
           }
       }
       return $translated_text;
   }

   // выводим скрипт, который устанавливает переменные в объекте window, чтобы к ним можно было получить доступ в других местах
   function category_image_send_to_editor( $html, $id, $attachment ) {
       // проверка контекста может быть не обязательной и может не работать во всех случаях
       if ( is_category_context() ) {
           $item = get_post($id);
           $src = wp_get_attachment_image_src($id,'thumbnail',true); // 0 = url, 1 = ширина, 2 = высота, 3 = иконка (bool)
           ?>
           <script type="text/javascript">
               // отправляем переменные изображения обратно в opener
               var win = window.dialogArguments || opener || parent || top;
               win.TI.id = <?php echo $id ?>;
               win.TI.thumb = '<?php echo $src[0]; ?>';
           </script>
           <?php
       }
       return $html;
   }

   // выводим javascript, который обрабатывает действия при нажатии пользователем на использование изображения
   function category_image_send_script() { ?>
       <script>
           self.TI = {};
           var tb_position;

           function send_to_editor(h) {
               // игнорируем контент, возвращаемый из загрузчика медиа, и используем переменные, переданные в window
               jQuery('.tax-image-id').val( self.TI.id );
               jQuery('.tax-image-thumb').val( self.TI.thumb );

               // отображаем изображение
               jQuery('#taxonomy-image-holder img, #taxonomy-image-remove').remove();
               jQuery('#taxonomy-image-holder')
                   .prepend('<img style="max-width:100%;display:block;" src="'+ self.TI.thumb +'" alt="Миниатюра категории" title="Миниатюра категории" />')
                   .append('<a class="deletion" id="taxonomy-image-remove" href="#remove-image">Удалить изображение</a>');

               jQuery('#taxonomy-image-select').html('Изменить изображение');

               // закрываем thickbox
               tb_remove();
           }

           (function($){
               $(document).ready(function() {

                   tb_position = function() {
                       var tbWindow = $('#TB_window'), width = $(window).width(), H = $(window).height(), W = ( 720 < width ) ? 720 : width;

                       if ( tbWindow.size() ) {
                           tbWindow.width( W - 50 ).height( H - 45 );
                           $('#TB_iframeContent').width( W - 50 ).height( H - 75 );
                           tbWindow.css({'margin-left': '-' + parseInt((( W - 50 ) / 2),10) + 'px'});
                           if ( typeof document.body.style.maxWidth != 'undefined' )
                               tbWindow.css({'top':'20px','margin-top':'0'});
                       };

                       return $('a.thickbox').each( function() {
                           var href = $(this).attr('href');
                           if ( ! href ) return;
                           href = href.replace(/&width=[0-9]+/g, '');
                           href = href.replace(/&height=[0-9]+/g, '');
                           $(this).attr( 'href', href + '&width=' + ( W - 80 ) + '&height=' + ( H - 85 ) );
                       });
                   };
                   $(window).resize(function(){ tb_position(); });

                   $('#taxonomy-image-select').click(function(event){
                       tb_show("Выбрать изображение:", $(this).attr("href"), false);
                       return false;
                   });
                   $('#taxonomy-image-remove').live('click',function(event){
                       $('#taxonomy-image-select').html('Выбрать изображение');
                       $('#taxonomy-image-holder img').remove();
                       $('input[class^="tax-image"]').val("");
                       $(this).remove();
                       return false;
                   });
               });
           })(jQuery);
       </script>
       <?php
   }

Доступ к информации

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

function my_function(){
    $args=array(
    'orderby' => 'name',
    'order' => 'ASC'
    );
    $categories=get_categories($args);

    // получаем наши метаданные категории и выходим, если их нет
    $category_meta = get_option('category_meta');
    if ( !$category_meta )
        return;

    echo '<ul style="list-style-type:none;margin:0;padding:0">';
    foreach($categories as $category) {
        // пропускаем неотмеченные категории и категории без метаданных
        if ( !isset( $category_meta[ $category->term_id ] ) || ( isset( $category_meta[ $category->term_id ] ) && !$category_meta[ $category->term_id ]['show_on_home'] ) )
            continue;
        echo '<li><a style="display:block;margin-top:20px;" href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "Просмотреть все записи в %s" ), $category->name ) . '" ' . '>' . $category_meta[ $category->term_id ]['title'].'</a>';
        if ( "" != $category_meta[ $category->term_id ]['image']['id'] )
            echo wp_get_attachment_image( $category_meta[ $category->term_id ]['image']['id'], 'category_thumbnail', false, array( 'alt' => $category->name, 'class' => '' ) );
        echo $category->description . '</li>';
        } 
    echo '</ul>';
}
12 янв. 2011 г. 19:59:47
Комментарии

Вау, спасибо sanchothefat. Я ценю твои усилия. Я уже собрал большую часть сам, но я приму твой ответ и внедрю его в свой код.

Scott B Scott B
14 янв. 2011 г. 00:38:44

Sanchothefat, ты заслуживаешь вознаграждение, которое я установил за этот вопрос. Ты его получил?

Scott B Scott B
14 янв. 2011 г. 04:22:44

Насколько сложно будет изменить твой код, чтобы сохранять изображения в папку "category-images" внутри uploads? И если папка не существует - создать ее.

Scott B Scott B
14 янв. 2011 г. 04:25:56

Честно говоря, я не уверен. Возможно, существует фильтр для пути к директории загрузки. Но лично я предпочитаю использовать встроенную медиатеку, так как она значительно упрощает процесс загрузки и генерации миниатюр. Посмотрите http://adambrown.info/p/wp_hooks - это отличный ресурс, где описаны все хуки и фильтры в WordPress.

Я не получил награду :( наверное, срок истек.

sanchothefat sanchothefat
14 янв. 2011 г. 12:52:09
2

Простой способ — использовать что-то вроде этого http://wordpress.org/extend/plugins/category-images/. Или вы можете написать собственный хук.

26 дек. 2010 г. 20:16:13
Комментарии

Спасибо, Уик, я протестировал этот плагин, но он не делает ВСЕ, что мне нужно. Например, я не хочу заменять текст ссылки на изображение, мне нужно и изображение, И текст ссылки.

Scott B Scott B
5 янв. 2011 г. 22:59:02

Похоже, что миниатюра отображается только на странице single.php для записи. Мне нужен пользовательский список категорий (что-то вроде индексной страницы) для всех категорий. Я обновил свой вопрос с более конкретными деталями и добавил награду за окончательное решение.

Scott B Scott B
5 янв. 2011 г. 23:53:46
0

Это была моя первая попытка...

add_filter( 'the_content', 'cb_category_listing' );

function cb_category_listing( $content )
{
    if ( is_home() ) {
        $cat_args['title_li'] = '';
        $cat_args['exclude_tree'] = 1;
        $cat_args['exclude'] = 1;
        $myContent = wp_list_categories(apply_filters('widget_categories_args', $cat_args)); 
        $content .= $myContent;
    }
    return $content;
}

Очевидно, что это просто создает список названий категорий со ссылкой на каждую категорию. Это дает мне старт. Однако мне все еще нужно...

  • Способ связать миниатюру категории с каждой категорией и отображать ее в списке категорий в моем коде выше.

  • Способ включить пользовательский заголовок категории, отличный от имени категории, и отображать его в списке категорий (вместо "Название категории").

  • Способ показывать/скрывать каждую категорию из списка. В идеале, с чекбоксом "Показывать в списке на главной странице", который можно редактировать на экране редактирования категории.

Вот мой обновленный код. Продвигаюсь, но еще не разобрался с миниатюрой или добавлением пользовательских полей (миниатюра, пользовательский заголовок, показ/скрытие) в админке редактора категорий...

function _add_my_filter() {
    if ( is_home() OR is_sticky() )
    {
    add_filter( 'the_content', 'my_function' );
    }
}
add_action('template_redirect', '_add_my_filter');

function my_function(){
    $args=array(
    'orderby' => 'name',
    'order' => 'ASC'
    );
    $categories=get_categories($args);
    echo '<ul style="list-style-type:none;margin:0;padding:0">';
    foreach($categories as $category) { 
        echo '<li><a style="display:block;margin-top:20px;" href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "Просмотреть все записи в %s" ), $category->name ) . '" ' . '>' . $category->name.'</a>';
        echo $category->description . '</li>';
        } 
    echo '</ul>';
}
5 янв. 2011 г. 23:07:20