Вопрос или проблема
Я пытаюсь написать плагин, который добавляет пользовательское мета-поле к изображениям-вложениям, чтобы предоставить изображениям поле для указания авторства. Я использую фильтры ‘attachment_fields_to_edit’ и ‘attachment_fields_to_save’.
function hrld_attachment_field_credit( $form_fields, $post ) {
$value = get_post_meta( $post->ID, '_hrld_media_credit', true );
$form_fields['hrld_media_credit']['label'] = 'Медиа-автор';
$form_fields['hrld_media_credit']['input'] = 'html';
$form_fields['hrld_media_credit']['html'] = '<input type="text" class="text hrld_media_credit_input" id="attachments-'.$post->ID.'-hrld_media_credit" name="attachments['.$post->ID.'][hrld_media_credit]" value="'.$value.'">';
$form_fields['hrld_media_credit']['helps'] = 'Если фотографию сделал фотограф Herald, используйте его имя пользователя. например, "Bucky Badger". Вы должны написать "bbadger".';
return $form_fields;
}
add_filter( 'attachment_fields_to_edit', 'hrld_attachment_field_credit', 10, 2 );
Выше добавляется поле ввода.
function hrld_attachment_field_credit_save( $post, $attachment ) {
if( isset( $attachment['hrld_media_credit'] ) )
update_post_meta( $post['ID'], '_hrld_media_credit', $attachment['hrld_media_credit'] );
return $post;
}
add_filter( 'attachment_fields_to_save', 'hrld_attachment_field_credit_save', 10, 2 );
А выше приведен код для сохранения метаданных.
Проблема возникает, когда вы редактируете запись и нажимаете кнопку “Добавить медиа”, чтобы добавить изображение. При изменении метаданных изображения в этом окне загрузчика медиа, таких как подпись или альтернативный текст, WordPress автоматически сохраняет данные, когда текстовое поле теряет фокус. Мои метаданные также сохраняются аналогично без проблем. Я добавил фильтр к ‘image_send_to_editor’, чтобы автоматически добавить поле авторства внутрь тега подписи, если данные авторства присутствуют.
function hrld_media_credit_send_editor($html, $id, $caption, $title, $align, $url, $size){
$html = get_image_tag($id, '', $title, $align, $size);
$hrld_credit = get_hrld_media_credit($id);
if(isset($hrld_credit) && !empty($hrld_credit)){
if(get_user_by('login', $hrld_credit)){
$hrld_user = get_user_by('login', $hrld_credit);
$html_text="<span class="hrld-media-credit">Фото от ".$hrld_user->display_name.'.</span>';
} else{
$html_text="<span class="hrld-media-credit">".$hrld_credit.'.</span>';
}
if($caption){
$html = get_image_tag($id, '', $title, $align, $size);
$html .= $html_text;
} else{
$attach_attributes = wp_get_attachment_image_src($id, $isze);
$html=".'"]';
$html .= get_image_tag($id, '', $title, $align, $size);
$html .= $html_text;
$html .= '';
}
}
return $html;
}
add_filter( 'image_send_to_editor', 'hrld_media_credit_send_editor', 10, 7 );
Пока все работает как ожидается. Функциональность, которую я хочу, это использование jQuery UI Autocomplete для предложения логинов пользователей по мере их ввода, но я хочу оставить поле ввода свободным текстом, потому что кредит на изображение не обязательно должен быть пользователем в WordPress. Я использую этот Javascript, чтобы добавить функцию автозаполнения к каждому полю.
jQuery("body").on("keydown", ".hrld_media_credit_input", function(){
var hrld_media_input = jQuery(this);
hrld_media_input.autocomplete({
source: hrld_user_tags,
select: function (event, ui) {
console.log(hrld_media_input);
hrld_media_input.attr("value", ui.item.value);
}
});
});
Причина, по которой я использую .on(), заключается в том, что при использовании кнопки “Добавить медиа” поля ввода создаются динамически, поэтому без .on() автозаполнение будет применяться только при загрузке страницы, что эти поля ввода еще не существовали (я опустил часть кода PHP, который добавляет этот скрипт, а также создает переменную hrld_user_tags, которая является просто массивом имен пользователей).
Теперь, когда я использую автозаполнение для выбора предложенного имени пользователя, щелчок по этому имени для заполнения поля, WordPress не будет автоматически сохранять эти метаданные. Если я нажимаю вставить в запись, это не будет вставлено в тег подписи, как будто я никогда не вводил имя пользователя. Однако если я ввожу в поле и вижу, что “пример” — это предложение, если вместо того, чтобы щелкнуть по предложению для автозаполнения поля, я завершаю ввод “пример” вручную и затем нажимаю “Вставить в публикацию”, он сохраняет метаданные “пример” и вставит их в тег подписи.
Я искал часы, чтобы найти ответы на эту проблему, смотрел в файлы ядра wp-includes и wp-admin, пытаясь найти функции для применения фильтров или добавления действий для запуска сохранения моих данных, но не могу это выяснить.
Любая помощь или идеи по этой проблеме будут очень ценны.
Вы должны вызвать событие изменения вашего поля, т.е. hrld_media_input.attr("value", ui.item.value).change();
. Это обеспечит вызов attachment_fields_to_save.
Ответ или решение
Проблема с сохранением пользовательских метаполей в загрузчике медиа при использовании jQuery UI Autocomplete
Ваша задача по добавлению пользовательского метаполя для кредитования изображений в WordPress через загрузчик медиа кажется вполне осуществимой. Вы используете подходящие фильтры attachment_fields_to_edit
и attachment_fields_to_save
, что правильно. Однако проблема возникает из-за того, что изменение значения поля с помощью jQuery UI Autocomplete не вызывает автоматическое сохранение метаданных, как это происходит с вручную введенными значениями.
Природа проблемы
Когда вы используете функцию автозаполнения jQuery UI, значение поля обновляется программно. Однако WordPress не фиксирует это изменение, поскольку не возникает события change
, которое триггерит процесс сохранения. Поэтому, когда вы выбираете значение из списка предложений, оно не сохраняется, и, следовательно, не попадает в метаданные, когда вы нажимаете "Вставить в пост".
Решение проблемы
Чтобы исправить это, вам необходимо программно вызвать событие change
на вашем поле. Это гарантирует, что фильтр attachment_fields_to_save
будет вызван и ваши метаданные будут сохранены. Ниже приведено, как это сделать.
Измените вашу функцию с автозаполнением следующим образом:
jQuery("body").on("keydown", ".hrld_media_credit_input", function(){
var hrld_media_input = jQuery(this);
hrld_media_input.autocomplete({
source: hrld_user_tags,
select: function (event, ui) {
hrld_media_input.attr("value", ui.item.value).change(); // Триггер события 'change'
}
});
});
Объяснение кода
hrld_media_input.attr("value", ui.item.value).change();
: Здесь мы устанавливаем значение поля так же, как и раньше, но теперь мы добавляем.change()
, чтобы триггерить событие изменения. Это событие вызовет механизм сохранения в WordPress, в результате чего данные будут сохранены и корректно вставлены в тег с подписями.
Итог
Внедрив данный подход, вы обеспечите сохранение значений, выбранных через автозаполнение, так же корректно, как и вручную введенных, что позволит вашему плагину работать следующим образом:
- Пользователь вводит текст в поле кредитования.
- Появляются предложения; пользователь выбирает одно из них.
- Значение сохраняется в метаданных через фильтры WordPress.
- Если указано, значение вставляется в тег во время вставки изображения в запись.
Это решение исправит вашу проблему, и ваш плагин сможет эффективно обрабатывать запросы на кредитование изображений, облегчая задачу пользователям и повышая общую функциональность вашего проекта.
Если у вас есть дополнительные вопросы или потребуется дальнейшая помощь, не стесняйтесь обращаться!