¿Integración de Plupload en un meta-box?

32

Sé que plupload será el nuevo motor de carga para WordPress 3.3, pero me preguntaba si todavía hay documentación sobre cómo se integra con WordPress.

¿Específicamente cómo recopilar una respuesta del objeto plUpload jQuery una vez que ha cargado los medios que desea y cómo se usaría la misma funcionalidad en un meta cuadro para crear una galería?

¿Alguien ha jugado con eso todavía?

Manny Fleurmond
fuente
Gracias por la recompensa, aunque hay una buena posibilidad de que no llegue una respuesta hasta que WordPress 3.3 tenga un lanzamiento oficial
Manny Fleurmond
3
También hay una buena posibilidad de que lo vea este fin de semana :-) He estado usando 3.3 durante meses y necesito escribir esto exactamente antes de que caiga el primer RC ...
EAMann
Aquí hay un enlace al complemento jQuery que usa el nuevo cargador, plupload ( plupload.com ). Tengo la idea de cómo lo implementan, pero no puedo decir cómo la nueva implementación recibe respuestas cuando un archivo se carga correctamente.
Manny Fleurmond

Respuestas:

18

¿Específicamente cómo recopilar una respuesta del objeto plUpload jQuery una vez que ha subido los medios que desea y cómo se usaría la misma funcionalidad en un meta cuadro para crear una galería?

Hay un archivo específico que se encarga de esta función: /wp-includes/js/plupload/handlers.dev.js. Este archivo contiene todos los ganchos y disparadores que vinculan Plupload (el sistema de archivos múltiples de arrastrar / soltar de terceros) al cargador.

Es posible que desee ver dos eventos: "FileUploaded" y "Upload Complete"

Archivo subido

Recuerde, el nuevo cargador es capaz de cargar múltiples archivos a la vez. Entonces, si hay algo que desea hacer después de cargar cada archivo en la cola, usará jQuery para vincular este evento.

WordPress, por ejemplo, une lo siguiente:

uploader.bind('FileUploaded', function(up, file, response) {
    uploadSuccess(file, response.response);
});'

La uploadSuccessfunción aquí maneja las miniaturas de las imágenes, recupera metadatos de archivos adjuntos del servidor y vincula los botones de edición / eliminación al objeto correcto.

Carga completa

El evento UploadComplete se activará después de que todo en la cola haya terminado de cargarse. Si desea iniciar una operación de limpieza general después de que termine la descarga completa, esto es a lo que querrá unirse.

WordPress, por ejemplo, une lo siguiente:

uploader.bind('UploadComplete', function(up, files) {
    uploadComplete();
});

La uploadCompletefunción aquí solo habilita el botón "Insertar galería" en la página.

Desafortunadamente ...

... no parece haber una forma de vincularnos con estos eventos. El uploaderobjeto existe dentro de un cierre en el handlers.jsarchivo, y Plupload en sí no tiene una forma de hacer referencia a instancias existentes. No puede usar un simple selector jQuery para detectarlo y agregar un evento personalizado ... así que no tenemos suerte allí.

Por un lado, puede usar estos eventos personalizados a voluntad en sus propios sistemas. Simplemente handlers.jshaga girar su propia versión del archivo con sus propios eventos y podrá hacer lo que quiera. Pero para el cargador existente, estás atascado con la API existente.

Tenga en cuenta que el nuevo Pluploader llama a los mismos métodos al mismo tiempo que el antiguo cargador de Flash. Entonces, mi mejor conjetura es que cualquier pirateo o integración existente que tenga debe continuar funcionando.

Probar esa suposición

Tengo un complemento que usa el cargador existente para cargar archivos adjuntos y mostrar la URL en un metacampo personalizado. Funcionó como magia con el viejo cargador, así que lo activé en WP 3.3 para ver si también funcionaba con el nuevo cargador.

Y lo hace!

Entonces, si ya se está integrando con el cargador de medios, su sistema aún debería funcionar con el nuevo sistema sin ningún cambio.

EAMann
fuente
22

(este es solo un ejemplo práctico basado en la respuesta de EAMann)

// include js
add_action('admin_enqueue_scripts', function($page){

  // check if this your page here with the upload form!
  if(($page !== 'post.php') || (get_post_type() !== 'post'))
    return;

  wp_enqueue_script('plupload-all');
});



// this adds a simple metabox with the upload form on the edit-post page
add_action('add_meta_boxes', function(){
  add_meta_box('gallery_photos', __('Photos'), 'upload_meta_box', 'post', 'normal', 'high');

});                                               



