Come selezionare un'immagine dalla Libreria Media nel mio plugin?
Ho sviluppato un plugin che mostra una piccola icona di chat nell'angolo in basso a destra, tuttavia vorrei permettere all'utente di scegliere un'immagine come icona dalla Libreria Media
. Come posso farlo utilizzando l'API di WordPress? L'immagine è un'impostazione del plugin (modificabile solo dall'amministratore)

Dovresti usare wp.media
per utilizzare la finestra di dialogo del Media Manager di WordPress.
Per prima cosa, devi mettere in coda gli script:
// Dato che stai lavorando con le impostazioni del plugin,
// presumo che tu sia nell'area di amministrazione
add_action( 'admin_enqueue_scripts', 'load_wp_media_files' );
function load_wp_media_files( $page ) {
// cambia con la $page dove vuoi mettere in coda lo script
if( $page == 'options-general.php' ) {
// Metti in coda gli script media di WordPress
wp_enqueue_media();
// Metti in coda lo script personalizzato che interagirà con wp.media
wp_enqueue_script( 'myprefix_script', plugins_url( '/js/myscript.js' , __FILE__ ), array('jquery'), '0.1' );
}
}
Il tuo HTML potrebbe essere qualcosa come questo (nota che il mio codice utilizza l'ID dell'allegato nelle impostazioni del plugin invece dell'URL dell'immagine come hai fatto nella tua risposta, penso sia molto meglio. Ad esempio, utilizzare l'ID ti permette di ottenere diverse dimensioni dell'immagine quando ne hai bisogno):
$image_id = get_option( 'myprefix_image_id' );
if( intval( $image_id ) > 0 ) {
// Cambia con la dimensione dell'immagine che vuoi usare
$image = wp_get_attachment_image( $image_id, 'medium', false, array( 'id' => 'myprefix-preview-image' ) );
} else {
// Un'immagine predefinita
$image = '<img id="myprefix-preview-image" src="https://some.default.image.jpg" />';
}
echo $image; ?>
<input type="hidden" name="myprefix_image_id" id="myprefix_image_id" value="<?php echo esc_attr( $image_id ); ?>" class="regular-text" />
<input type='button' class="button-primary" value="<?php esc_attr_e( 'Seleziona un\'immagine', 'mytextdomain' ); ?>" id="myprefix_media_manager"/>
myscript.js
jQuery(document).ready( function($) {
jQuery('input#myprefix_media_manager').click(function(e) {
e.preventDefault();
var image_frame;
if(image_frame){
image_frame.open();
}
// Definisci image_frame come oggetto wp.media
image_frame = wp.media({
title: 'Seleziona Media',
multiple : false,
library : {
type : 'image',
}
});
image_frame.on('close',function() {
// Alla chiusura, ottieni le selezioni e salva nell'input nascosto
// più altre operazioni AJAX per aggiornare l'anteprima dell'immagine
var selection = image_frame.state().get('selection');
var gallery_ids = new Array();
var my_index = 0;
selection.each(function(attachment) {
gallery_ids[my_index] = attachment['id'];
my_index++;
});
var ids = gallery_ids.join(",");
if(ids.length === 0) return true;//se chiuso senza selezionare un'immagine
jQuery('input#myprefix_image_id').val(ids);
Refresh_Image(ids);
});
image_frame.on('open',function() {
// All'apertura, ottieni l'id dall'input nascosto
// e seleziona le immagini appropriate nel media manager
var selection = image_frame.state().get('selection');
var ids = jQuery('input#myprefix_image_id').val().split(',');
ids.forEach(function(id) {
var attachment = wp.media.attachment(id);
attachment.fetch();
selection.add( attachment ? [ attachment ] : [] );
});
});
image_frame.open();
});
});
// Richiesta AJAX per aggiornare l'anteprima dell'immagine
function Refresh_Image(the_id){
var data = {
action: 'myprefix_get_image',
id: the_id
};
jQuery.get(ajaxurl, data, function(response) {
if(response.success === true) {
jQuery('#myprefix-preview-image').replaceWith( response.data.image );
}
});
}
E l'azione Ajax per aggiornare l'anteprima dell'immagine:
// Azione Ajax per aggiornare l'immagine utente
add_action( 'wp_ajax_myprefix_get_image', 'myprefix_get_image' );
function myprefix_get_image() {
if(isset($_GET['id']) ){
$image = wp_get_attachment_image( filter_input( INPUT_GET, 'id', FILTER_VALIDATE_INT ), 'medium', false, array( 'id' => 'myprefix-preview-image' ) );
$data = array(
'image' => $image,
);
wp_send_json_success( $data );
} else {
wp_send_json_error();
}
}
PD: è un esempio rapido scritto qui basato su un'altra risposta. Non testato perché non hai fornito abbastanza informazioni sul contesto esatto in cui il codice verrà utilizzato o sui problemi esatti che hai.

