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

| Скачать исходники |

Что конкретно мы сделаем

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

1. Создание плагина

В этой части ничего особо разбирать не будем. Здесь достаточно просто создать новую папку в папке с плагинами wp-content/plugins/media-fields и добавить в нее файл под названием plugin.php. Еще надо добавить файл custom_media_fields.php, в котором и будут все наши настройки. Вот как изначально должен выглядеть ваш файл plugin.php:

/*
Plugin Name: Wptuts+ Custom Media Fields
Plugin URI:
Description: Create attachments custom fields
Version: 0.1
Author: Guillaume Voisin
Author URI: http://wp.tutsplus.com/author/guillaumevoisin
License: GPL2
*/
 
require_once( plugin_dir_path( __FILE__ ) . '/custom_media_fields.php' );
 
Class Wptuts_Custom_Media_Fields {
 
    private $media_fields = array();
 
    function __construct( $fields ) {
 
    }
 
    public function applyFilter( $form_fields, $post = null ) {
 
    }
 
    function saveFields( $post, $attachment ) {
 
    }
 
}
 
$cmf = new Wptuts_Custom_Media_Fields( $attchments_options );

Вот это и будет нашей основой для дальнейшей работы. А теперь перейдем к опциям.

2. Определяем параметры

В другом файле пропишем параметры для вложений. В этом пошаговом руководстве рассмотрим опции для вложенных изображений и улучшения работы с ними. К примеру, добавим к нашим фотографиям и картинкам копирайт, описание, водяной знак, рейтинг и другие поля:

$themename = "twentytwelve";
$attchments_options = array(
    'image_copyright' => array(
        'label'       => __( 'Image copyright', $themename ),
        'input'       => 'text',
        'helps'       => __( 'If your image is protected by copyrights', $themename ),
        'application' => 'image',
        'exclusions'  => array( 'audio', 'video' ),
        'required'    => true,
        'error_text'  => __( 'Copyright field required', $themename )
    ),
    'image_author_desc' => array(
        'label'       => __( 'Image author description', $themename ),
        'input'       => 'textarea',
        'application' => 'image',
        'exclusions'   => array( 'audio', 'video' ),
    ),
    'image_watermark' => array(
        'label'       => __( 'Image watermark', $themename ),
        'input'       => 'checkbox',
        'application' => 'image',
        'exclusions'   => array( 'audio', 'video' )
    ),
    'image_stars' => array(
        'label'       => __( 'Image rating', $themename ),
        'input'       => 'radio',
        'options' => array(
            '0' => 0,
            '1' => 1,
            '2' => 2,
            '3' => 3,
            '4' => 4
        ),
        'application' => 'image',
        'exclusions'   => array( 'audio', 'video' )
    ),
    'image_disposition' => array(
        'label'       => __( 'Image disposition', $themename ),
        'input'       => 'select',
        'options' => array(
            'portrait' => __( 'portrtait', $themename ),
            'landscape' => __( 'landscape', $themename )
        ),
        'application' => 'image',
        'exclusions'   => array( 'audio', 'video' )
    )
);

В связанном массиве будут следующие параметры:

  • label — отображает имя поля
  • input — тип вводимых данных
  • helps — подсказка в помощь пользователю при заполнении полей
  • application — применяемый тип MIME для вложения
  • exclusions — что исключить из вложений
  • required — является ли это поле обязательным? (значение по умолчанию — false)
  • error_text — опциональное поле для описания ошибки
  • options — для выбора переключений между radio и select
  • show_in_modal — показывать ли поле в модальном формате или нет (по умолчанию — true)
  • show_in_edit — показывать ли классический формат редактора для полей (по умолчанию — true)
  • extra_rows — дополнительные строки для отображения контента
  • tr — дополнительные строки с тегом "tr"

Выделенные опции — это те, которые надо будет настроить вручную, а остальные уже заполнены по умолчанию в WordPress и будут обрабатываться автоматически. Поскольку дело мы имеем с изображениями, то параметру application надо присвоить значение "image". Так будут обрабатываться все виды изображений, в которых тип данных совпадает с image/jpeg, image/png и аналогичными. Можно исключить gif, заполнив поле исключений.

Разобрались с опциями — самое время переходить к более тонкой настройке кода.

3. Немного кода

У нас 2 настраиваемые функции, которые включены в состав конструктора:

function __construct( $fields ) {
    $this->media_fields = $fields;
 
    add_filter( 'attachment_fields_to_edit', array( $this, 'applyFilter' ), 11, 2 );
    add_filter( 'attachment_fields_to_save', array( $this, 'saveFields' ), 11, 2 );
}

Рассмотрим подробнее.

attachment_fields_to_edit

Здесь есть 2 параметра:

  • $form_fields — массив полей в форме с редактированием вложений
  • $post — объект самого вложения

Для объединения наших собственных полей будем использовать $form_fields для проверки каждого из них на соблюдение параметров и требований ко вложениям.

public function applyFilter( $form_fields, $post = null ) {
    // If our fields array is not empty
    if ( ! empty( $this->media_fields ) ) {
        // We browse our set of options
        foreach ( $this->media_fields as $field => $values ) {
            // If the field matches the current attachment mime type
            // and is not one of the exclusions
            if ( preg_match( "/" . $values['application'] . "/", $post->post_mime_type) && ! in_array( $post->post_mime_type, $values['exclusions'] ) ) {
                // We get the already saved field meta value
                $meta = get_post_meta( $post->ID, '_' . $field, true );
 
                // Define the input type to 'text' by default
                $values['input'] = 'text';
 
                // And set it to the field before building it
                $values['value'] = $meta;
 
                // We add our field into the $form_fields array
                $form_fields[$field] = $values;
            }
        }
    }
 
    // We return the completed $form_fields array
    return $form_fields;
}

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

Приступим к редактированию. Начнем с замены $values['input'] = 'text'; следующим кодом:

switch ( $values['input'] ) {
    default:
    case 'text':
        $values['input'] = 'text';
        break;
 
    case 'textarea':
        $values['input'] = 'textarea';
        break;
 
    case 'select':
 
        // Select type doesn't exist, so we will create the html manually
        // For this, we have to set the input type to 'html'
        $values['input'] = 'html';
 
        // Create the select element with the right name (matches the one that wordpress creates for custom fields)
        $html = '<select name="attachments[' . $post->ID . '][' . $field . ']">';
 
        // If options array is passed
        if ( isset( $values['options'] ) ) {
            // Browse and add the options
            foreach ( $values['options'] as $k => $v ) {
                // Set the option selected or not
                if ( $meta == $k )
                    $selected = ' selected="selected"';
                else
                    $selected = '';
 
                $html .= '<option' . $selected . ' value="' . $k . '">' . $v . '</option>';
            }
        }
 
        $html .= '</select>';
 
        // Set the html content
        $values['html'] = $html;
 
        break;
 
    case 'checkbox':
 
        // Checkbox type doesn't exist either
        $values['input'] = 'html';
 
        // Set the checkbox checked or not
        if ( $meta == 'on' )
            $checked = ' checked="checked"';
        else
            $checked = '';
 
        $html = '<input' . $checked . ' type="checkbox" name="attachments[' . $post->ID . '][' . $field . ']" id="attachments-' . $post->ID . '-' . $field . '" />';
 
        $values['html'] = $html;
 
        break;
 
    case 'radio':
 
        // radio type doesn't exist either
        $values['input'] = 'html';
 
        $html = '';
 
        if ( ! empty( $values['options'] ) ) {
            $i = 0;
 
            foreach ( $values['options'] as $k => $v ) {
                if ( $meta == $k )
                    $checked = ' checked="checked"';
                else
                    $checked = '';
 
                $html .= '<input' . $checked . ' value="' . $k . '" type="radio" name="attachments[' . $post->ID . '][' . $field . ']" id="' . sanitize_key( $field . '_' . $post->ID . '_' . $i ) . '" /> <label for="' . sanitize_key( $field . '_' . $post->ID . '_' . $i ) . '">' . $v . '</label><br />';
                $i++;
            }
        }
 
        $values['html'] = $html;
 
        break;
}

Теперь можно создавать и более общие элементы HTML. Проверим, как выглядит наша форма редактирования вложений. Должно получиться что-то наподобие:

Настраиваемые поля, в зависимости от того, выбраны ли модальные опции, также будут отображаться в форме при редактировании постов.

Теперь наши поля отображаются в форме редактирования для вложений, и мы можем их сохранить в БД. Для этой цели нам и нужна вторая функция:

attachment_fields_to_save

