Добавление изображения в медиатеку из URL в директории uploads
Плагин "Video Embed & Thumbnail Generator" отлично генерирует миниатюры из видео. Он сохраняет URL миниатюры как метаданные вложения. Миниатюра добавляется в директорию uploads. Есть ли способ добавить это изображение в медиатеку, чтобы я мог пропустить его через функцию image_downsize для создания миниатюры другого размера?
Функция wp_insert_attachment, похоже, требует путь к файлу, а не URL, или я ошибаюсь? Как я могу добавить URL в медиатеку?
Возможно, это дубликат вопроса Как получить изображение из директории uploads и добавить его в медиатеку?, но на него не было получено ответов.

Если изображение находится в исходном коде контента, вы можете извлечь его и использовать media_sideload_image(); для импорта в медиатеку.
Этот пример кода взят из моего плагина Media Tools, который выполняет эту операцию через административную страницу с использованием AJAX. Он также устанавливает извлеченное изображение как миниатюру записи. ID записи передается в эту функцию через AJAX. Чтобы увидеть полный код, перейдите по ссылке: http://plugins.trac.wordpress.org/browser/media-tools/trunk/media-tools.php?rev=581988
function process_image( $post_id ) {
$response = '';
$error = 0;
$post = get_post( $post_id );
$img = $this->extract_image( $post );
if( empty( $img ) ) {
$response .= 'Изображения не найдены <br>';
die( sprintf( $response . '<br>Инструмент Media Tools завершил работу (ID записи %1$s) за %2$s секунд. Ошибок: %3$d', esc_html( $post->ID ), timer_stop(), $error = $error > 0 ? $error : 'нет' ) );
}
/** @var $file string or WP_Error of image attached to the post */
$file = media_sideload_image( $img, (int)$post->ID );
if ( is_wp_error( $file ) ) {
$response .= '<span style="color:red">Ошибка загрузки: Не удалось загрузить изображение. Проверьте URL в атрибуте src тега img</span><br>';
$error++;
} else {
$atts = $this->get_attach( $post->ID );
foreach ( $atts as $a ) {
$img = set_post_thumbnail( $post->ID, $a['ID'] );
if ( $img ) {
$thumb = wp_get_attachment_thumb_url( $a['ID'] );
$response .= '<img src="'.esc_url( $thumb ).'" /><br>';
$response .= '<a href="'.wp_nonce_url( get_edit_post_link( $a['ID'], true ) ).'" >'.get_the_title( $a['ID'] ).'</a> Установлено как миниатюра записи</p><br>';
}
}
unset( $atts );
unset( $a );
}
die( sprintf( $response.'<br>Инструмент Media Tools завершил работу (ID записи %1$s) за %2$s секунд. Ошибок: %3$d', esc_html( $post->ID ), timer_stop(), $error = $error > 0 ? $error : 'нет' ) );
}
/**
* Извлекает первое изображение из содержимого записи
* @param object $post объект записи
* @return bool|string false если изображений нет или src изображения
*/
function extract_image( $post ) {
$html = $post->post_content;
if ( stripos( $html, '<img' ) !== false ) {
$regex = '#<\s*img [^\>]*src\s*=\s*(["\'])(.*?)\1#im';
preg_match( $regex, $html, $matches );
unset( $regex );
unset( $html );
if ( is_array( $matches ) && ! empty( $matches ) ) {
return $matches[2];
} else {
return false;
}
} else {
return false;
}
}
/**
* Ищет прикрепленные изображения
* @param int $post_id ID записи для проверки наличия вложений
* @return array|bool Первое вложение при успехе или false если вложений нет
*/
function get_attach( $post_id ) {
return get_children( array (
'post_parent' => $post_id,
'post_type' => 'attachment',
'post_mime_type' => 'image',
'posts_per_page' => (int)1
), ARRAY_A );
}

Функция media_sideload_image() выглядит перспективно, но как получить ID вложения для загруженного изображения?

Посмотрите на функцию get_attach. Она выполняется после media_sideload_image.

Вы имеете в виду get_attachment? Для неё нужен ID, которого у меня пока нет. Я собираюсь изучить media_handle_sideload()

