Ви вже напевно стикалися з полями, що настроюються у WordPress. Вони використовуються для додавання додаткових даних на сторінках та постах. Вкладення до постів теж зберігаються як окремі поля, що настроюються. Сьогодні ми з вами розберемося, як додати поля, що настроюються так, щоб медіа-вкладення містили додаткові дані, а не тільки ті, які доступні за замовчуванням.
| Завантажити вихідні |
Що конкретно ми зробимо
Для початку ми напишемо плагін, щоб керувати вкладеннями та прив'язаними до них полями. У плагіні буде набір налаштувань, які треба буде пов'язати воєдино та зберегти у БД сайту. Для цього використовуємо:
- attachment_fields_to_edit - Для управління формою редагування
- attachment_fields_to_save — для збереження полів, що настроюються
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' ) ) );
У зв'язаному масиві будуть наступні параметри:
- етикетка - Відображає ім'я поля
- вхід - Тип даних, що вводяться
- допомагає - підказка на допомогу користувачеві при заповненні полів
- додатку — тип MIME, що застосовується для вкладення
- виключення - що виключити з вкладень
- вимагається - Чи є це поле обов'язковим? (значення за замовчуванням - false)
- error_text - Опціональне поле для опису помилки
- опції — для вибору перемикань між радіо и вибрати
- show_in_modal — показувати поле у модальному форматі чи ні (за замовчуванням — правда)
- show_in_edit - Чи показувати класичний формат редактора для полів (за замовчуванням - правда)
- extra_rows - Додаткові рядки для відображення контенту
- tr - Додаткові рядки з тегомtr"
Виділені опції - це ті, які потрібно буде налаштувати вручну, а інші вже заповнені за замовчуванням WordPress і будуть оброблятися автоматично. Оскільки справу ми маємо із зображеннями, то параметром додатку треба надати значення "зображенняТак будуть оброблятися всі види зображень, в яких тип даних збігається з 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 - Масив полів у формі з редагуванням вкладень
- $ пост - Об'єкт самого вкладення
Для об'єднання наших власних полів будемо використовувати $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 параметри:
- $ пост - Масив для ідентифікації вкладення
- $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; }
Ну ось, ми зберегли поля, що настроюються в БД і вони доступні для інтерфейсних.
Будьте уважні при експериментах з полями та параметром після. У першому випадку нам потрібний об'єкт, а в другому - масив.
Підказка: використання update_post_meta створить значення метаякщо воно ще не створене.
Підказка: Треба додати префікс до полів виду, що настроюються._", щоб вони не відображалися в списку метабоксів для полів на сторінках редагування постів.
Перевіряємо та враховуємо помилки
На момент виходу версії 3.5 помилки не відображалися для форм редагування вкладень. Незважаючи на заяву, що цей недолік виправлений, вивчення коду показало, що жодних змін немає (http://core.trac.wordpress.org/ticket/13810). Для процесу збереження Аякса-Кода все ще не було правок у файлі ajax-actions.php наступного виду:
$errors = $post['errors']; // @todo return me and display me!
А тепер помилки повинні оброблятися коректно.
4. Передня частина
Для використання полів у ваших шаблонах оформлення вам потрібно просто заповнити значення мета-даних так, як ви зазвичай це робите для постів. І не забудьте додати префікс_". Наприклад, ось так:
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>";
І ще трохи
Є ще кілька покращень, які варто врахувати в залежності від ваших цілей та завдань:
- Налаштування можна внести в БД, щоб зробити редагування та додавання/видалення більш гнучким процесом.
- Можна використовувати значення за замовчуванням для всіх вкладень, якщо не встановлено параметр користувача або не вказано конкретне значення.
- До модального відображення не завадить додати трохи стилістичного оформлення для полів, що настроюються.
Якщо у вас залишилися питання чи побажання, не соромтеся, запитувати можна у коментарях до цього уроку.
Коментарі до запису: 2
Доброго дня, підкажіть будь ласка, чи є способи зробити сортування медіа (у медіагалереї) за створеними полями, або за доданими до них таксономіями? У бік яких фільтрів копати? Стандартне сортування за датою завантаження катастрофічно незручне
У цьому конкретному плагіні такої можливості немає. Які фільтри тут шукати та застосовувати - це скоріше до WP розробникам питання. Але ідея безперечно здорова, така можливість багатьом би знадобилася.