// so here's the actual uploader
// most of the code comes from media.php and handlers.js
function upload_meta_box(){ ?>
   <div id="plupload-upload-ui" class="hide-if-no-js">
     <div id="drag-drop-area">
       <div class="drag-drop-inside">
        <p class="drag-drop-info"><?php _e('Drop files here'); ?></p>
        <p><?php _ex('or', 'Uploader: Drop files here - or - Select Files'); ?></p>
        <p class="drag-drop-buttons"><input id="plupload-browse-button" type="button" value="<?php esc_attr_e('Select Files'); ?>" class="button" /></p>
      </div>
     </div>
  </div>

  <?php

  $plupload_init = array(
    'runtimes'            => 'html5,silverlight,flash,html4',
    'browse_button'       => 'plupload-browse-button',
    'container'           => 'plupload-upload-ui',
    'drop_element'        => 'drag-drop-area',
    'file_data_name'      => 'async-upload',            
    'multiple_queues'     => true,
    'max_file_size'       => wp_max_upload_size().'b',
    'url'                 => admin_url('admin-ajax.php'),
    'flash_swf_url'       => includes_url('js/plupload/plupload.flash.swf'),
    'silverlight_xap_url' => includes_url('js/plupload/plupload.silverlight.xap'),
    'filters'             => array(array('title' => __('Allowed Files'), 'extensions' => '*')),
    'multipart'           => true,
    'urlstream_upload'    => true,

    // additional post data to send to our ajax hook
    'multipart_params'    => array(
      '_ajax_nonce' => wp_create_nonce('photo-upload'),
      'action'      => 'photo_gallery_upload',            // the ajax action name
    ),
  );

  // we should probably not apply this filter, plugins may expect wp's media uploader...
  $plupload_init = apply_filters('plupload_init', $plupload_init); ?>

  <script type="text/javascript">

    jQuery(document).ready(function($){

      // create the uploader and pass the config from above
      var uploader = new plupload.Uploader(<?php echo json_encode($plupload_init); ?>);

      // checks if browser supports drag and drop upload, makes some css adjustments if necessary
      uploader.bind('Init', function(up){
        var uploaddiv = $('#plupload-upload-ui');

        if(up.features.dragdrop){
          uploaddiv.addClass('drag-drop');
            $('#drag-drop-area')
              .bind('dragover.wp-uploader', function(){ uploaddiv.addClass('drag-over'); })
              .bind('dragleave.wp-uploader, drop.wp-uploader', function(){ uploaddiv.removeClass('drag-over'); });

        }else{
          uploaddiv.removeClass('drag-drop');
          $('#drag-drop-area').unbind('.wp-uploader');
        }
      });

      uploader.init();

      // a file was added in the queue
      uploader.bind('FilesAdded', function(up, files){
        var hundredmb = 100 * 1024 * 1024, max = parseInt(up.settings.max_file_size, 10);

        plupload.each(files, function(file){
          if (max > hundredmb && file.size > hundredmb && up.runtime != 'html5'){
            // file size error?

          }else{

            // a file was added, you may want to update your DOM here...
            console.log(file);
          }
        });

        up.refresh();
        up.start();
      });

      // a file was uploaded 
      uploader.bind('FileUploaded', function(up, file, response) {

        // this is your ajax response, update the DOM with it or something...
        console.log(response);

      });

    });   

  </script>
  <?php
}


// handle uploaded file here
add_action('wp_ajax_photo_gallery_upload', function(){

  check_ajax_referer('photo-upload');

  // you can use WP's wp_handle_upload() function:
  $status = wp_handle_upload($_FILES['async-upload'], array('test_form'=>true, 'action' => 'photo_gallery_upload'));

  // and output the results or something...
  echo 'Uploaded to: '.$status['url'];

  exit;
});

Hay más eventos plupload que puede usar, consulte su documentación ...

Pony de un solo truco
fuente
He intentado este código tal cual y hasta ahora no hace nada. La imagen parece subir pero no sé dónde y no recibo respuesta de la consola
Manny Fleurmond
1
Bien, encontré el problema: por alguna razón, el $ _FILES ['async-upload'] que envió a wp_handle_upload no parece pasar un cheque en dicha función. Si pasa array ('test_form' => false) como segundo argumento en wp_handle_upload, carga el archivo sin problemas. También hay paréntesis adicionales en la llamada a add_meta_box. Agregué ediciones a su respuesta que deberían hacerlo funcionar.
Manny Fleurmond
Como nota de implementación: puede establecer una acción para upload-attachmentactivar el wp_ajax_upload_attachment()controlador nativo y, con algunos ajustes, no necesita un controlador de carga personalizado, solo las partes del formulario y el script.
Rarst
13

Aquí hay una expansión de la respuesta de @One Trick Pony. Esto, además de cargar el archivo en el correcto, también guardará dicho archivo como un archivo adjunto:

