Создание загрузчика изображений для виджета
Я нашел этот пост//
Использование загрузки медиафайлов в пользовательском виджете WordPress 3.5
У меня нет опыта в этом, поэтому я просто скопировал предоставленный код в свой файл functions.php. Я загрузил JS и все остальное...
Затем я заменил определенный код, который опубликовал "sven" в своем ответе.
Загрузчик работает отлично, но когда я просматриваю фронтенд, изображение вообще не отображается...
Вот код из моего functions.php//
(он включает зарегистрированные сайдбары и пользовательский виджет и т.д.)
if (function_exists('register_sidebar')) {
register_sidebar(array(
'name' => 'Left Sidebar',
'id' => 'left-sidebar',
'description' => 'Widget Area',
'before_widget' => '<div id="one" class="two"><h1>EOTW//</h1>',
'after_widget' => '</div>',
'before_title' => '<h2>',
'after_title' => '</h2>'
));
}
add_action('widgets_init', 'ctUp_ads_widget');
function ctUp_ads_widget() {
register_widget( 'ctUp_ads' );
}
function ctUp_wdScript(){
wp_enqueue_media();
wp_enqueue_script('adsScript', get_template_directory_uri() . '/js/ads.js');
}
add_action('admin_enqueue_scripts', 'ctUp_wdScript');
class ctUp_ads extends WP_Widget{
function ctUp_ads() {
$widget_ops = array( 'classname' => 'ctUp-ads' );
$control_ops = array( 'width' => 250, 'height' => 350, 'id_base' => 'ctUp-ads-widget' );
$this->WP_Widget( 'ctUp-ads-widget','EOTW', $widget_ops, $control_ops );
}
public function widget($args, $instance){
extract( $args );
?>
<a href="#"><img src="<?php echo esc_url($instance['image_uri']); ?>" /></a>
<?php }
function update($new_instance, $old_instance) {
$instance = $old_instance;
$instance['text'] = strip_tags( $new_instance['text'] );
$instance['image_uri'] = strip_tags( $new_instance['image_uri'] );
return $instance;
}
public function form($instance){ ?>
<p>
<label for="<?php echo $this->get_field_id('text'); ?>"><?php _e('Текст', 'themename'); ?></label><br />
<input type="text" name="<?php echo $this->get_field_name('text'); ?>" id="<?php echo $this->get_field_id('text'); ?>" value="<?php echo $instance['text']; ?>" class="widefat" />
</p>
<p>
<label for="<?php echo $this->get_field_id('image_uri'); ?>">Изображение</label><br />
<img class="custom_media_image" src="<?php if(!empty($instance['image_uri'])){echo $instance['image_uri'];} ?>" style="margin:0;padding:0;max-width:100px;float:left;display:inline-block" />
<input type="text" class="widefat custom_media_url" name="<?php echo $this->get_field_name('image_uri'); ?>" id="<?php echo $this->get_field_id('image_uri'); ?>" value="<?php echo $instance['image_uri']; ?>">
<input type="button" value="<?php _e( 'Загрузить изображение', 'themename' ); ?>" class="button custom_media_upload" id="custom_image_uploader"/>
</p>
<?php } } ?>
Вот JS//
jQuery(document).ready( function(){
function media_upload( button_class) {
var _custom_media = true,
_orig_send_attachment = wp.media.editor.send.attachment;
jQuery('body').on('click',button_class, function(e) {
var button_id ='#'+jQuery(this).attr('id');
/* console.log(button_id); */
var self = jQuery(button_id);
var send_attachment_bkp = wp.media.editor.send.attachment;
var button = jQuery(button_id);
var id = button.attr('id').replace('_button', '');
_custom_media = true;
wp.media.editor.send.attachment = function(props, attachment){
if ( _custom_media ) {
jQuery('.custom_media_id').val(attachment.id);
jQuery('.custom_media_url').val(attachment.url);
jQuery('.custom_media_image').attr('src',attachment.url).css('display','block');
} else {
return _orig_send_attachment.apply( button_id, [props, attachment] );
}
}
wp.media.editor.open(button);
return false;
});
}
media_upload( '.custom_media_upload');
});
Итак, мой вопрос: что именно нужно исправить, чтобы этот загрузчик изображений работал? Я думал, что обновления, предоставленные "sven", помогут, но очевидно, что я что-то упускаю. Пожалуйста, помогите.

