Добавление загрузчика (Media uploader) к произвольному полю wordpress

Иногда является хорошей практикой вставить в произвольное поле (Custom Field’s) wordpress какой ссылку, id либо какой  либо атрибут файла из медиабиблиотеки, но ещё лучшей практикой будет создать метабокс (Meta Box) который имел бы возможность загрузить файл , сразу же добавить его в библиотеку и уже после сгенерировать произвольное поле с атрибутами файла. Очевидно что решить задачу должно помочь богатое или не очень (доподлинно неизвестно) Media uploader API, к слову об этом очень мало чего известно, поэтому пришлось смотреть исходники. Создадим плагин пусть он будет добавлять метабокс в который загружаются документы Exel.

<?php
/*
Plugin Name: Field uploder js
Plugin URI: https://alkoweb.ru
Author: Petrozavodsky
Author URI: https://alkoweb.ru
*/
if (is_admin()) { //подключаем в админке js файл зависящий от jquery (jquery в админке подключен по умолчанию).
    function ll_uploader_xls_scripts()
    {
      wp_enqueue_style('thickbox');
       wp_enqueue_script('thickbox');
      wp_enqueue_script('xls-uploader', plugin_dir_url(__FILE__) . 'js/uploader.js', array('jquery'), '0.1', false);
    }
 
    add_action('admin_head', 'll_uploader_xls_scripts');
}
 
 
add_action('add_meta_boxes', 'uploder_extra_fields', 1);
 
function uploder_extra_fields() {
    add_meta_box( 'uploader_js', 'Дополнительные поля', 'extra_fields_box_func', 'post', 'normal', 'high'  );
}
 
function extra_fields_box_func()
{
global $post;
//создаем метабокс
    ?>
    <input id="xls-uploader-input" type="text" name="extra[file_id]"  value="<?php echo get_post_meta($post->ID, 'file_id', 1); ?>" style="width:50%"/>
 
    <p id="xls-uploader-name">Файл не выбран</p>
    <hr/>
    <button id="xls-uploader-submit" class="button button-primary button-large">Выбрать файл</button>
    <input type="hidden" name="extra_fields_nonce" value="<?php echo wp_create_nonce(__FILE__); ?>"/>
<?php
}
 
add_action('save_post', 'uploader_js_filds_update', 0);
 
function uploader_js_filds_update($post_id)
{
    if (!wp_verify_nonce($_POST['extra_fields_nonce'], __FILE__)) return false; // проверка
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return false; // если это автосохранение
    if (!current_user_can('edit_post', $post_id)) return false; // если юзер не имеет право редактировать запись
    if (!isset($_POST['extra'])) return false;
    // Все ОК! Теперь, нужно сохранить/удалить данные
    $_POST['extra'] = array_map('trim', $_POST['extra']);
    foreach ($_POST['extra'] as $key => $value) {
        if (empty($value)) {
            delete_post_meta($post_id, $key); // удаляем поле если значение пустое
        }
        update_post_meta($post_id, $key, $value); // add_post_meta() работает автоматически
    }
    return $post_id;
}
 

//Цепляемся к "виртуальному" так сказать экшену свою функцию
add_action('wp_ajax_xls_autocomplet', 'xls_autocomplet');
add_action('wp_ajax_nopriv_xls_autocomplet', 'xls_autocomplet');
//Собственно функция
function xls_autocomplet()
{
    url_to_postid($_POST['url_file']);
}

//Цепляемся к "виртуальному" так сказать экшену свою функцию
add_action('wp_ajax_xls_autocomplet', 'xls_autocomplet');
add_action('wp_ajax_nopriv_xls_autocomplet', 'xls_autocomplet');
//Собственно функция
function xsl_autocomplet()
{
    url_to_postid($_POST['url_file']);
}

Теперь javascript:

var $ = jQuery.noConflict();
$(document).ready(function () {
/* Обработка события .click() кнопки */
    $("#xls-uploader-submit").click(function () {

        tb_show("Загрузить файл.", "media-upload.php?type=file&TB_iframe=true");
        return false;
    });

    /* Обрабатываем результаты */
    window.send_to_editor = function (html) {
        $("#xls-uploader-input").val($(html).attr('href'));
        tb_remove();
    };

    $('#xls-uploader-process').click(function (e) {
        e.preventDefault();
        var data = 'url_file=' + $("#xls-uploader-input").val();
        $.ajax({
            type: 'post',
            url: '/wp-admin/admin-ajax.php?action=xml_autocomplet',
            data: data,
            success: function (result) {
                console.log('готово!')
            }
        });
    });
});

