Aggiungere un'immagine alla libreria multimediale da un URL nella directory uploads
Il plugin "Video Embed & Thumbnail Generator" fa un ottimo lavoro nel generare miniature dai video. Salva l'URL della miniatura come metadato per l'allegato. La miniatura viene aggiunta alla directory uploads. Esiste un modo per prendere questa immagine e aggiungerla alla libreria multimediale in modo da poterla passare attraverso la funzione image_downsize per creare miniature di dimensioni diverse?
wp_insert_attachment sembra richiedere un percorso a un file e non un URL, o mi sbaglio? Come posso aggiungere un URL alla libreria multimediale?
Questo potrebbe essere un duplicato di Come posso ottenere un'immagine dalla directory uploads e inserirla nella libreria multimediale? ma quella domanda non ha mai ricevuto risposte.

Se l'immagine è presente nel contenuto sorgente puoi estrarla e utilizzare media_sideload_image(); per importarla nella libreria media.
Questo esempio di codice è tratto dal mio plugin Media Tools. Che esegue questa operazione tramite una pagina di amministrazione via ajax. Imposta anche l'immagine estratta come immagine in evidenza per l'articolo. L'ID del post viene passato a questa funzione via ajax. Per vedere il codice completo consulta: 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 .= 'Nessuna immagine trovata <br>';
die( sprintf( $response . '<br>Media tool completato (Post ID %1$s) in %2$s secondi. %3$d errori', esc_html( $post->ID ), timer_stop(), $error = $error > 0 ? $error : 'no' ) );
}
/** @var $file string o WP_Error dell'immagine allegata al post */
$file = media_sideload_image( $img, (int)$post->ID );
if ( is_wp_error( $file ) ) {
$response .= '<span style="color:red">Errore di Upload: Impossibile caricare l\'immagine. Verifica la presenza di un URL src malformato</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> Impostata come Immagine in Evidenza</p><br>';
}
}
unset( $atts );
unset( $a );
}
die( sprintf( $response.'<br>Media tool completato (Post ID %1$s) in %2$s secondi. %3$d errori', esc_html( $post->ID ), timer_stop(), $error = $error > 0 ? $error : 'no' ) );
}
/**
* Estrae la prima immagine nel contenuto del post
* @param object $post l'oggetto post
* @return bool|string false se non ci sono immagini o img 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;
}
}
/**
* Cerca immagini allegate
* @param int $post_id L'ID del post da verificare per allegati esistenti
* @return array|bool Il primo allegato in caso di successo, false se non ci sono allegati
*/
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() sembra promettente, ma come si recupera l'ID dell'allegato per l'immagine sideloaded?

Guarda la funzione get_attach. Viene eseguita dopo media_sideload_image.

intendi get_attachment? quella ha bisogno dell'ID che non ho ancora. Darò un'occhiata a media_handle_sideload()

inoltre il media sideload non è proprio corretto perché duplica le immagini che sono già nella cartella wp-uploads (dove il plugin video embedder le sta aggiungendo)

Beh, il video embedder dovrebbe aggiungerle alla tua libreria media invece che limitarsi a scaricarle nella tua cartella uploads.

Ecco le parti pertinenti che ho modificato dalla funzione kg_video_attachment_fields_to_save()
che filtra attachment_fields_to_save
:
$thumb_url = $attachment['kgflashmediaplayer-poster'];
//inserisce l'URL della miniatura nella libreria media se non esiste già
if ( ! ($thumb_id = get_attachment_id_from_src( $thumb_url ) ) ) {
$post_id = $post['ID'];
$desc = $attachment['post_title'] . ' miniatura';
//l'immagine si trova nella directory degli upload?
$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 );
// è necessario includere prima il file image.php
// affinché la funzione wp_generate_attachment_metadata() funzioni
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 { //non è negli upload, quindi dobbiamo caricarla tramite sideload
$tmp = download_url( $thumb_url );
// Imposta le variabili per lo storage
// corregge il nome del file per le query string
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;
// Se c'è un errore nello storage temporaneo, cancella
if ( is_wp_error( $tmp ) ) {
@unlink($file_array['tmp_name']);
$file_array['tmp_name'] = '';
}
// esegue la validazione e lo storage
$thumb_id = media_handle_sideload( $file_array, $post_id, $desc );
// Se c'è un errore nello storage permanente, cancella
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);
}
} //fine sideload
} //fine 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);
}
E ora l'ID della miniatura personalizzata del video è archiviato nel campo meta: _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;
}
Non amo particolarmente la funzione get_attachment_id_from_src()
ma non esiste un modo integrato per farlo. Dovrei aggiungere un controllo in modo che se l'attuale src è lo stesso del vecchio sorgente, questa query non debba essere eseguita. Il plugin di embedding crea molte potenziali miniature per ogni video e non c'è bisogno di inserirle tutte nella libreria media... quindi questo viene eseguito ogni volta che un allegato media viene salvato e dovrebbe coprire immagini già presenti nella libreria media, immagini nella directory media ma non nella libreria e immagini su altri server (che vengono caricate tramite sideload e l'URL viene adattato al nuovo URL locale)

Funzione fantastica... ha richiesto qualche piccola modifica ma ha funzionato alla grande per le mie esigenze ;)

Visto che questo codice ha 3 anni, presumo che ora ci sia un modo molto migliore per farlo.

ha comunque funzionato per me - che è tutto ciò di cui avevo bisogno ;) - un codice dettagliato, pronto all'uso e veloce. grazie.
