Предыдущий вариант встраивания картинки в редактор терминов меня не устраивает в части работы диалога и того, что в базу сохраняется URL, а не ID картинки (thumbnail).
Что не так с диалогом?
Использован диалог выбора URL картинки встроенного в WP WYSIWYG редактора, который не совсем удачен в данном случае, т.к. интерфейс может сбивать с толку пользователя. Для собственных нужд он вполне подходит, но встраивать его в работе «на клиента» не пойдет.
В WordPress есть и другой диалог, который позволяет выбрать картинку и при этом возвращает её идентификатор, а не URL. Этот диалог мы и будем использовать в новой версии демо-плагина, который писали в прошлой статье.
Структура плагина
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
<?php /* Plugin Name: TaxonomyImage Description: Example of taxonomy field Requires at least: 4.4 Version: 2.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html */ if (!class_exists('TaxonomyImage')) { class TaxonomyImage { //в конструкторе объявим все необходимые зацепки public function __construct() { add_action( 'init', array($this, 'init'), 0); if (function_exists('add_action')) { if (is_admin()) { add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts')); add_action('wp_ajax_set_term_thumbnail', array($this, '_ajax_action')); //встраивание поля с картинкой add_action('edit_term', array($this, 'tax_pic_save')); add_action('create_term', array($this, 'tax_pic_save')); //сохранение данных термина add_action('mytax_add_form_fields', array($this, 'tax_pic_edit')); add_action('mytax_edit_form_fields', array($this, 'tax_pic_edit')); } } } public function tax_pic_edit($taxonomy) { //выводим поле картинки в редакторе термина ... } public function tax_pic_save($term_id) { //сохранение данных поля в базе ... } public function enqueue_scripts($hook) { //подключим необходимые файлы if ( $hook == 'edit-tags.php' || $hook == 'term.php' ) { //эти файлы предоставляет WP wp_enqueue_media(); wp_enqueue_style( 'editor-buttons' ); //а этот скрипт напишем сами //разместим в той же папке, что и плагин wp_enqueue_script( 'term-image', plugin_dir_url(__FILE__) . 'term_image.admin.js', array( 'jquery' ) ); } } function _ajax_action() { //код выбранной картинки будет поступать через ajax //здесь мы его перехватим, чтобы потом сохранять в базу ... } public function init() { //пример регистрации таксономии register_taxonomy( 'mytax', array('post'), array( 'hierarchical' => true, 'labels' => array('name' => 'Пример словаря'), 'query_var' => true, 'rewrite' => true, 'show_tagcloud' => true, 'show_in_quick_edit' => true, 'show_admin_column' => true, ) ); } }} //создадим глобальный объект, чтобы объявить зацепки плагина global $TaxonomyImage_obj; $TaxonomyImage_obj = new TaxonomyImage(); |
Вывод поля картинки в редакторе
Вывод поля имеет декоративную цель, формирует нужный шаблон, с которым мы будем потом работать из javascript. Каких то реальных полей (input, file) здесь не выводится, т.к. ID выбранной картинки мы передадим по ajax.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public function tax_pic_edit($taxonomy) { if (empty($taxonomy)) { //этот шаблон для формы ввода нового термина $content = '<div class="form-field" id="term_image"> <label>Изображение</label> <p class="hide-if-no-js"> <a href="#" id="set-term-thumbnail">Кликните, чтобы выбрать картинку</a> </p> <div class="image-wrapper"></div> </div>'; } else { //шаблон для редактора термина $content = '<tr class="form-field" id="term_image"> <th scope="row" valign="top"><label>Изображение</label></th> <td> <p class="hide-if-no-js"> <a href="#" id="set-term-thumbnail">Кликните, чтобы выбрать картинку</a> </p> <br /> <div class="image-wrapper">' . $this->img_field( get_term_meta($taxonomy->term_id, 'pic', true) ) . '</div></td></tr>'; } echo $content; } |
В функции вызывается метод img_field(thumb_id). Это вспомогательная функция выводит миниатюру указанной картинки. Мы будем ей пользоваться ещё в одном месте, из-за этого пришлось выделить код в отдельную функцию.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
private function img_field($thumb_id) { //сформируем миниатюру с размерами 250x250 $content = ''; if ( $thumb_id && get_post( $thumb_id ) ) { $width = 250; if ( !isset( $_wp_additional_image_sizes['post-thumbnail'] ) ) { $html = wp_get_attachment_image( $thumb_id, array( $width, $width ) ); } else { $html = wp_get_attachment_image( $thumb_id, 'post-thumbnail' ); } //добавим ссылку на удаление связи с картинкой if ( !empty( $html ) ) { $content = $html . '<p class="hide-if-no-js"> <a href="#" id="remove-term-thumbnail">Убрать картинку</a></p>'; } } return $content; } |
Обвязка скриптом
Сейчас, когда уже определена структура HTML шаблона, можно приступить к java-скрипту.
Скрипт выполняет две задачи:
- привязывает события к ссылкам «выберите картинку» и «удалите картинку»;
- передаёт ID выбранного изображения по ajax нашей программе.
Попутно мы обновляем шаблон, показывая картинку или убирая её, в зависимости от действий пользователя.
Итак, файл term_image.admin.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
(function ($) { $(document ).ready(function() { var AltImageUpdate = function ( thumb_id ) { //отправим ID картинки wp.media.post( 'set_term_thumbnail', { thumbnail_id: thumb_id, }).done( function ( html ) { //обновим контейнер с картинкой $('#term_image').find('.image-wrapper').html(html); }).fail( function () { console.log('error'); }); }; //подключаем события на ссылки $('#term_image' ) //... выберите изображение .on('click', '#set-term-thumbnail', function(e) { e.preventDefault(); e.stopPropagation(); //настраиваем и открываем диалог выбора изображения var uploader = wp.media({ title: 'Выберите картинку', button: { text: 'Выбрать' }, multiple: false }); uploader.on('select', function() { var attachment = uploader.state().get( 'selection' ).first().toJSON(); AltImageUpdate(attachment.id ); }); uploader.open(); }) //... удалите изображение .on('click', '#remove-term-thumbnail', function(e) { e.preventDefault(); e.stopPropagation(); AltImageUpdate( -1 ); }); }); })(jQuery); |
Обработка передачи и сохранения данных
Скрипт отправляет данные по ajax, которые мы принимаем зацепившись хуком в нашей функциий _ajax_action().
Выполняются две задачи:
- запомнить в сессии новое значение выбранной картинки (такая реализация не подойдет, если вы открыли и редактируете сразу два термина в рамках одной сессии!);
- сформировать шаблон превью картинки для обновления клиентской части.
1 2 3 4 5 6 7 8 |
function _ajax_action() { session_start(); $thumbnail_id = intval( $_POST['thumbnail_id'] ); $_SESSION['_term_new_picture'] = $thumbnail_id; wp_send_json_success( $this->img_field( $thumbnail_id )); wp_die(0); } |
Когда программа дойдет до сохранения формы, мы используем значение ID картинки из сессии.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public function tax_pic_save($term_id) { session_start(); if (!empty($_SESSION['_term_new_picture'])) { $thumb_id = intval($_SESSION['_term_new_picture']); if ( $thumb_id == -1 ) { delete_term_meta( $term_id, 'pic' ); } else { update_term_meta( $term_id, 'pic', $thumb_id); } unset($_SESSION['_term_new_picture']); } } |
* * *
Есть и другие готовые решения. См. обзор плагинов, добавляющих картинку в таксономию.