La chiamata ajax get_image non è necessaria. selection.models[0].attributes.url
contiene l'URL dell'immagine selezionata alla chiusura di image_frame
. Se vuoi utilizzare una dimensione specifica, avrai bisogno della chiamata ajax.

Facile da usare, basta copiare e incollare il codice nel punto desiderato
<?php
if ( isset( $_POST['submit_image_selector'] ) && isset( $_POST['image_attachment_id'] ) ) :
update_option( 'media_selector_attachment_id', absint( $_POST['image_attachment_id'] ) );
endif;
wp_enqueue_media();
?><form method='post'>
<div class='image-preview-wrapper'>
<img id='image-preview' src='<?php echo wp_get_attachment_url( get_option( 'media_selector_attachment_id' ) ); ?>' width='200' alt="Anteprima immagine" title="Anteprima immagine selezionata">
</div>
<input id="upload_image_button" type="button" class="button" value="<?php _e( 'Carica immagine' ); ?>" />
<input type='hidden' name='image_attachment_id' id='image_attachment_id' value='<?php echo get_option( 'media_selector_attachment_id' ); ?>'>
<input type="submit" name="submit_image_selector" value="Salva" class="button-primary">
</form>
<?php
$my_saved_attachment_post_id = get_option( 'media_selector_attachment_id', 0 );
?><script type='text/javascript'>
jQuery( document ).ready( function( $ ) {
// Uploading files
var file_frame;
var wp_media_post_id = wp.media.model.settings.post.id; // Memorizza il vecchio ID
var set_to_post_id = <?php echo $my_saved_attachment_post_id; ?>; // Imposta questo
jQuery('#upload_image_button').on('click', function( event ){
event.preventDefault();
// Se il frame media esiste già, riaprirlo
if ( file_frame ) {
// Imposta l'ID del post a quello che vogliamo
file_frame.uploader.uploader.param( 'post_id', set_to_post_id );
// Apri il frame
file_frame.open();
return;
} else {
// Imposta l'ID del post wp.media in modo che l'uploader prenda l'ID desiderato all'inizializzazione
wp.media.model.settings.post.id = set_to_post_id;
}
// Crea il frame media
file_frame = wp.media.frames.file_frame = wp.media({
title: 'Seleziona un\'immagine da caricare',
button: {
text: 'Usa questa immagine',
},
multiple: false // Imposta a true per consentire la selezione di più file
});
// Quando un'immagine è selezionata, esegui una callback
file_frame.on( 'select', function() {
// Abbiamo impostato multiple a false per ottenere solo un'immagine dall'uploader
attachment = file_frame.state().get('selection').first().toJSON();
// Fai qualcosa con attachment.id e/o attachment.url qui
$( '#image-preview' ).attr( 'src', attachment.url ).css( 'width', 'auto' );
$( '#image_attachment_id' ).val( attachment.id );
// Ripristina l'ID principale del post
wp.media.model.settings.post.id = wp_media_post_id;
});
// Infine, apri il modal
file_frame.open();
});
// Ripristina l'ID principale quando viene premuto il pulsante aggiungi media
jQuery( 'a.add_media' ).on( 'click', function() {
wp.media.model.settings.post.id = wp_media_post_id;
});
});
</script>