Здесь стоит обратить внимание  на строку media-upload.php?type=file&TB_iframe=true это строка GET запроса к Media Uploader с параметрами . Например если открыть http://you-dev-site.com/wp-admin/media-upload.php?type=file&TB_iframe=true то можно увидеть окно загрузчика которое формируется при помощи GET параметров. tupe —  строка   принимающая значения image,audio,video,file, и т.д.  По умолчанию file. На что это влияет. TB_iframe — каких то конкретных комментариев в коде не нашел, но если поэкспериментировать то можно заметить что без этого параметра открывается какой то старый , дряхлый TinyMCE загрузчик и верстка едет так что смело ставим true. Есть ещё целая туча параметров , есть подозрение что некоторые из них уже Deprecated, все не проверял ( пока не было повода). Итог — имеем плагин который может загружать файл и сохранять его id в произвольное поле. Что это дает — ну много чего так:

<?php
 var_dump( wp_get_attachment_metadata(get_post_meta($post->ID, 'file_id', 1)) );
?>

по id можно вообще всю информацию о файле получить. Применение зависит от только от вашей фантазии от подгрузки индивидуальных js, css файлов, вывода каких либо дополнительных превью, до создания каталога загрузок.

  1. Доброе утро.
    Подскажите пожалуйста, мне нужно несколько независимых друг от друга загрузчиков, и в разных блоках. Как это сделать?

  2. да можно сделать любое количество, хотя поле одно )) например для двух полей Нужно будет сделать разными такие вещи как идентификатор метабокса uploader_js , id кнопки самбмита #xls-uploader-submit ключ мета поля экшен аякса и прочее))
    Можно как то это автоматически в цикле добавлять или как угодно иначе, но в для примера такое писать было бы сложно для понимания, я для своих нужд делал нечто подобное, но оно уже затерялось где-то не могу показать.
    Тот код что в посте только для примера в идеале каждый под себя может переписать.

    • Добрый день, Владимир.
      Благодарю за ответ.
      Я вообще не знаток JS, так, где что нашёл, переделал под себя и всё, но знать его не знаю.
      Когда подгружается фрейм, по нажатию на кнопку «вставить в запись», попробовал вывести alert-ом, всегда только в последнее поле, у меня это 4, где бы ни кликнул.
      Проверял без второго метабокса, два загрузчика РЯДОМ работали нормально, относительно, ссылки вставлялись туда, куда надо, хотя уверен ошибки есть.
      Неделю бьюсь, решения не нашёл.
      Мне эта дурость нужна для заказчика… но видимо придётся отказаться от этой идеи, моего терпения явно не хватит больше на поиски, пусть копирует и вставляет руками, разберётся, не обезьяна.

    • Подтверждаю пословицу «всё гениальное — просто» =))))))
      Достаточно было сделать так:
      В функции each()
      получить индекс текущего блока
      var veli = $(«.des_up»).index(this);
      далее, по клику, сохранить текущее значение в глобальную переменную
      window.velIndex = $(«#xls-uploader-submit-«+i).index(this);
      Так как она глобальная, она не принимает индекс элемента, по которому кликнули, но имеет НОЛЬ
      Ну и — velIndex += veli;
      приплюсовал к нулю значение из первой переменной, вышло то, что нужно:
      window.send_to_editor = function (html) {
      $(«#xls-uploader-input-«+velIndex).val($(html).attr(‘href’));
      tb_remove();
      };
      Выводит ссылку в INPUT с «кликнутым» АЙ ДИ.
      И у меня ещё изображения выводятся )))
      Хех, благодарю, Владимир ))
      То, что вы просто ответили подтолкнуло на поиски дальше.
      Не тот вопрос я задавал выходит, всего то нужно было передать ЧИСЛО элемента, на который нажали )
      Не знаю насколько правильно или не правильно написано, но это реальное решение и всего в пару строк.

  3. Добрый день.

    Интересное решение, но я бы на вашем месте подключение скриптов реализовал через хук admin_enqueue_scripts https://codex.wordpress.org/Plugin_API/Action_Reference/admin_enqueue_scripts. Ваше решение тоже будет работать, но «не православно» получается)

    К тому же в кодексе есть вариант решения поставленной задачи, предложенный разработчиками https://codex.wordpress.org/Javascript_Reference/wp.media.

    Но вам все равно + за глубокое изучение предметной области =)

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

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

Ваш e-mail не будет опубликован. Обязательные поля помечены *