Давайте разберемся подробно: Зарегистрированная область виджетов (с идентификатором left-sidebar
) имеет два аргумента для обертки всего виджета (before_widget
и after_widget
), которые вы можете вывести с помощью echo $before_widget
и echo $after_widget
в вашем виджете (см. мою версию ниже):
<?php
// Регистрация области виджетов
if (function_exists('register_sidebar')) {
register_sidebar(
array(
'name' => 'Левая колонка',
'id' => 'left-sidebar',
'description' => 'Область для виджетов',
'before_widget' => '<div id="one" class="two">',
'after_widget' => '</div>',
)
);
}
// Регистрация виджета
add_action('widgets_init', 'ctUp_ads_widget');
function ctUp_ads_widget() {
register_widget( 'ctUp_ads' );
}
// Подключение дополнительных скриптов в админке
add_action('admin_enqueue_scripts', 'ctup_wdscript');
function ctup_wdscript() {
wp_enqueue_media();
wp_enqueue_script('ads_script', get_template_directory_uri() . '/js/widget.js', false, '1.0.0', true);
}
// Виджет
class ctUp_ads extends WP_Widget {
function ctUp_ads() {
$widget_ops = array('classname' => 'ctUp-ads');
$this->WP_Widget('ctUp-ads-widget', 'EOTW', $widget_ops);
}
function widget($args, $instance) {
echo $before_widget;
?>
<h1><?php echo apply_filters('widget_title', $instance['text'] ); ?></h1>
<img src="<?php echo esc_url($instance['image_uri']); ?>" />
<?php
echo $after_widget;
}
function update($new_instance, $old_instance) {
$instance = $old_instance;
$instance['text'] = strip_tags( $new_instance['text'] );
$instance['image_uri'] = strip_tags( $new_instance['image_uri'] );
return $instance;
}
function form($instance) {
?>
<p>
<label for="<?php echo $this->get_field_id('text'); ?>">Текст</label><br />
<input type="text" name="<?php echo $this->get_field_name('text'); ?>" id="<?php echo $this->get_field_id('text'); ?>" value="<?php echo $instance['text'] ?? ''; ?>" class="widefat" />
</p>
<p>
<label for="<?= $this->get_field_id( 'image_uri' ); ?>">Изображение</label>
<img class="<?= $this->id ?>_img" src="<?= (!empty($instance['image_uri'])) ? $instance['image_uri'] : ''; ?>" style="margin:0;padding:0;max-width:100%;display:block"/>
<input type="text" class="widefat <?= $this->id ?>_url" name="<?= $this->get_field_name( 'image_uri' ); ?>" value="<?= $instance['image_uri'] ?? ''; ?>" style="margin-top:5px;" />
<input type="button" id="<?= $this->id ?>" class="button button-primary js_custom_upload_media" value="Загрузить изображение" style="margin-top:5px;" />
</p>
<?php
}
}
И JavaScript для кнопки загрузки:
jQuery(document).ready(function ($) {
function media_upload(button_selector) {
var _custom_media = true,
_orig_send_attachment = wp.media.editor.send.attachment;
$('body').on('click', button_selector, function () {
var button_id = $(this).attr('id');
wp.media.editor.send.attachment = function (props, attachment) {
if (_custom_media) {
$('.' + button_id + '_img').attr('src', attachment.url);
$('.' + button_id + '_url').val(attachment.url);
} else {
return _orig_send_attachment.apply($('#' + button_id), [props, attachment]);
}
}
wp.media.editor.open($('#' + button_id));
return false;
});
}
media_upload('.js_custom_upload_media');
});
Теперь ваш виджет может быть частью любой области виджетов. Для вывода области виджетов вы можете использовать функцию dynamic_sidebar()
, которая будет работать в любом месте ваших шаблонов:
if ( is_active_sidebar('left-sidebar') ) {
dynamic_sidebar('left-sidebar');
}
Обновление 01/2019: Я изменил код, чтобы он работал с несколькими виджетами и областями виджетов.

