diff --git a/wp-admin/includes/ajax-actions.php b/wp-admin/includes/ajax-actions.php index b6dcca4bb5..5dbe74e23b 100644 --- a/wp-admin/includes/ajax-actions.php +++ b/wp-admin/includes/ajax-actions.php @@ -1611,12 +1611,12 @@ function wp_ajax_upload_attachment() { check_ajax_referer( 'media-form' ); if ( ! current_user_can( 'upload_files' ) ) - wp_die( -1 ); + wp_send_json_error(); if ( isset( $_REQUEST['post_id'] ) ) { $post_id = $_REQUEST['post_id']; if ( ! current_user_can( 'edit_post', $post_id ) ) - wp_die( -1 ); + wp_send_json_error(); } else { $post_id = null; } @@ -1626,14 +1626,10 @@ function wp_ajax_upload_attachment() { $attachment_id = media_handle_upload( 'async-upload', $post_id, $post_data ); if ( is_wp_error( $attachment_id ) ) { - echo json_encode( array( - 'type' => 'error', - 'data' => array( - 'message' => $attachment_id->get_error_message(), - 'filename' => $_FILES['async-upload']['name'], - ), + wp_send_json_error( array( + 'message' => $attachment_id->get_error_message(), + 'filename' => $_FILES['async-upload']['name'], ) ); - wp_die(); } if ( isset( $post_data['context'] ) && isset( $post_data['theme'] ) ) { @@ -1644,19 +1640,10 @@ function wp_ajax_upload_attachment() { update_post_meta( $attachment_id, '_wp_attachment_is_custom_header', $post_data['theme'] ); } - $post = get_post( $attachment_id ); + if ( ! $attachment = wp_prepare_attachment_for_js( $attachment_id ) ) + wp_send_json_error(); - echo json_encode( array( - 'type' => 'success', - 'data' => array( - 'id' => $attachment_id, - 'title' => esc_attr( $post->post_title ), - 'filename' => esc_html( basename( $post->guid ) ), - 'url' => wp_get_attachment_url( $attachment_id ), - 'meta' => wp_get_attachment_metadata( $attachment_id ), - ), - ) ); - wp_die(); + wp_send_json_success( $attachment ); } function wp_ajax_image_editor() { diff --git a/wp-admin/js/customize-controls.js b/wp-admin/js/customize-controls.js index 900ab13c01..12e0f16a7e 100644 --- a/wp-admin/js/customize-controls.js +++ b/wp-admin/js/customize-controls.js @@ -168,7 +168,7 @@ this.removerVisibility( this.setting.get() ); }, success: function( attachment ) { - this.setting.set( attachment.url ); + this.setting.set( attachment.get('url') ); }, removerVisibility: function( to ) { this.remover.toggle( to != this.params.removed ); @@ -272,9 +272,10 @@ if ( this.tabs.uploaded && this.tabs.uploaded.target.length ) { this.tabs.uploaded.both.removeClass('hidden'); + // @todo: Do NOT store this on the attachment model. That is bad. attachment.element = $( '' ) - .data( 'customizeImageValue', attachment.url ) - .append( '' ) + .data( 'customizeImageValue', attachment.get('url') ) + .append( '' ) .appendTo( this.tabs.uploaded.target ); } }, @@ -945,16 +946,16 @@ api.ImageControl.prototype.success.call( control, attachment ); data = { - attachment_id: attachment.id, - url: attachment.url, - thumbnail_url: attachment.url, - height: attachment.meta.height, - width: attachment.meta.width + attachment_id: attachment.get('id'), + url: attachment.get('url'), + thumbnail_url: attachment.get('url'), + height: attachment.get('height'), + width: attachment.get('width') }; attachment.element.data( 'customizeHeaderImageData', data ); control.settings.data.set( data ); - } + }; }); api.trigger( 'ready' ); diff --git a/wp-includes/js/media-views.js b/wp-includes/js/media-views.js index 032b5d85f2..49a33f750e 100644 --- a/wp-includes/js/media-views.js +++ b/wp-includes/js/media-views.js @@ -279,26 +279,14 @@ this.$content.append( this.attachmentsView.$el ); // Track uploading attachments. - this.pending = new Attachments( [], { query: false }); - this.pending.on( 'add remove reset change:percent', function() { - this.$el.toggleClass( 'uploading', !! this.pending.length ); - - if ( ! this.$bar || ! this.pending.length ) - return; - - this.$bar.width( ( this.pending.reduce( function( memo, attachment ) { - if ( attachment.get('uploading') ) - return memo + ( attachment.get('percent') || 0 ); - else - return memo + 100; - }, 0 ) / this.pending.length ) + '%' ); - }, this ); + wp.Uploader.queue.on( 'add remove reset change:percent', this.renderUploadProgress, this ); }, render: function() { this.attachmentsView.render(); + this.renderUploadProgress(); this.$el.html( this.template( this.options ) ).append( this.$content ); - this.$bar = this.$('.media-progress-bar div'); + this.$bar = this.$('.upload-attachments .media-progress-bar div'); return this; }, @@ -312,46 +300,26 @@ this.uploader = new wp.Uploader( _.extend({ container: this.$el, dropzone: this.$el, - browser: this.$('.upload-attachments a'), - - added: function( file ) { - file.attachment = Attachment.create( _.extend({ - file: file, - uploading: true, - date: new Date() - }, _.pick( file, 'loaded', 'size', 'percent' ) ) ); - - workspace.pending.add( file.attachment ); - }, - - progress: function( file ) { - file.attachment.set( _.pick( file, 'loaded', 'percent' ) ); - }, - - success: function( resp, file ) { - var complete; - - _.each(['file','loaded','size','uploading','percent'], function( key ) { - file.attachment.unset( key ); - }); - - file.attachment.set( 'id', resp.id ); - Attachment.get( resp.id, file.attachment ).fetch(); - - complete = workspace.pending.all( function( attachment ) { - return ! attachment.get('uploading'); - }); - - if ( complete ) - workspace.pending.reset(); - }, - - error: function( message, error, file ) { - file.attachment.destroy(); - } + browser: this.$('.upload-attachments a') }, this.options.uploader ) ); }, + renderUploadProgress: function() { + var queue = wp.Uploader.queue; + + this.$el.toggleClass( 'uploading', !! queue.length ); + + if ( ! this.$bar || ! queue.length ) + return; + + this.$bar.width( ( queue.reduce( function( memo, attachment ) { + if ( attachment.get('uploading') ) + return memo + ( attachment.get('percent') || 0 ); + else + return memo + 100; + }, 0 ) / queue.length ) + '%' ); + }, + // Initializes the toolbar view. Currently uses defaults set for // inserting media into a post. This should be pulled out into the // appropriate workflow when the time comes, but is currently here diff --git a/wp-includes/js/plupload/wp-plupload.js b/wp-includes/js/plupload/wp-plupload.js index e9ec49292a..31f21f6260 100644 --- a/wp-includes/js/plupload/wp-plupload.js +++ b/wp-includes/js/plupload/wp-plupload.js @@ -28,7 +28,7 @@ if ( typeof wp === 'undefined' ) browser: 'browse_button', dropzone: 'drop_element' }, - key; + key, error; this.supports = { upload: Uploader.browser.supported @@ -84,6 +84,12 @@ if ( typeof wp === 'undefined' ) this.param( this.params || {} ); delete this.params; + error = function( message, data, file ) { + if ( file.attachment ) + file.attachment.destroy(); + self.error( message, data, file ); + }; + this.uploader.init(); this.supports.dragdrop = this.uploader.features.dragdrop && ! Uploader.browser.mobile; @@ -134,26 +140,57 @@ if ( typeof wp === 'undefined' ) $('#' + this.uploader.id + '_html5_container').hide(); } + this.uploader.bind( 'FilesAdded', function( up, files ) { + _.each( files, function( file ) { + file.attachment = wp.media.model.Attachment.create( _.extend({ + file: file, + uploading: true, + date: new Date() + }, _.pick( file, 'loaded', 'size', 'percent' ) ) ); + + Uploader.queue.add( file.attachment ); + + self.added( file.attachment ); + }); + + up.refresh(); + up.start(); + }); + this.uploader.bind( 'UploadProgress', function( up, file ) { - self.progress( file ); + file.attachment.set( _.pick( file, 'loaded', 'percent' ) ); + self.progress( file.attachment ); }); this.uploader.bind( 'FileUploaded', function( up, file, response ) { + var complete; + try { response = JSON.parse( response.response ); } catch ( e ) { - return self.error( pluploadL10n.default_error, e ); + return error( pluploadL10n.default_error, e, file ); } - if ( ! response || ! response.type || ! response.data ) - return self.error( pluploadL10n.default_error ); + if ( ! _.isObject( response ) || _.isUndefined( response.success ) ) + return error( pluploadL10n.default_error, null, file ); + else if ( ! response.success ) + return error( response.data.message, response.data, file ); - if ( 'error' === response.type ) - return self.error( response.data.message, response.data, file ); + _.each(['file','loaded','size','uploading','percent'], function( key ) { + file.attachment.unset( key ); + }); - if ( 'success' === response.type ) - return self.success( response.data, file ); + file.attachment.set( response.data ); + wp.media.model.Attachment.get( response.data.id, file.attachment ); + complete = Uploader.queue.all( function( attachment ) { + return ! attachment.get('uploading'); + }); + + if ( complete ) + Uploader.queue.reset(); + + self.success( file.attachment ); }); this.uploader.bind( 'Error', function( up, error ) { @@ -168,19 +205,10 @@ if ( typeof wp === 'undefined' ) } } - self.error( message, error, error.file ); + error( message, error, error.file ); up.refresh(); }); - this.uploader.bind( 'FilesAdded', function( up, files ) { - $.each( files, function() { - self.added( this ); - }); - - up.refresh(); - up.start(); - }); - this.init(); }; @@ -237,5 +265,7 @@ if ( typeof wp === 'undefined' ) } }); + Uploader.queue = new wp.media.model.Attachments( [], { query: false }); + exports.Uploader = Uploader; })( wp, jQuery ); diff --git a/wp-includes/script-loader.php b/wp-includes/script-loader.php index 5fdc7e5335..6a03efeb29 100644 --- a/wp-includes/script-loader.php +++ b/wp-includes/script-loader.php @@ -232,7 +232,7 @@ function wp_default_scripts( &$scripts ) { $scripts->add( 'plupload-handlers', "/wp-includes/js/plupload/handlers$suffix.js", array('plupload-all', 'jquery') ); did_action( 'init' ) && $scripts->localize( 'plupload-handlers', 'pluploadL10n', $uploader_l10n ); - $scripts->add( 'wp-plupload', "/wp-includes/js/plupload/wp-plupload$suffix.js", array('plupload-all', 'jquery', 'json2') ); + $scripts->add( 'wp-plupload', "/wp-includes/js/plupload/wp-plupload$suffix.js", array('plupload-all', 'jquery', 'json2', 'media-models'), false, 1 ); did_action( 'init' ) && $scripts->localize( 'wp-plupload', 'pluploadL10n', $uploader_l10n ); // keep 'swfupload' for back-compat.