Plupload Intergration in einer Meta-Box?

32

Ich weiß, dass plupload die neue Upload-Engine für WordPress 3.3 sein wird, aber ich habe mich gefragt, ob es noch Unterlagen zur Integration in WordPress gibt.

Wie kann ich eine Antwort vom plUpload jQuery-Objekt erfassen, nachdem es die gewünschten Medien hochgeladen hat, und wie kann ich dieselbe Funktionalität in einer Meta-Box zum Erstellen einer Galerie verwenden?

Hat schon jemand damit gespielt?

Manny Fleurmond
quelle
Danke für das Kopfgeld, obwohl es eine gute Chance gibt, dass eine Antwort nicht kommt, bis WordPress 3.3 eine offizielle Veröffentlichung hat
Manny Fleurmond,
3
Es ist auch eine gute Chance , dass ich es an diesem Wochenende einen Blick darauf werfen werde :-) Ich bin jetzt seit Monaten 3.3 wurde verwendet und müssen genau dieses Ding zu schreiben , bevor der erste RC fällt ...
EAMann
Hier ist ein Link zum jQuery-Plugin, das der neue Uploader verwendet: plupload ( plupload.com ). Ich verstehe, wie sie es implementieren, kann aber nicht sagen, wie die neue Implementierung Antworten erhält, wenn eine Datei erfolgreich hochgeladen wurde.
Manny Fleurmond

Antworten:

18

Wie kann ich eine Antwort vom plUpload jQuery-Objekt erfassen, nachdem es die gewünschten Medien hochgeladen hat, und wie kann ich dieselbe Funktionalität in einer Meta-Box zum Erstellen einer Galerie verwenden?

Es gibt eine bestimmte Datei, die diese Funktionalität behandelt: /wp-includes/js/plupload/handlers.dev.js . Diese Datei enthält alle Hooks und Trigger, die Plupload (das Drag & Drop-Multi-File-System eines Drittanbieters) mit dem Uploader verbinden.

Es gibt zwei Ereignisse, die Sie sich ansehen sollten: "FileUploaded" und "Upload Complete"

Datei hochgeladen

Denken Sie daran, dass der neue Uploader mehrere Dateien gleichzeitig hochladen kann. Wenn Sie also nach dem Hochladen jeder Datei in der Warteschlange etwas tun möchten, verwenden Sie jQuery, um eine Bindung an dieses Ereignis herzustellen.

WordPress bindet beispielsweise Folgendes:

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

Das uploadSuccess Funktion hier verarbeitet Miniaturansichten von Bildern, ruft Meta-Anhänge vom Server ab und bindet die Schaltflächen zum Bearbeiten / Löschen an das richtige Objekt.

UploadComplete

Das UploadComplete-Ereignis wird nach allem ausgelöst in der Warteschlange fertig Upload ist. Wenn Sie einen allgemeinen Bereinigungsvorgang starten möchten, nachdem der gesamte Download abgeschlossen ist, ist dies das, woran Sie binden möchten.

WordPress bindet beispielsweise Folgendes:

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

Die uploadCompleteFunktion hier aktiviert nur die Schaltfläche "Galerie einfügen" auf der Seite.

Unglücklicherweise ...

... es scheint keine Möglichkeit für uns zu geben, uns an diese Ereignisse zu binden. Das uploaderObjekt befindet sich innerhalb eines Abschlusses in der handlers.jsDatei, und Plupload selbst kann nicht auf vorhandene Instanzen verweisen. Sie können keinen einfachen jQuery-Selektor verwenden, um ein benutzerdefiniertes Ereignis hinzuzufügen.

Zum einen können Sie diese benutzerdefinierten Ereignisse beliebig in Ihren eigenen Systemen verwenden. Drehen Sie einfach Ihre eigene Version vonhandlers.jsStellen Sie einfach Datei mit Ihren eigenen Ereignissen zusammen und Sie können tun, was Sie wollen. Für den vorhandenen Uploader bleibt jedoch die vorhandene API erhalten.

Beachten Sie, dass der neue Pluploader die gleichen Methoden wie der alte Flash-Uploader aufruft. Ich vermute also, dass alle vorhandenen Hacks oder Integrationen, die Sie haben, weiter funktionieren sollten.

Testen Sie diese Annahme

Ich habe ein Plugin , das den vorhandenen Uploader verwendet, um Dateianhänge hochzuladen und die URL in einem benutzerdefinierten Metafeld anzuzeigen. Mit dem alten Uploader hat es wie durch Zauberhand geklappt, also habe ich es in WP 3.3 gestartet, um zu sehen, ob es auch mit dem neuen Uploader funktioniert .

Und das tut es!

Wenn Sie sich bereits in den Media Uploader integrieren, sollte Ihr System dennoch ohne Änderungen mit dem neuen System funktionieren.

EAMann
quelle
22

(Dies ist nur ein praktisches Beispiel, das auf der Antwort von EAMann basiert.)

// 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;
});

Es gibt weitere Upload-Ereignisse, die Sie verwenden können. Lesen Sie die Dokumentation ...

ein Trickpony
quelle
Ich habe diesen Code so wie er ist ausprobiert und bisher macht er nichts. Das Bild scheint hochgeladen zu werden, aber ich weiß nicht, wo und ich bekomme keine Antwort von der Konsole
Manny Fleurmond
1
Okay, ich habe das Problem gefunden: Aus irgendeinem Grund scheint die Funktion $ _FILES ['async-upload'], die Sie an wp_handle_upload gesendet haben, keinen Check in dieser Funktion zu bestehen. Wenn Sie ein Array ('test_form' => false) als zweites Argument an wp_handle_upload übergeben, wird die Datei problemlos hochgeladen. Der Aufruf von add_meta_box enthält außerdem zusätzliche Klammern. Ich habe Ihrer Antwort Änderungen hinzugefügt, damit es funktioniert.
Manny Fleurmond
Als Implementierungsnotiz - kann eine Aktion festlegen, upload-attachmentdie den nativen wp_ajax_upload_attachment()Handler auslöst, und mit einigen Optimierungen muss der benutzerdefinierte Upload-Handler insgesamt nicht verwendet werden, sondern nur der Formular- und der Skriptteil.
Rarst
13

Hier ist eine Erweiterung der Antwort von @One Trick Pony. Zusätzlich zum Hochladen der Datei in den richtigen Ordner wird die Datei auch als Anhang gespeichert:

<?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
quelle
1
Denke, hier liegt ein kleiner Fehler vor - der letzte Parameter des Aufrufs von wp_insert_attachment sollte $ status ['file'] und nicht $ status ['url'] sein. Ich bin mir ziemlich sicher, dass es der lokale Pfad sein muss.
MathSmath