Quindi questa risposta ha funzionato perfettamente. Ma per renderla riutilizzabile, ho convertito il codice in una funzione. Quindi, per utilizzarla, devi prima controllare questo per enqueue
lo script. E poi dichiarare wpOpenGallery
in questo modo:
(function($) {
$(document).ready(function() {
const wpOpenGallery = function(o, callback) {
const options = (typeof o === 'object') ? o : {};
// Impostazioni predefinite
const defaultOptions = {
title: 'Seleziona Media',
fileType: 'image',
multiple: false,
currentValue: '',
};
const opt = { ...defaultOptions, ...options };
let image_frame;
if(image_frame){
image_frame.open();
}
// Definisce image_frame come oggetto wp.media
image_frame = wp.media({
title: opt.title,
multiple : opt.multiple,
library : {
type : opt.fileType,
}
});
image_frame.on('open',function() {
// All'apertura, ottiene l'id dall'input nascosto
// e seleziona le immagini appropriate nel media manager
const selection = image_frame.state().get('selection');
const ids = opt.currentValue.split(',');
ids.forEach(function(id) {
const attachment = wp.media.attachment(id);
attachment.fetch();
selection.add( attachment ? [ attachment ] : [] );
});
});
image_frame.on('close',function() {
// Alla chiusura, ottiene le selezioni e salva nell'input nascosto
// più altre operazioni AJAX per aggiornare l'anteprima dell'immagine
const selection = image_frame.state().get('selection');
const files = [];
selection.each(function(attachment) {
files.push({
id: attachment.attributes.id,
filename: attachment.attributes.filename,
url: attachment.attributes.url,
type: attachment.attributes.type,
subtype: attachment.attributes.subtype,
sizes: attachment.attributes.sizes,
});
});
callback(files);
});
image_frame.open();
}
})
}(jQuery));
E chiamarla così:
wpOpenGallery(null, function(data) {
console.log(data);
});

