Merge "[search] Fix method call on null value"
[lhc/web/wiklou.git] / resources / src / mediawiki / mediawiki.Upload.BookletLayout.js
index cb532c3..c616829 100644 (file)
         *
         * @constructor
         * @param {Object} config Configuration options
+        * @cfg {jQuery} [$overlay] Overlay to use for widgets in the booklet
         */
        mw.Upload.BookletLayout = function ( config ) {
                // Parent constructor
                mw.Upload.BookletLayout.parent.call( this, config );
 
+               this.$overlay = config.$overlay;
+
                this.renderUploadForm();
                this.renderInfoForm();
                this.renderInsertForm();
         * The file has been saved to the database
         *
         * @event fileSaved
+        * @param {Object} imageInfo See mw.Upload#getImageInfo
         */
 
        /**
 
        /**
         * Initialize for a new upload
+        *
+        * @return {jQuery.Promise} Promise resolved when everything is initialized
         */
        mw.Upload.BookletLayout.prototype.initialize = function () {
                this.clear();
                this.upload = this.createUpload();
                this.setPage( 'upload' );
+               return $.Deferred().resolve().promise();
        };
 
        /**
         * @return {jQuery.Promise}
         */
        mw.Upload.BookletLayout.prototype.uploadFile = function () {
-               var file = this.getFile();
+               var deferred = $.Deferred(),
+                       layout = this,
+                       file = this.getFile();
 
                this.filenameWidget.setValue( file.name );
                this.setPage( 'info' );
 
                this.upload.setFile( file );
+               // Explicitly set the filename so that the old filename isn't used in case of retry
+               this.upload.setFilenameFromFile();
+
                this.uploadPromise = this.upload.uploadToStash();
-               this.uploadPromise.then( this.emit.bind( this, 'fileUploaded' ) );
+               this.uploadPromise.then( function () {
+                       deferred.resolve();
+                       layout.emit( 'fileUploaded' );
+               }, function () {
+                       // These errors will be thrown while the user is on the info page.
+                       // Pretty sure it's impossible to get a warning other than 'stashfailed' here, which should
+                       // really be an error...
+                       var errorMessage = layout.getErrorMessageForStateDetails();
+                       deferred.reject( errorMessage );
+               } );
 
-               return this.uploadPromise;
+               // If there is an error in uploading, come back to the upload page
+               deferred.fail( function () {
+                       layout.setPage( 'upload' );
+               } );
+
+               return deferred;
        };
 
        /**
                this.upload.setFilename( this.getFilename() );
                this.upload.setText( this.getText() );
 
-               this.uploadPromise.always( function () {
-
-                       if ( layout.upload.getState() === mw.Upload.State.ERROR ) {
-                               deferred.reject( new OO.ui.Error( mw.msg( 'upload-process-error' )  ) );
-                               return false;
-                       }
-
-                       if ( layout.upload.getState() === mw.Upload.State.WARNING ) {
-                               deferred.reject( new OO.ui.Error( mw.msg( 'upload-process-error' )  ) );
-                               return false;
-                       }
-
-                       layout.upload.finishStashUpload().always( function () {
+               this.uploadPromise.then( function () {
+                       layout.upload.finishStashUpload().then( function () {
                                var name;
 
-                               if ( layout.upload.getState() === mw.Upload.State.ERROR ) {
-                                       deferred.reject( new OO.ui.Error( mw.msg( 'upload-process-error' ) ) );
-                                       return false;
-                               }
-
-                               if ( layout.upload.getState() === mw.Upload.State.WARNING ) {
-                                       deferred.reject( new OO.ui.Error( mw.msg( 'upload-process-warning' ) ) );
-                                       return false;
-                               }
-
                                // Normalize page name and localise the 'File:' prefix
                                name = new mw.Title( 'File:' + layout.upload.getFilename() ).toString();
                                layout.filenameUsageWidget.setValue( '[[' + name + ']]' );
                                layout.setPage( 'insert' );
 
                                deferred.resolve();
-                               layout.emit( 'fileSaved' );
+                               layout.emit( 'fileSaved', layout.upload.getImageInfo() );
+                       }, function () {
+                               var errorMessage = layout.getErrorMessageForStateDetails();
+                               deferred.reject( errorMessage );
                        } );
                } );
 
                return deferred.promise();
        };
 
+       /**
+        * Get an error message (as OO.ui.Error object) that should be displayed to the user for current
+        * state and state details.
+        *
+        * @protected
+        * @returns {OO.ui.Error} Error to display for given state and details.
+        */
+       mw.Upload.BookletLayout.prototype.getErrorMessageForStateDetails = function () {
+               var message,
+                       state = this.upload.getState(),
+                       stateDetails = this.upload.getStateDetails(),
+                       error = stateDetails.error,
+                       warnings = stateDetails.upload && stateDetails.upload.warnings;
+
+               if ( state === mw.Upload.State.ERROR ) {
+                       // HACK We should either have a hook here to allow TitleBlacklist to handle this, or just have
+                       // TitleBlacklist produce sane error messages that can be displayed without arcane knowledge
+                       if ( error.info === 'TitleBlacklist prevents this title from being created' ) {
+                               // HACK Apparently the only reliable way to determine whether TitleBlacklist was involved
+                               return new OO.ui.Error(
+                                       $( '<p>' ).html(
+                                               // HACK TitleBlacklist doesn't have a sensible message, this one is from UploadWizard
+                                               mw.message( 'api-error-blacklisted' ).parse()
+                                       ),
+                                       { recoverable: false }
+                               );
+                       }
+
+                       message = mw.message( 'api-error-' + error.code );
+                       if ( !message.exists() ) {
+                               message = mw.message( 'api-error-unknownerror', JSON.stringify( stateDetails ) );
+                       }
+                       return new OO.ui.Error(
+                               $( '<p>' ).html(
+                                       message.parse()
+                               ),
+                               { recoverable: false }
+                       );
+               }
+
+               if ( state === mw.Upload.State.WARNING ) {
+                       // We could get more than one of these errors, these are in order
+                       // of importance. For example fixing the thumbnail like file name
+                       // won't help the fact that the file already exists.
+                       if ( warnings.stashfailed !== undefined ) {
+                               return new OO.ui.Error(
+                                       $( '<p>' ).html(
+                                               mw.message( 'api-error-stashfailed' ).parse()
+                                       ),
+                                       { recoverable: false }
+                               );
+                       } else if ( warnings.exists !== undefined ) {
+                               return new OO.ui.Error(
+                                       $( '<p>' ).html(
+                                               mw.message( 'fileexists', 'File:' + warnings.exists ).parse()
+                                       ),
+                                       { recoverable: false }
+                               );
+                       } else if ( warnings[ 'page-exists' ] !== undefined ) {
+                               return new OO.ui.Error(
+                                       $( '<p>' ).html(
+                                               mw.message( 'filepageexists', 'File:' + warnings[ 'page-exists' ] ).parse()
+                                       ),
+                                       { recoverable: false }
+                               );
+                       } else if ( warnings.duplicate !== undefined ) {
+                               return new OO.ui.Error(
+                                       $( '<p>' ).html(
+                                               mw.message( 'api-error-duplicate', warnings.duplicate.length ).parse()
+                                       ),
+                                       { recoverable: false }
+                               );
+                       } else if ( warnings[ 'thumb-name' ] !== undefined ) {
+                               return new OO.ui.Error(
+                                       $( '<p>' ).html(
+                                               mw.message( 'filename-thumb-name' ).parse()
+                                       ),
+                                       { recoverable: false }
+                               );
+                       } else if ( warnings[ 'bad-prefix' ] !== undefined ) {
+                               return new OO.ui.Error(
+                                       $( '<p>' ).html(
+                                               mw.message( 'filename-bad-prefix', warnings[ 'bad-prefix' ] ).parse()
+                                       ),
+                                       { recoverable: false }
+                               );
+                       } else if ( warnings[ 'duplicate-archive' ] !== undefined ) {
+                               return new OO.ui.Error(
+                                       $( '<p>' ).html(
+                                               mw.message( 'api-error-duplicate-archive', 1 ).parse()
+                                       ),
+                                       { recoverable: false }
+                               );
+                       } else if ( warnings.badfilename !== undefined ) {
+                               // Change the name if the current name isn't acceptable
+                               // TODO This might not really be the best place to do this
+                               this.filenameWidget.setValue( warnings.badfilename );
+                               return new OO.ui.Error(
+                                       $( '<p>' ).html(
+                                               mw.message( 'badfilename', warnings.badfilename ).parse()
+                                       )
+                               );
+                       } else {
+                               return new OO.ui.Error(
+                                       $( '<p>' ).html(
+                                               // Let's get all the help we can if we can't pin point the error
+                                               mw.message( 'api-error-unknown-warning', JSON.stringify( stateDetails ) ).parse()
+                                       ),
+                                       { recoverable: false }
+                               );
+                       }
+               }
+       };
+
        /* Form renderers */
 
        /**
 
        /* Setters */
 
+       /**
+        * Sets the file object
+        *
+        * @protected
+        * @param {File|null} file File to select
+        */
+       mw.Upload.BookletLayout.prototype.setFile = function ( file ) {
+               this.selectFileWidget.setValue( file );
+       };
+
        /**
         * Clear the values of all fields
         *