<?php
// include js
add_action('admin_enqueue_scripts', function($page){

  // check if this your page here with the upload form!
  if(($page !== 'post.php') || (get_post_type() !== 'post'))
    return;

  wp_enqueue_script('plupload-all');
});



// this adds a simple metabox with the upload form on the edit-post page
add_action('add_meta_boxes', function(){
  add_meta_box('gallery_photos', __('Photos'), 'upload_meta_box', 'post', 'normal', 'high');

});                                               



// so here's the actual uploader
// most of the code comes from media.php and handlers.js
function upload_meta_box(){ ?>
   <div id="plupload-upload-ui" class="hide-if-no-js">
     <div id="drag-drop-area">
       <div class="drag-drop-inside">
        <p class="drag-drop-info"><?php _e('Drop files here'); ?></p>
        <p><?php _ex('or', 'Uploader: Drop files here - or - Select Files'); ?></p>
        <p class="drag-drop-buttons"><input id="plupload-browse-button" type="button" value="<?php esc_attr_e('Select Files'); ?>" class="button" /></p>
      </div>
     </div>
  </div>

  <?php

  $plupload_init = array(
    'runtimes'            => 'html5,silverlight,flash,html4',
    'browse_button'       => 'plupload-browse-button',
    'container'           => 'plupload-upload-ui',
    'drop_element'        => 'drag-drop-area',
    'file_data_name'      => 'async-upload',            
    'multiple_queues'     => true,
    'max_file_size'       => wp_max_upload_size().'b',
    'url'                 => admin_url('admin-ajax.php'),
    'flash_swf_url'       => includes_url('js/plupload/plupload.flash.swf'),
    'silverlight_xap_url' => includes_url('js/plupload/plupload.silverlight.xap'),
    'filters'             => array(array('title' => __('Allowed Files'), 'extensions' => '*')),
    'multipart'           => true,
    'urlstream_upload'    => true,

    // additional post data to send to our ajax hook
    'multipart_params'    => array(
      '_ajax_nonce' => wp_create_nonce('photo-upload'),
      'action'      => 'photo_gallery_upload',            // the ajax action name
    ),
  );

  // we should probably not apply this filter, plugins may expect wp's media uploader...
  $plupload_init = apply_filters('plupload_init', $plupload_init); ?>

  <script type="text/javascript">

    jQuery(document).ready(function($){

      // create the uploader and pass the config from above
      var uploader = new plupload.Uploader(<?php echo json_encode($plupload_init); ?>);

      // checks if browser supports drag and drop upload, makes some css adjustments if necessary
      uploader.bind('Init', function(up){
        var uploaddiv = $('#plupload-upload-ui');

        if(up.features.dragdrop){
          uploaddiv.addClass('drag-drop');
            $('#drag-drop-area')
              .bind('dragover.wp-uploader', function(){ uploaddiv.addClass('drag-over'); })
              .bind('dragleave.wp-uploader, drop.wp-uploader', function(){ uploaddiv.removeClass('drag-over'); });

        }else{
          uploaddiv.removeClass('drag-drop');
          $('#drag-drop-area').unbind('.wp-uploader');
        }
      });

      uploader.init();

      // a file was added in the queue
      uploader.bind('FilesAdded', function(up, files){
        var hundredmb = 100 * 1024 * 1024, max = parseInt(up.settings.max_file_size, 10);

        plupload.each(files, function(file){
          if (max > hundredmb && file.size > hundredmb && up.runtime != 'html5'){
            // file size error?

          }else{

            // a file was added, you may want to update your DOM here...
            console.log(file);
          }
        });

        up.refresh();
        up.start();
      });

      // a file was uploaded 
      uploader.bind('FileUploaded', function(up, file, response) {

        // this is your ajax response, update the DOM with it or something...
        console.log(response);

      });

    });   

  </script>
  <?php
}


// handle uploaded file here
add_action('wp_ajax_photo_gallery_upload', function(){

  check_ajax_referer('photo-upload');

  // you can use WP's wp_handle_upload() function:
  $file = $_FILES['async-upload'];
  $status = wp_handle_upload($file, array('test_form'=>true, 'action' => 'photo_gallery_upload'));

  // and output the results or something...
  echo 'Uploaded to: '.$status['url'];

  //Adds file as attachment to WordPress
  echo "\n Attachment ID: " .wp_insert_attachment( array(
     'post_mime_type' => $status['type'],
     'post_title' => preg_replace('/\.[^.]+$/', '', basename($file['name'])),
     'post_content' => '',
     'post_status' => 'inherit'
  ), $status['file']);

  exit;
});
?>
Manny Fleurmond
fuente
1
Cree que hay un pequeño error aquí: el último parámetro de la llamada wp_insert_attachment debería ser $ status ['archivo'] en lugar de $ status ['url']. Estoy bastante seguro de que debe ser el camino local.
MathSmath