Utilizza wordpress-settings-api-class
di Tareq Hasan, Url: https://github.com/tareq1988/wordpress-settings-api-class
- Includi la classe principale
class.settings-api.php
nel tuo plugin. (questo file https://github.com/tareq1988/wordpress-settings-api-class/blob/master/src/class.settings-api.php) - Definisci le tue opzioni. Dovrai usare
'type' => 'file'
se vuoi aggiungere un caricatore di media. (Vedi questo esempio per una migliore comprensione https://github.com/tareq1988/wordpress-settings-api-class/blob/master/example/procedural-example.php)

Penso che una soluzione senza librerie aggiuntive sia migliore, solida; come il wp.media
control.

Dal momento che vuoi che l'icona sia diversa per ogni utente, dovrai memorizzare l'immagine nel profilo dell'utente. Questo significa che devi aggiungere un campo utente aggiuntivo:
// crea il campo
add_action( 'show_user_profile', 'wpse_235406_chaticon' );
add_action( 'edit_user_profile', 'wpse_235406_chaticon' );
function wpse_235406_chaticon ($user) {
echo '
<h3>Icona Chat</h3>
<table class="form-table">
<tr>
<th><label for="chaticon">Icona Chat</label></th>
<td>
<input type="file" name="chaticon" id="chaticon" value="' . esc_attr (get_the_author_meta ('chaticon', $user->ID)) . '" class="file-upload" /><br />
<span class="description">Seleziona la tua icona per la chat.</span>
</td>
</tr>
</table>';
}
// salva il campo
add_action( 'personal_options_update', 'wpse_235406_chaticon_save' );
add_action( 'edit_user_profile_update', 'wpse_235406_chaticon_save' );
function wpse_235406_chaticon_save ($user_id) {
if (current_user_can ('edit_user', $user_id))
update_usermeta ($user_id, 'chaticon', $_POST['chaticon']);
}
Ora, questo ti dà la possibilità di caricare un file dal computer dell'utente. Se vuoi che l'utente selezioni il file da immagini esistenti, le cose si complicano, perché allora devi richiamare la libreria media invece del normale caricamento file. Steven Slack ha scritto un post eccellente su come fare questo, che non voglio copiare-incollare qui togliendogli il merito.
Nel tuo template devi distinguere tre possibilità: utente non loggato, utente loggato ma senza icona, utente loggato con icona. In generale, includi questo:
$current_user = wp_get_current_user();
if ( 0 == $current_user->ID ) {
... fai quello che vuoi per gli utenti non loggati ...
}
else {
$icon = get_user_meta ($current_user->ID, 'chaticon');
if (empty($icon)) {
... icona di default con link alla possibilità di upload ...
}
else {
... mostra $icon ...
}

Intendi che solo l'amministratore del sito dovrebbe poter cambiare l'icona e sarà la stessa per ogni visitatore/utente?

Sarebbe abbastanza banale. Ecco un tutorial per questo: https://mikejolley.com/2012/12/21/using-the-new-wordpress-3-5-media-uploader-in-plugins/

Ho utilizzato questa soluzione (senza usare direttamente la Libreria Multimediale):
Usando image-picker-lib all'interno di una modale che imposta il valore di un input nascosto, che viene inviato alle opzioni. Ottenendo tutti i media e visualizzandoli come opzioni, posso permettere all'utente di selezionare un'immagine.
HTML
<input id="image" name="image" class="validate" type="image" src="<?php echo esc_attr(get_option('image_url')); ?>" id="image_url" width="48" height="48" />
<br>
<a href="#imageModal" class="waves-effect waves-light btn modal-trigger">
cambia
</a>
<input id="image_url" name="image_url" type="text" value="" hidden />
PHP/HTML
<div id="imageModal" class="modal">
<div class="modal-content">
<select class="image-picker show-html">
<option data-img-src="<?php echo CM_PATH . "/img/chat_general.png" ?>" value="0"></option>
<?php
$query_images_args = array(
'post_type' => 'attachment',
'post_mime_type' => 'image',
'post_status' => 'inherit',
'posts_per_page' => - 1,
);
$query_images = new WP_Query( $query_images_args );
$i = 1;
foreach ( $query_images->posts as $image ) {
?>
<option data-img-src="<?php echo wp_get_attachment_url($image->ID); ?>" value="<?php echo $i; ?>"></option>
<?php
$i++;
}
?>
</select>
</div>
<div class="modal-footer">
<a class="waves-effect waves-light btn change">Scegli</a>
</div>
</div>
</div>
</div>
JS
$(".change").on("click", function() {
+ var url = $(".image-picker > option:selected").attr("data-img-src");
+ $("#image").attr("src", url);
+ $("#image_url").attr("value", url);
+ $("#imageModal").closeModal();
+ });

Penso che una soluzione senza librerie aggiuntive sia migliore, solida; come il wp.media
control.

@bueltge Sono d'accordo, ma nessuno ha dato una risposta diretta e avevo fretta. Quindi se qualcuno fornisce una grande risposta, si merita il premio!

Vedo anche la tua risposta come una soluzione, ma non la migliore. Ora spetta all'autore della domanda, cioè a te ;), prendere la decisione.

Questa soluzione può rapidamente diventare un problema all'aumentare del numero di immagini. "nessuno ha dato una risposta diretta" non è una scusa; la tua domanda è molto scarsa, quindi ottieni risposte scadenti. Non ci mostri alcuno sforzo, ricerca o codice che hai provato, solo "voglio fare questo, dammi una soluzione pronta all'uso", che è come dire "fai il lavoro al posto mio". Cerca wp.media come ha suggerito bueltge; ci sono centinaia di esempi qui su WPSE. Se hai problemi a usarlo, pubblica una nuova domanda al riguardo.

@cybmeta Ho provato e questo è il mio miglior tentativo, quindi non fare lo stronzo. Se non ti piace, proponi una soluzione migliore.

wp.media
è la migliore opzione che hai ed è quella che ti propongo; prova a usarlo e, se hai domande al riguardo, chiedile. Ho scritto diverse risposte sull'uso di wp.media
così come altre persone, prova a usare la barra di ricerca (o Google), prova tu stesso e pubblica domande sui problemi che potresti incontrare nel suo utilizzo. Scusa se i miei commenti ti sono sembrati brutti, ti lamenti di non ottenere buone risposte, ho solo cercato di spiegarti il perché. Onestamente, penso che dovresti prendere il mio commento senza offesa e imparare a evitare domande scadenti.

A proposito, quando ho detto "non ci mostri alcuno sforzo, ricerca o codice che hai provato" mi riferivo alla tua domanda. Pensavo che il mio commento fosse chiaro a riguardo, forse non lo era e avrei dovuto pubblicare quel commento nella domanda e non nella risposta. Comunque, ho aggiunto una risposta; spero che ti sia utile.
