Integração Plupload em uma meta-caixa?

32

Eu sei que o plupload será o novo mecanismo de upload do WordPress 3.3, mas eu queria saber se ainda existe alguma documentação sobre como ele se integra ao WordPress.

Meu especificamente como coletar uma resposta do objeto plUpload jQuery depois que ele carregou a mídia que você deseja e como alguém usaria a mesma funcionalidade em uma meta box para criar uma galeria?

Alguém já brincou com isso ainda?

Manny Fleurmond
fonte
Agradecimentos para a recompensa, embora haja uma boa chance de uma resposta não virá até WordPress 3.3 tem uma versão oficial
Manny Fleurmond
3
Há também uma boa chance de dar uma olhada neste final de semana :-) Estou usando o 3.3 há meses e preciso escrever exatamente isso antes que o primeiro RC caia ...
EAMann
Aqui está um link para o plugin jQuery que o novo remetente usa, plupload ( plupload.com ). Eu tenho a essência de como eles a implementam, mas não posso dizer como a nova implementação recebe respostas quando um arquivo é carregado com êxito.
Manny Fleurmond

Respostas:

18

Meu especificamente como coletar uma resposta do objeto plUpload jQuery depois que ele carregou a mídia que você deseja e como alguém usaria a mesma funcionalidade em uma meta box para criar uma galeria?

Há um arquivo específico que lida com esta funcionalidade: /wp-includes/js/plupload/handlers.dev.js. Este arquivo contém todos os ganchos e gatilhos que vinculam o Plupload (o sistema de vários arquivos de arrastar / soltar de terceiros) ao remetente.

Há dois eventos que você pode querer assistir: "FileUploaded" e "Upload Complete"

FileUploaded

Lembre-se de que o novo remetente é capaz de carregar vários arquivos de uma só vez. Portanto, se houver algo que você queira fazer após o upload de cada arquivo na fila, você usará o jQuery para vincular a esse evento.

O WordPress, por exemplo, vincula o seguinte:

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

A uploadSuccessfunção aqui lida com miniaturas de imagens, busca a meta de anexo do servidor e vincula os botões de edição / exclusão ao objeto certo.

Envio completo

O evento UploadComplete será acionado após o término do upload de tudo na fila. Se você deseja acionar uma operação de limpeza geral após a conclusão do download inteiro, é nisso que você deseja se associar.

O WordPress, por exemplo, vincula o seguinte:

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

A uploadCompletefunção aqui apenas ativa o botão "Inserir galeria" na página.

Infelizmente ...

... parece não haver uma maneira de nos vincularmos a esses eventos. O uploaderobjeto existe dentro de um fechamento no handlers.jsarquivo e o próprio Plupload não tem como referenciar instâncias existentes. Você não pode usar um simples seletor de jQuery para farejá-lo e adicionar um evento personalizado ... por isso estamos sem sorte lá.

Por um lado, você pode usar esses eventos personalizados à vontade em seus próprios sistemas. Basta girar sua própria versão do handlers.jsarquivo com seus próprios eventos e você poderá fazer o que quiser. Mas para o remetente existente, você está preso à API existente.

Lembre-se de que o novo Pluploader chama os mesmos métodos nos mesmos horários que o antigo Flash Uploader. Portanto, meu melhor palpite é que todos os hacks ou integrações existentes devem continuar funcionando.

Testando essa suposição

Eu tenho um plug-in que usa o remetente existente para fazer upload de anexos de arquivo e exibir o URL em um meta-campo personalizado. Funcionou como mágica com o uploader antigo, então eu o iniciei no WP 3.3 para ver se funcionava com o novo uploader.

E faz!

Portanto, se você já estiver se integrando ao carregador de mídia, seu sistema ainda deverá funcionar com o novo sistema sem nenhuma alteração.

EAMann
fonte
22

(este é apenas um exemplo prático baseado na resposta da 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;
});

Existem mais eventos do plupload que você pode usar, confira a documentação ....

onetrickpony
fonte
Eu tentei esse código como está e até agora ele não faz nada. A imagem parece carregar, mas eu não sei onde e eu não obter resposta do console
Manny Fleurmond
1
Ok, encontrei o problema: por algum motivo, o $ _FILES ['async-upload'] que você enviou para o wp_handle_upload parece não passar na verificação da referida função. Se você passar a matriz ('test_form' => false) como um segundo argumento para wp_handle_upload, ela fará o upload do arquivo sem problemas. Também há parênteses extras na chamada para add_meta_box. Adicionei edições à sua resposta, o que deve fazer com que ela funcione.
Manny Fleurmond
Como uma nota de implementação - pode definir uma ação para a upload-attachmentqual acionará o wp_ajax_upload_attachment()manipulador nativo e, com alguns ajustes, não precisará totalmente do manipulador de upload personalizado, apenas as partes do formulário e do script.
Rarst
13

Aqui está uma expansão da resposta do @One Trick Pony. Além de fazer o upload do arquivo, isso também salvará o arquivo como um anexo:

<?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
fonte
1
Pense que há um pequeno erro aqui - o último parâmetro da chamada wp_insert_attachment deve ser $ status ['file'] em vez de $ status ['url']. Certamente ele precisa ser o caminho local.
MathSmath