Огромное спасибо за вашу помощь! Всё работает идеально! Я искренне ценю вашу доброту!

Большое спасибо, но в моем виджете загруженный файл обновляется только когда я изменяю что-то внутри поля URL или другого поля. Загрузка изображения не обновляет это поле, можете помочь?

Мне удалось заставить работать решение Свена, но, как он упомянул в конце, есть проблема с идентификаторами - если у вас несколько загрузчиков на одной странице, они все будут изменяться одновременно. Я столкнулся с проблемами при использовании этого для виджетов в конструкторах страниц и подобных случаях. Я исправил это, используя уникальный идентификатор виджета.
Мой код формы был таким:
<label class="widg-label widg-img-label" for="<?php echo $this->get_field_id( 'image_uri' ); ?>">Изображение</label>
<div class="widg-img" >
<img class="<?php echo $this->get_field_id( 'image_id' ); ?>_media_image custom_media_image" src="<?php if( !empty( $instance['image_uri'] ) ){echo $instance['image_uri'];} ?>" />
<input input type="hidden" type="text" class="<?php echo $this->get_field_id( 'image_id' ); ?>_media_id custom_media_id" name="<?php echo $this->get_field_name( 'image_id' ); ?>" id="<?php echo $this->get_field_id( 'image_id' ); ?>" value="<?php echo $instance['image_id']; ?>" />
<input type="text" class="<?php echo $this->get_field_id( 'image_id' ); ?>_media_url custom_media_url" name="<?php echo $this->get_field_name( 'image_uri' ); ?>" id="<?php echo $this->get_field_id( 'image_uri' ); ?>" value="<?php echo $instance['image_uri']; ?>" >
<input type="button" value="Загрузить изображение" class="button custom_media_upload" id="<?php echo $this->get_field_id( 'image_id' ); ?>"/>
</div>
А мой JavaScript код:
jQuery(document ).ready( function(){
function media_upload( button_class ) {
var _custom_media = true,
_orig_send_attachment = wp.media.editor.send.attachment;
jQuery('body').on('click','.custom_media_upload',function(e) {
var button_id ='#'+jQuery(this).attr( 'id' );
var button_id_s = jQuery(this).attr( 'id' );
console.log(button_id);
var self = jQuery(button_id);
var send_attachment_bkp = wp.media.editor.send.attachment;
var button = jQuery(button_id);
var id = button.attr( 'id' ).replace( '_button', '' );
_custom_media = true;
wp.media.editor.send.attachment = function(props, attachment ){
if ( _custom_media ) {
jQuery( '.' + button_id_s + '_media_id' ).val(attachment.id);
jQuery( '.' + button_id_s + '_media_url' ).val(attachment.url);
jQuery( '.' + button_id_s + '_media_image' ).attr( 'src',attachment.url).css( 'display','block' );
} else {
return _orig_send_attachment.apply( button_id, [props, attachment] );
}
}
wp.media.editor.open(button);
return false;
});
}
media_upload( '.custom_media_upload' );
});
Основное изменение - использование уникального идентификатора в форме виджета:
<?php echo $this->get_field_id( 'image_id' ); ?>
и добавление его перед классами, затем получение его без символа #:
var button_id_s = jQuery(this).attr( 'id' );
и вставка перед всеми классами, чтобы они соответствовали форме:
jQuery( '.' + button_id_s + '_media_id' ).val(attachment.id);
jQuery( '.' + button_id_s + '_media_url' ).val(attachment.url);
jQuery( '.' + button_id_s + '_media_image' ).attr( 'src',attachment.url).css( 'display','block' );
Надеюсь, это поможет тем, кто столкнулся с такой же проблемой.
