¿Cómo selecciono una imagen de la Biblioteca de Medios en mi plugin?

9 ago 2016, 10:52:11
Vistas: 48.9K
Votos: 31

He escrito un plugin que tiene un pequeño ícono de chat en la esquina inferior derecha, sin embargo, quiero que el usuario pueda elegir una imagen como ícono desde la Biblioteca de Medios. ¿Cómo puedo hacer esto con la API de WordPress? La imagen es un ajuste en el plugin (solo modificable por el administrador)

1
Comentarios

Debes incluir wp.media para permitir subidas personalizadas y selección de un archivo multimedia para este requisito. WPSE tiene muchos ejemplos, pero quizás esta publicación te ayude http://jeroensormani.com/how-to-include-the-wordpress-media-selector-in-your-plugin/ También encontrarás ejemplos en GitHub, especialmente de ocean90 - https://github.com/ocean90/media-modal-demo

bueltge bueltge
17 ago 2016 15:24:34
Todas las respuestas a la pregunta 6
2
48

Deberías usar wp.media para utilizar el cuadro de diálogo del Gestor de Medios de WordPress.

Primero, necesitas encolar los scripts:

// Como estás trabajando con ajustes del plugin,
// asumo que estás en el área de administración
add_action( 'admin_enqueue_scripts', 'load_wp_media_files' );
function load_wp_media_files( $page ) {
  // cambia a la $page donde quieras encolar el script
  if( $page == 'options-general.php' ) {
    // Encolar scripts de medios de WordPress
    wp_enqueue_media();
    // Encolar script personalizado que interactuará con wp.media
    wp_enqueue_script( 'myprefix_script', plugins_url( '/js/myscript.js' , __FILE__ ), array('jquery'), '0.1' );
  }
}

Tu HTML podría ser algo como esto (nota que mi código usa el ID del adjunto en el ajuste del plugin en lugar de la URL de la imagen como hiciste en tu respuesta, creo que es mucho mejor. Por ejemplo, usar el ID te permite obtener diferentes tamaños de imagen cuando los necesites):

$image_id = get_option( 'myprefix_image_id' );
if( intval( $image_id ) > 0 ) {
    // Cambia con el tamaño de imagen que quieras usar
    $image = wp_get_attachment_image( $image_id, 'medium', false, array( 'id' => 'myprefix-preview-image' ) );
} else {
    // Alguna imagen por defecto
    $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( 'Seleccionar una imagen', '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();
             }
             // Definir image_frame como objeto wp.media
             image_frame = wp.media({
                           title: 'Seleccionar Medio',
                           multiple : false,
                           library : {
                                type : 'image',
                            }
                       });

                       image_frame.on('close',function() {
                          // Al cerrar, obtener selecciones y guardar en el input oculto
                          // además de otras cosas AJAX para refrescar la vista previa de la imagen
                          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;//si se cierra sin seleccionar una imagen
                          jQuery('input#myprefix_image_id').val(ids);
                          Refresh_Image(ids);
                       });

                      image_frame.on('open',function() {
                        // Al abrir, obtener el ID del input oculto
                        // y seleccionar las imágenes apropiadas en el gestor de medios
                        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();
     });

});

// Solicitud Ajax para refrescar la vista previa de la imagen
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 );
            }
        });
}

Y la acción Ajax para refrescar la vista previa de la imagen:

// Acción Ajax para refrescar la imagen del usuario
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: es un ejemplo rápido escrito aquí basado en otra respuesta. No probado porque no proporcionaste suficiente información sobre el contexto exacto en el que se usará el código o los problemas exactos que tienes.

18 ago 2016 14:29:20
Comentarios

La llamada ajax get_image no es necesaria. El selection.models[0].attributes.url contiene la URL de la imagen seleccionada al cerrar el image_frame. Si deseas usar un tamaño específico, necesitarás la llamada ajax.

Bjorn Bjorn
17 abr 2020 20:48:30

¡Gracias! Un pequeño ajuste, creo que al "cerrar" no debería hacer ningún cambio en la imagen seleccionada, sino solo al "seleccionar".

Nikolay Nikolay
14 jun 2022 15:48:33
3

Fácil de usar, solo copia y pega el código en el lugar requerido

