Merge "mediawiki.Upload: Add #getApi method, use it instead of undocumented properties"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 6 Jan 2016 22:21:40 +0000 (22:21 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 6 Jan 2016 22:21:40 +0000 (22:21 +0000)
1  2 
resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.js
resources/src/mediawiki/mediawiki.Upload.BookletLayout.js

@@@ -43,7 -43,7 +43,7 @@@
                mw.ForeignStructuredUpload.BookletLayout.parent.prototype.initialize.call( this )
                        .done( function () {
                                // Point the CategorySelector to the right wiki
-                               this.upload.apiPromise.done( function ( api ) {
+                               this.upload.getApi().done( function ( api ) {
                                        // If this is a ForeignApi, it will have a apiUrl, otherwise we don't need to do anything
                                        if ( api.apiUrl ) {
                                                // Can't reuse the same object, CategorySelector calls #abort on its mw.Api instance
                this.selectFileWidget.on( 'change', onUploadFormChange.bind( this ) );
                this.ownWorkCheckbox.on( 'change', onUploadFormChange.bind( this ) );
  
 +              this.selectFileWidget.on( 'change', function () {
 +                      var file = layout.getFile();
 +
 +                      // Set the date to lastModified once we have the file
 +                      if ( layout.getDateFromLastModified( file ) !== undefined ) {
 +                              layout.dateWidget.setValue( layout.getDateFromLastModified( file ) );
 +                      }
 +
 +                      // Check if we have EXIF data and set to that where available
 +                      layout.getDateFromExif( file ).done( function ( date ) {
 +                              layout.dateWidget.setValue( date );
 +                      } );
 +              } );
 +
                return this.uploadForm;
        };
  
                        multiline: true,
                        autosize: true
                } );
 -              this.dateWidget = new mw.widgets.DateInputWidget( {
 -                      $overlay: this.$overlay,
 -                      required: true,
 -                      mustBeBefore: moment().add( 1, 'day' ).locale( 'en' ).format( 'YYYY-MM-DD' ) // Tomorrow
 -              } );
                this.categoriesWidget = new mw.widgets.CategorySelector( {
                        // Can't be done here because we don't know the target wiki yet... done in #initialize.
                        // api: new mw.ForeignApi( ... ),
                        $overlay: this.$overlay
                } );
 +              this.dateWidget = new mw.widgets.DateInputWidget( {
 +                      $overlay: this.$overlay,
 +                      required: true,
 +                      mustBeBefore: moment().add( 1, 'day' ).locale( 'en' ).format( 'YYYY-MM-DD' ) // Tomorrow
 +              } );
  
                fieldset = new OO.ui.FieldsetLayout( {
                        label: mw.msg( 'upload-form-label-infoform-title' )
                fieldset.addItems( [
                        new OO.ui.FieldLayout( this.filenameWidget, {
                                label: mw.msg( 'upload-form-label-infoform-name' ),
 -                              align: 'top'
 +                              align: 'top',
 +                              help: mw.msg( 'upload-form-label-infoform-name-tooltip' )
                        } ),
                        new OO.ui.FieldLayout( this.descriptionWidget, {
                                label: mw.msg( 'upload-form-label-infoform-description' ),
 -                              align: 'top'
 +                              align: 'top',
 +                              help: mw.msg( 'upload-form-label-infoform-description-tooltip' )
                        } ),
                        new OO.ui.FieldLayout( this.categoriesWidget, {
                                label: mw.msg( 'foreign-structured-upload-form-label-infoform-categories' ),
                return this.upload.getText();
        };
  
 +      /**
 +       * Get original date from EXIF data
 +       *
 +       * @param {Object} file
 +       * @return {jQuery.Promise} Promise resolved with the EXIF date
 +       */
 +      mw.ForeignStructuredUpload.BookletLayout.prototype.getDateFromExif = function ( file ) {
 +              var fileReader,
 +                      deferred = $.Deferred();
 +
 +              if ( file && file.type === 'image/jpeg' ) {
 +                      fileReader = new FileReader();
 +                      fileReader.onload = function () {
 +                              var fileStr, arr, i, metadata;
 +
 +                              if ( typeof fileReader.result === 'string' ) {
 +                                      fileStr = fileReader.result;
 +                              } else {
 +                                      // Array buffer; convert to binary string for the library.
 +                                      arr = new Uint8Array( fileReader.result );
 +                                      fileStr = '';
 +                                      for ( i = 0; i < arr.byteLength; i++ ) {
 +                                              fileStr += String.fromCharCode( arr[ i ] );
 +                                      }
 +                              }
 +
 +                              try {
 +                                      metadata = mw.libs.jpegmeta( this.result, file.name );
 +                              } catch ( e ) {
 +                                      metadata = null;
 +                              }
 +
 +                              if ( metadata !== null && metadata.exif !== undefined && metadata.exif.DateTimeOriginal ) {
 +                                      deferred.resolve( moment( metadata.exif.DateTimeOriginal, 'YYYY:MM:DD' ).format( 'YYYY-MM-DD' ) );
 +                              } else {
 +                                      deferred.reject();
 +                              }
 +                      };
 +
 +                      if ( 'readAsBinaryString' in fileReader ) {
 +                              fileReader.readAsBinaryString( file );
 +                      } else if ( 'readAsArrayBuffer' in fileReader ) {
 +                              fileReader.readAsArrayBuffer( file );
 +                      } else {
 +                              // We should never get here
 +                              deferred.reject();
 +                              throw new Error( 'Cannot read thumbnail as binary string or array buffer.' );
 +                      }
 +              }
 +
 +              return deferred.promise();
 +      };
 +
 +      /**
 +       * Get last modified date from file
 +       *
 +       * @param {Object} file
 +       * @return {Object} Last modified date from file
 +       */
 +      mw.ForeignStructuredUpload.BookletLayout.prototype.getDateFromLastModified = function ( file ) {
 +              if ( file && file.lastModified ) {
 +                      return moment( file.lastModified ).format( 'YYYY-MM-DD' );
 +              }
 +      };
 +
        /* Setters */
  
        /**
         */
        mw.Upload.BookletLayout.prototype.initialize = function () {
                var
-                       apiPromise,
                        booklet = this,
                        deferred = $.Deferred();
  
                this.upload = this.createUpload();
                this.setPage( 'upload' );
  
-               apiPromise = this.upload.apiPromise || $.Deferred().resolve( this.upload.api );
-               apiPromise.done( function ( api ) {
+               this.upload.getApi().done( function ( api ) {
                        // If the user can't upload anything, don't give them the option to.
                        api.getUserInfo().done( function ( userInfo ) {
                                if ( userInfo.rights.indexOf( 'upload' ) === -1 ) {
                        layout = this,
                        file = this.getFile();
  
 -              this.filenameWidget.setValue( file.name );
 +              this.setFilename( file.name );
 +
                this.setPage( 'info' );
  
                if ( this.shouldRecordBucket ) {
                }
  
                this.upload.setFile( file );
 -              // Explicitly set the filename so that the old filename isn't used in case of retry
 -              this.upload.setFilenameFromFile();
 +              // The original file name might contain invalid characters, so use our sanitized one
 +              this.upload.setFilename( this.getFilename() );
  
                this.uploadPromise = this.upload.uploadToStash();
                this.uploadPromise.then( function () {
                        } 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 );
 +                              this.setFilename( warnings.badfilename );
                                return new OO.ui.Error(
                                        $( '<p>' ).msg( 'badfilename', warnings.badfilename )
                                );
                fieldset.addItems( [
                        new OO.ui.FieldLayout( this.filenameWidget, {
                                label: mw.msg( 'upload-form-label-infoform-name' ),
 -                              align: 'top'
 +                              align: 'top',
 +                              help: mw.msg( 'upload-form-label-infoform-name-tooltip' )
                        } ),
                        new OO.ui.FieldLayout( this.descriptionWidget, {
                                label: mw.msg( 'upload-form-label-infoform-description' ),
 -                              align: 'top'
 +                              align: 'top',
 +                              help: mw.msg( 'upload-form-label-infoform-description-tooltip' )
                        } )
                ] );
                this.infoForm = new OO.ui.FormLayout( { items: [ fieldset ] } );
         * @return {string}
         */
        mw.Upload.BookletLayout.prototype.getFilename = function () {
 -              return this.filenameWidget.getValue();
 +              var filename = this.filenameWidget.getValue();
 +              if ( this.filenameExtension ) {
 +                      filename += '.' + this.filenameExtension;
 +              }
 +              return filename;
 +      };
 +
 +      /**
 +       * Prefills the {@link #infoForm information form} with the given filename.
 +       *
 +       * @protected
 +       * @param {string} filename
 +       */
 +      mw.Upload.BookletLayout.prototype.setFilename = function ( filename ) {
 +              var title = mw.Title.newFromFileName( filename );
 +
 +              if ( title ) {
 +                      this.filenameWidget.setValue( title.getNameText() );
 +                      this.filenameExtension = mw.Title.normalizeExtension( title.getExtension() );
 +              } else {
 +                      // Seems to happen for files with no extension, which should fail some checks anyway...
 +                      this.filenameWidget.setValue( filename );
 +                      this.filenameExtension = null;
 +              }
        };
  
        /**