также media sideload не совсем подходит, потому что дублирует изображения, которые уже есть в папке wp-uploads (куда их добавляет плагин video embedder)

На самом деле video embedder должен добавлять их в вашу медиатеку, а не просто сбрасывать в папку uploads.

Вот соответствующие части, которые я изменил в функции kg_video_attachment_fields_to_save()
, которая фильтрует attachment_fields_to_save
:
$thumb_url = $attachment['kgflashmediaplayer-poster'];
//вставляем $thumb_url в медиатеку, если он еще не существует
if ( ! ($thumb_id = get_attachment_id_from_src( $thumb_url ) ) ) {
$post_id = $post['ID'];
$desc = $attachment['post_title'] . ' миниатюра';
//находится ли изображение в директории загрузок?
$upload_dir = wp_upload_dir();
if ( FALSE !== strpos( $url, $upload_dir['baseurl'] ) ) {
$wp_filetype = wp_check_filetype(basename($thumb_url), null );
$filename = preg_replace('/\.[^.]+$/', '', basename($thumb_url));
$attachment = array(
'guid' => $thumb_url,
'post_mime_type' => $wp_filetype['type'],
'post_title' => $desc,
'post_content' => '',
'post_status' => 'inherit'
);
$thumb_id = wp_insert_attachment( $attachment, basename($thumb_url), $post_id );
// сначала необходимо подключить файл image.php
// для работы функции wp_generate_attachment_metadata()
require_once(ABSPATH . 'wp-admin/includes/image.php');
$attach_data = wp_generate_attachment_metadata( $thumb_id, basename($thumb_url) );
wp_update_attachment_metadata( $thumb_id, $attach_data );
} else { //не в загрузках, поэтому нужно загрузить через sideload
$tmp = download_url( $thumb_url );
// Устанавливаем переменные для хранения
// исправляем имя файла для query strings
preg_match('/[^\?]+\.(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG)/', $thumb_url, $matches);
$file_array['name'] = basename($matches[0]);
$file_array['tmp_name'] = $tmp;
// Если ошибка временного хранения, удаляем
if ( is_wp_error( $tmp ) ) {
@unlink($file_array['tmp_name']);
$file_array['tmp_name'] = '';
}
// выполняем проверку и загрузку
$thumb_id = media_handle_sideload( $file_array, $post_id, $desc );
// Если ошибка постоянного хранения, удаляем
if ( is_wp_error($thumb_id) ) {
@unlink($file_array['tmp_name']);
return $thumb_id;
}
if ( $local_src = wp_get_attachment_url( $thumb_id ) ) {
update_post_meta($post['ID'], '_kgflashmediaplayer-poster', $local_src);
}
} //конец sideload
} //конец get_attachment_id_from_src
if(!is_wp_error($thumb_id)) {
$thumb_id = intval( $thumb_id );
update_post_meta($post['ID'], '_kgflashmediaplayer-poster-id', $thumb_id);
}
Теперь ID пользовательской миниатюры видео хранится в метаполе: _kgflashmediaplayer-poster-id
function get_attachment_id_from_src ($image_src) {
global $wpdb;
$query = "SELECT ID FROM {$wpdb->posts} WHERE guid='$image_src'";
$id = $wpdb->get_var($query);
return $id;
}
Мне не очень нравится функция get_attachment_id_from_src()
, но встроенного способа сделать это нет. Я должен добавить проверку, чтобы если текущий src совпадает со старым, этот запрос не выполнялся. Плагин для встраивания создает множество потенциальных миниатюр для каждого видео, и нет необходимости вставлять их все в медиатеку... Этот код срабатывает при сохранении вложения и должен обрабатывать изображения, которые уже есть в медиатеке, изображения в директории загрузок, но не в медиатеке, и изображения на других серверах (которые загружаются через sideload, и их URL изменяется на локальный).

Отличная функция... потребовалось немного доработок, но отлично сработало для моих нужд ;)

Так как этому уже 3 года, предполагаю, что сейчас есть гораздо лучший способ сделать это.

все равно сработало для меня - а это все, что мне было нужно ;) - быстрый, готовый к использованию детализированный код. спасибо.