<?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="Vista previa de imagen" title="Vista previa de la imagen seleccionada">
        </div>
        <input id="upload_image_button" type="button" class="button" value="<?php _e( 'Subir imagen' ); ?>" />
        <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="Guardar" 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( $ ) {
            // Carga de archivos
            var file_frame;
            var wp_media_post_id = wp.media.model.settings.post.id; // Almacena el ID antiguo
            var set_to_post_id = <?php echo $my_saved_attachment_post_id; ?>; // Establece este
            jQuery('#upload_image_button').on('click', function( event ){
                event.preventDefault();
                // Si el marco de medios ya existe, reabrirlo
                if ( file_frame ) {
                    // Establecer el ID de publicación que queremos
                    file_frame.uploader.uploader.param( 'post_id', set_to_post_id );
                    // Abrir marco
                    file_frame.open();
                    return;
                } else {
                    // Establecer el ID de publicación de wp.media para que el cargador obtenga el ID deseado al inicializarse
                    wp.media.model.settings.post.id = set_to_post_id;
                }
                // Crear el marco de medios
                file_frame = wp.media.frames.file_frame = wp.media({
                    title: 'Selecciona una imagen para subir',
                    button: {
                        text: 'Usar esta imagen',
                    },
                    multiple: false // Establecer en true para permitir selección múltiple
                });
                // Cuando se selecciona una imagen, ejecutar una devolución de llamada
                file_frame.on( 'select', function() {
                    // Establecemos múltiple a false para obtener solo una imagen del cargador
                    attachment = file_frame.state().get('selection').first().toJSON();
                    // Hacer algo con attachment.id y/o attachment.url aquí
                    $( '#image-preview' ).attr( 'src', attachment.url ).css( 'width', 'auto' );
                    $( '#image_attachment_id' ).val( attachment.id );
                    // Restaurar el ID de publicación principal
                    wp.media.model.settings.post.id = wp_media_post_id;
                });
                    // Finalmente, abrir el modal
                    file_frame.open();
            });
            // Restaurar el ID principal cuando se presiona el botón agregar medios
            jQuery( 'a.add_media' ).on( 'click', function() {
                wp.media.model.settings.post.id = wp_media_post_id;
            });
        });
    </script>
6 ene 2018 07:35:32
Comentarios

¡Me salvaste la vida! :) Gracias

Freestyle09 Freestyle09
23 jun 2020 10:20:45

@LawrenceCherone ¿puedes ver mi código? Lo he actualizado

Rohit Kaushik Rohit Kaushik
14 ene 2021 08:49:30

Esto funciona bien. ¿Hay alguna forma de pasar una categoría al selector de la Biblioteca Multimedia?

TARKUS TARKUS
27 ago 2022 21:05:39
0

Así que esta respuesta funcionó perfectamente. Pero para hacerla reutilizable, convertí el código en una función. Entonces, para usar esto, primero debes revisar esto para enqueue el script. Y luego declarar wpOpenGallery así:

(function($) {
    $(document).ready(function() {
        const wpOpenGallery = function(o, callback) {
            const options = (typeof o === 'object') ? o : {};

            // Configuraciones predefinidas
            const defaultOptions = {
                title: 'Seleccionar medios',
                fileType: 'image',
                multiple: false,
                currentValue: '',
            };

            const opt = { ...defaultOptions, ...options };

            let image_frame;

            if(image_frame){
                image_frame.open();
            }

            // Define image_frame como objeto wp.media
            image_frame = wp.media({
                title: opt.title,
                multiple : opt.multiple,
                library : {
                    type : opt.fileType,
                }
            });

            image_frame.on('open',function() {
                // Al abrir, obtén el id del input oculto
                // y selecciona las imágenes apropiadas en el administrador de medios
                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() {
                // Al cerrar, obtén las selecciones y guárdalas en el input oculto
                // más otras cosas AJAX para actualizar la vista previa de la imagen
                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));

Y llámalo así:

wpOpenGallery(null, function(data) {
    console.log(data);
});
13 abr 2020 17:11:58
1

Utiliza wordpress-settings-api-class de Tareq Hasan, URL: https://github.com/tareq1988/wordpress-settings-api-class

16 ago 2016 17:07:15
Comentarios

Creo que una solución sin bibliotecas adicionales es mejor, más sólida; como el wp.media control.

bueltge bueltge
17 ago 2016 15:27:09
5

Como deseas que el ícono sea diferente para cada usuario, tendrás que almacenar la imagen en el perfil del usuario. Esto significa que necesitas agregar un campo de usuario adicional:

// crear el campo
add_action( 'show_user_profile', 'wpse_235406_chaticon' );
add_action( 'edit_user_profile', 'wpse_235406_chaticon' );

function wpse_235406_chaticon ($user) { 
    echo '
    <h3>Ícono de Chat</h3>
    <table class="form-table">
        <tr>
            <th><label for="chaticon">Ícono de 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">Por favor selecciona tu ícono de chat.</span>
            </td>
        </tr>
    </table>';
}

// guardar el 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']);
}

Ahora, esto te da la posibilidad de subir un archivo desde la computadora del usuario. Si deseas que el usuario seleccione el archivo de imágenes existentes, las cosas se complican más, porque entonces necesitas llamar a la biblioteca de medios en lugar de la carga de archivos predeterminada. Steven Slack ha escrito un excelente artículo sobre cómo hacer esto, cuyo código no quiero copiar y pegar aquí para no apropiarme del crédito.

En tu plantilla debes distinguir tres posibilidades: usuario no conectado, usuario conectado pero sin ícono, usuario conectado y con ícono. Básicamente, incluye esto:

$current_user = wp_get_current_user();
if ( 0 == $current_user->ID ) {
  ... haz lo que quieras hacer para usuarios no conectados ...
  }
else {
  $icon = get_user_meta ($current_user->ID, 'chaticon');
  if (empty($icon)) {
    ... ícono predeterminado con enlace a la posibilidad de subir uno ...
    }
  else {
     ... muestra $icon ...
     }
15 ago 2016 14:13:14
Comentarios

no, me gustaría que fuera una configuración del plugin

Thomas Thomas
15 ago 2016 14:20:05

¿Te refieres a que solo el administrador del sitio debería poder cambiar el icono y será el mismo para cada visitante/usuario?

cjbj cjbj
15 ago 2016 14:24:32

Eso sería bastante trivial. Aquí hay un tutorial para eso: https://mikejolley.com/2012/12/21/using-the-new-wordpress-3-5-media-uploader-in-plugins/

cjbj cjbj
15 ago 2016 14:28:13

sí, personaliza la apariencia (imagen) de un botón

Thomas Thomas
15 ago 2016 14:28:28

Probé el tutorial, pero no funciona para mí (¿obsoleto?) porque frames no es parte del objeto js

Thomas Thomas
16 ago 2016 10:08:50
7

Utilicé esta solución (sin usar directamente la Biblioteca de Medios):

Usando image-picker-lib dentro de un modal que establece el valor de un input oculto, el cual se envía a las opciones. Al obtener todos los medios y mostrarlos como opciones, permito que el usuario seleccione una imagen.

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">
    cambiar
</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">Elegir</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();
 +        });
16 ago 2016 17:23:29
Comentarios

Creo que una solución sin bibliotecas adicionales es mejor, sólida; como el wp.media control.

bueltge bueltge
17 ago 2016 15:26:54

@bueltge Estoy de acuerdo, pero nadie dio una respuesta directa y necesitaba una solución rápida. Así que si alguien da una gran respuesta, ¡se lleva la recompensa!

Thomas Thomas
17 ago 2016 15:40:01

Veo tu respuesta también como una solución, pero no la mejor manera. Ahora es parte del autor de la pregunta, tú ;), tomar la decisión.

bueltge bueltge
17 ago 2016 15:42:08

Esta solución puede convertirse rápidamente en un problema a medida que aumenta el número de imágenes. "nadie dio una respuesta directa" no es una excusa; tu pregunta es muy pobre, por eso obtienes respuestas pobres. No nos muestras ningún esfuerzo, investigación o código que hayas intentado, solo "quiero hacer esto, dame una solución lista para usar", que es lo mismo que "haz el trabajo por mí". Busca wp.media como sugirió bueltge; hay cientos de ejemplos aquí en WPSE. Si tienes problemas al usarlo, publica una nueva pregunta al respecto.

cybmeta cybmeta
18 ago 2016 13:19:49

@cybmeta lo intenté y este es mi mejor intento, así que no seas grosero al respecto. Si no te gusta, propón una mejor solución.

Thomas Thomas
18 ago 2016 13:27:57

wp.media es la mejor opción que tienes y eso es lo que propongo; intenta usarlo y, si tienes dudas al respecto, pregúntalas. He escrito varias respuestas sobre el uso de wp.media al igual que otras personas, intenta usar el cuadro de búsqueda (o Google), intenta tú mismo y publica preguntas sobre los problemas que puedas encontrar al usarlo. Lamento si mis comentarios te parecen malos, te quejaste de no obtener buenas respuestas, solo intenté explicarte por qué. Honestamente, creo que deberías tomar mi comentario sin ofenderte y aprender a evitar malas preguntas.

cybmeta cybmeta
18 ago 2016 13:44:20

Por cierto, cuando dije "no nos muestras ningún esfuerzo, investigación o código que hayas intentado" me refería a tu pregunta. Pensé que mi comentario era claro al respecto, tal vez no lo fue y debería haber publicado ese comentario en la pregunta y no en la respuesta. De todos modos, he añadido una respuesta; espero que te sea útil.

cybmeta cybmeta
18 ago 2016 17:49:20
Mostrar los 2 comentarios restantes