Она включает 2 параметра:

  • $post — массив для идентификации вложения
  • $attachment — все поля, связанные со вложением в данном посте

Теперь заполним функцию saveFields из предыдущей секции.

function saveFields( $post, $attachment ) {
    // If our fields array is not empty
    if ( ! empty( $this->media_fields ) ) {
        // Browser those fields
        foreach ( $this->media_fields as $field => $values ) {
            // If this field has been submitted (is present in the $attachment variable)
            if ( isset( $attachment[$field] ) ) {
                // If submitted field is empty
                // We add errors to the post object with the "error_text" parameter we set in the options
                if ( strlen( trim( $attachment[$field] ) ) == 0 )
                    $post['errors'][$field]['errors'][] = __( $values['error_text'] );
                // Otherwise we update the custom field
                else
                    update_post_meta( $post['ID'], '_' . $field, $attachment[$field] );
            }
            // Otherwise, we delete it if it already existed
            else {
                delete_post_meta( $post['ID'], $field );
            }
        }
    }
 
    return $post;
}

Ну вот, мы сохранили настраиваемые поля в БД и они доступны для front-end.

Будьте внимательны при экспериментах с полями и параметром post. В первом случае нам нужен object, а во втором — array.

Подсказка: использование update_post_meta создаст значение meta, если оно еще не создано.

Подсказка: Надо добавить префикс к настраиваемым полям вида "_", чтобы они не отображались в списке мета-боксов для настраиваемых полей на страницах редактирования постов.

Проверяем и учитываем ошибки

На момент выхода версии 3.5 ошибки не отображались для форм редактирования вложений. Не смотря на заявление, что этот недостаток исправлен, изучение кода показало, что никаких изменений нет (http://core.trac.wordpress.org/ticket/13810). Для процесса сохранения ajax-кода всё еще не было правок в файле ajax-actions.php следующего вида:

$errors = $post['errors']; // @todo return me and display me!

А вот теперь ошибки должны обрабатываться корректно.

4. Front End

Для использования настраиваемых полей в ваших шаблонах оформления вам надо просто заполнить значение мета-данных так, как вы обычно это делаете для постов. И не забудьте добавить префикс "_". Например, вот так:

echo "<ul>";
echo "  <li><strong>Copyright</strong>: " . get_post_meta( get_the_ID(), '_image_copyright', true ) . "</li>";
echo "  <li><strong>Rating</strong>: " . get_post_meta( get_the_ID(), '_image_stars', true ) . "</li>";
echo "  <li><strong>Author description</strong>: " . get_post_meta( get_the_ID(), '_image_author_desc', true ) . "</li>";
echo "  <li><strong>Image disposition</strong>: " . get_post_meta( get_the_ID(), '_image_disposition', true ) . "</li>";
echo "  <li><strong>Watermark?</strong> " . ( get_post_meta( get_the_ID(), '_image_watermark', true ) == "on" ? "yes" : "no" ) . "</li>";
echo "</ul>";

И еще немного

Есть еще несколько улучшений, которые стоит учесть в зависимости от ваших целей и задач:

  • Настройки можно внести в БД, чтобы сделать редактирование и добавление / удаление более гибким процессом.
  • Можно использовать значения по умолчанию для всех вложений, если не задан пользовательский параметр или не указано конкретное значение.
  • К модальному отображению не помешает добавить немного стилистического оформления для настраиваемых полей.

Если у вас остались вопросы или пожелания, не стесняйтесь, спрашивать можно в комментариях к этому уроку.

Источник: WP.tutsplus.com

Вам понравился материал?

Лучшие темы от Tesla Themes:

Добавить комментарий

Такой e-mail уже зарегистрирован. Воспользуйтесь формой входа или введите другой.

Вы ввели некорректные логин или пароль

Извините, для комментирования необходимо войти.

2 комментария

сначала новые
по рейтингу сначала новые по хронологии

Здравствуйте, подскажите пожалуйста, есть ли способы сделать сортировку медиа (в медиагаллерее) по созданным полям, или по добавленным к ним таксономиям? В сторону каких фильтров копать? Стандартная сортировка по дате загрузки катастрофически неудобна

В данном конкретном плагине такой возможности нет. Какие фильтры тут искать и применять - это скорее к WP разработчикам вопрос. Но идея определенно здравая, такая возможность многим бы пригодилась.