jenkins-bot has submitted this change and it was merged.

Change subject: mw.Upload.BookletLayout: Better handle error messages from 
AbuseFilter and TitleBlacklist
......................................................................


mw.Upload.BookletLayout: Better handle error messages from AbuseFilter and 
TitleBlacklist

And hopefully, also other extensions, if they follow the format where
result.error.message.key is the key of a message that can be used to report
the error to the user and result.error.message.params is an array of
parameters for it, if any.

The message text is loaded dynamically from the foreign wiki.

Bug: T115260
Bug: T137841
Depends-On: I97c1f5c6bbbdfc0b8ea9914bb075d5299c14df8f (TitleBlacklist)
Depends-On: I5780eae96930211191ecd874aacf53fdacb58f89 (AbuseFilter)
Change-Id: I5d1a289cf3d3b9de53047566172ab19a859e608e
---
M languages/i18n/en.json
M languages/i18n/qqq.json
M resources/Resources.php
M resources/src/mediawiki/api/messages.js
M resources/src/mediawiki/mediawiki.Upload.BookletLayout.js
5 files changed, 74 insertions(+), 45 deletions(-)

Approvals:
  MarkTraceur: Looks good to me, approved
  Prtksxna: Looks good to me, but someone else must approve
  jenkins-bot: Verified



diff --git a/languages/i18n/en.json b/languages/i18n/en.json
index 0d7d047..a35a176 100644
--- a/languages/i18n/en.json
+++ b/languages/i18n/en.json
@@ -4057,7 +4057,6 @@
        "mw-widgets-dateinput-placeholder-month": "YYYY-MM",
        "mw-widgets-titleinput-description-new-page": "page does not exist yet",
        "mw-widgets-titleinput-description-redirect": "redirect to $1",
-       "api-error-blacklisted": "Please choose a different, descriptive 
title.",
        "sessionmanager-tie": "Cannot combine multiple request authentication 
types: $1.",
        "sessionprovider-generic": "$1 sessions",
        "sessionprovider-mediawiki-session-cookiesessionprovider": 
"cookie-based sessions",
diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json
index c1e0652..79e9cdd 100644
--- a/languages/i18n/qqq.json
+++ b/languages/i18n/qqq.json
@@ -4238,7 +4238,6 @@
        "mw-widgets-dateinput-placeholder-month": "Placeholder displayed in a 
date input field when it's empty, representing a date format with 4 digits for 
year and 2 digits for month, separated with hyphens (without a day). This 
should be uppercase, if possible, and must not include any additional 
explanations. If there is no good way to translate it, make this message 
blank.",
        "mw-widgets-titleinput-description-new-page": "Description label for a 
new page in the title input widget.",
        "mw-widgets-titleinput-description-redirect": "Description label for a 
redirect in the title input widget.",
-       "api-error-blacklisted": "Used as error message.\n\nFollowed by the 
link {{msg-mw|Mwe-upwiz-feedback-blacklist-info-prompt}}.",
        "sessionmanager-tie": "Used as an error message when multiple session 
sources are tied in priority.\n\nParameters:\n* $1 - List of dession type 
descriptions, from messages like 
{{msg-mw|sessionprovider-mediawiki-session-cookiesessionprovider}}.",
        "sessionprovider-generic": "Used to create a generic session type 
description when one isn't provided via the proper message. Should be phrased 
to make sense when added to a message such as 
{{msg-mw|cannotloginnow-text}}.\n\nParameters:\n* $1 - PHP classname.",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "Description 
of the sessions provided by the CookieSessionProvider class, which use HTTP 
cookies. Should be phrased to make sense when added to a message such as 
{{msg-mw|cannotloginnow-text}}.",
diff --git a/resources/Resources.php b/resources/Resources.php
index 150b8d3..2e22c93 100644
--- a/resources/Resources.php
+++ b/resources/Resources.php
@@ -1298,7 +1298,6 @@
                        'filename-thumb-name',
                        'badfilename',
                        'protectedpagetext',
-                       'api-error-blacklisted', // HACK
                ],
        ],
        'mediawiki.ForeignStructuredUpload.BookletLayout' => [
diff --git a/resources/src/mediawiki/api/messages.js 
b/resources/src/mediawiki/api/messages.js
index df21eb2..9ba562e 100644
--- a/resources/src/mediawiki/api/messages.js
+++ b/resources/src/mediawiki/api/messages.js
@@ -44,6 +44,25 @@
                 */
                loadMessages: function ( messages ) {
                        return this.getMessages( messages ).then( $.proxy( 
mw.messages, 'set' ) );
+               },
+
+               /**
+                * Loads a set of mesages and add them to mw.messages. Only 
messages that are not already known
+                * are loaded. If all messages are known, the returned promise 
is resolved immediately.
+                *
+                * @param {Array} messages Messages to retrieve
+                * @return {jQuery.Promise}
+                */
+               loadMessagesIfMissing: function ( messages ) {
+                       var missing = messages.filter( function ( msg ) {
+                               return !mw.message( msg ).exists();
+                       } );
+
+                       if ( missing.length === 0 ) {
+                               return $.Deferred().resolve();
+                       }
+
+                       return this.getMessages( missing ).then( $.proxy( 
mw.messages, 'set' ) );
                }
        } );
 
diff --git a/resources/src/mediawiki/mediawiki.Upload.BookletLayout.js 
b/resources/src/mediawiki/mediawiki.Upload.BookletLayout.js
index bbd0f1b..31e4492 100644
--- a/resources/src/mediawiki/mediawiki.Upload.BookletLayout.js
+++ b/resources/src/mediawiki/mediawiki.Upload.BookletLayout.js
@@ -260,10 +260,9 @@
                        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 );
+                       layout.getErrorMessageForStateDetails().then( function 
( errorMessage ) {
+                               deferred.reject( errorMessage );
+                       } );
                }, function ( progress ) {
                        var elapsedTime = new Date() - startTime,
                                estimatedTotalTime = ( 1 / progress ) * 
elapsedTime,
@@ -309,8 +308,9 @@
                                deferred.resolve();
                                layout.emit( 'fileSaved', 
layout.upload.getImageInfo() );
                        }, function () {
-                               var errorMessage = 
layout.getErrorMessageForStateDetails();
-                               deferred.reject( errorMessage );
+                               layout.getErrorMessageForStateDetails().then( 
function ( errorMessage ) {
+                                       deferred.reject( errorMessage );
+                               } );
                        } );
                } );
 
@@ -322,7 +322,7 @@
         * state and state details.
         *
         * @protected
-        * @return {OO.ui.Error} Error to display for given state and details.
+        * @return {jQuery.Promise} A Promise that will be resolved with an 
OO.ui.Error.
         */
        mw.Upload.BookletLayout.prototype.getErrorMessageForStateDetails = 
function () {
                var message,
@@ -334,21 +334,34 @@
                if ( state === mw.Upload.State.ERROR ) {
                        if ( !error ) {
                                // If there's an 'exception' key, this might be 
a timeout, or other connection problem
-                               return new OO.ui.Error(
+                               return $.Deferred().resolve( new OO.ui.Error(
                                        $( '<p>' ).msg( 
'api-error-unknownerror', JSON.stringify( stateDetails ) ),
                                        { recoverable: false }
-                               );
+                               ) );
                        }
 
-                       // 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(
-                                       // HACK TitleBlacklist doesn't have a 
sensible message, this one is from UploadWizard
-                                       $( '<p>' ).msg( 'api-error-blacklisted' 
),
-                                       { recoverable: false }
-                               );
+                       // Errors in this format are produced by TitleBlacklist 
and AbuseFilter. Perhaps other
+                       // extensions will follow this format in the future.
+                       if ( error.message ) {
+                               return this.upload.getApi()
+                                       .then( function ( api ) {
+                                               return 
api.loadMessagesIfMissing( [ error.message.key ] ).then( function () {
+                                                       if ( !mw.message( 
error.message.key ).exists() ) {
+                                                               return 
$.Deferred().reject();
+                                                       }
+                                                       return new OO.ui.Error(
+                                                               $( '<p>' ).msg( 
error.message.key, error.message.params || [] ),
+                                                               { recoverable: 
false }
+                                                       );
+                                               } );
+                                       } )
+                                       .then( null, function () {
+                                               // We failed when loading the 
error message, or it doesn't actually exist, fall back
+                                               return $.Deferred().resolve( 
new OO.ui.Error(
+                                                       $( '<p>' ).msg( 
'api-error-unknownerror', JSON.stringify( stateDetails ) ),
+                                                       { recoverable: false }
+                                               ) );
+                                       } );
                        }
 
                        if ( error.code === 'protectedpage' ) {
@@ -359,10 +372,10 @@
                                        message = mw.message( 
'api-error-unknownerror', JSON.stringify( stateDetails ) );
                                }
                        }
-                       return new OO.ui.Error(
+                       return $.Deferred().resolve( new OO.ui.Error(
                                $( '<p>' ).append( message.parseDom() ),
                                { recoverable: false }
-                       );
+                       ) );
                }
 
                if ( state === mw.Upload.State.WARNING ) {
@@ -370,63 +383,63 @@
                        // 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(
+                               return $.Deferred().resolve( new OO.ui.Error(
                                        $( '<p>' ).msg( 'api-error-stashfailed' 
),
                                        { recoverable: false }
-                               );
+                               ) );
                        } else if ( warnings.exists !== undefined ) {
-                               return new OO.ui.Error(
+                               return $.Deferred().resolve( new OO.ui.Error(
                                        $( '<p>' ).msg( 'fileexists', 'File:' + 
warnings.exists ),
                                        { recoverable: false }
-                               );
+                               ) );
                        } else if ( warnings[ 'exists-normalized' ] !== 
undefined ) {
-                               return new OO.ui.Error(
+                               return $.Deferred().resolve( new OO.ui.Error(
                                        $( '<p>' ).msg( 'fileexists', 'File:' + 
warnings[ 'exists-normalized' ] ),
                                        { recoverable: false }
-                               );
+                               ) );
                        } else if ( warnings[ 'page-exists' ] !== undefined ) {
-                               return new OO.ui.Error(
+                               return $.Deferred().resolve( new OO.ui.Error(
                                        $( '<p>' ).msg( 'filepageexists', 
'File:' + warnings[ 'page-exists' ] ),
                                        { recoverable: false }
-                               );
+                               ) );
                        } else if ( warnings.duplicate !== undefined ) {
-                               return new OO.ui.Error(
+                               return $.Deferred().resolve( new OO.ui.Error(
                                        $( '<p>' ).msg( 'api-error-duplicate', 
warnings.duplicate.length ),
                                        { recoverable: false }
-                               );
+                               ) );
                        } else if ( warnings[ 'thumb-name' ] !== undefined ) {
-                               return new OO.ui.Error(
+                               return $.Deferred().resolve( new OO.ui.Error(
                                        $( '<p>' ).msg( 'filename-thumb-name' ),
                                        { recoverable: false }
-                               );
+                               ) );
                        } else if ( warnings[ 'bad-prefix' ] !== undefined ) {
-                               return new OO.ui.Error(
+                               return $.Deferred().resolve( new OO.ui.Error(
                                        $( '<p>' ).msg( 'filename-bad-prefix', 
warnings[ 'bad-prefix' ] ),
                                        { recoverable: false }
-                               );
+                               ) );
                        } else if ( warnings[ 'duplicate-archive' ] !== 
undefined ) {
-                               return new OO.ui.Error(
+                               return $.Deferred().resolve( new OO.ui.Error(
                                        $( '<p>' ).msg( 
'api-error-duplicate-archive', 1 ),
                                        { recoverable: false }
-                               );
+                               ) );
                        } else if ( warnings[ 'was-deleted' ] !== undefined ) {
-                               return new OO.ui.Error(
+                               return $.Deferred().resolve( new OO.ui.Error(
                                        $( '<p>' ).msg( 'api-error-was-deleted' 
),
                                        { 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.setFilename( warnings.badfilename );
-                               return new OO.ui.Error(
+                               return $.Deferred().resolve( new OO.ui.Error(
                                        $( '<p>' ).msg( 'badfilename', 
warnings.badfilename )
-                               );
+                               ) );
                        } else {
-                               return new OO.ui.Error(
+                               return $.Deferred().resolve( new OO.ui.Error(
                                        // Let's get all the help we can if we 
can't pin point the error
                                        $( '<p>' ).msg( 
'api-error-unknown-warning', JSON.stringify( stateDetails ) ),
                                        { recoverable: false }
-                               );
+                               ) );
                        }
                }
        };

-- 
To view, visit https://gerrit.wikimedia.org/r/295610
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I5d1a289cf3d3b9de53047566172ab19a859e608e
Gerrit-PatchSet: 5
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Bartosz Dziewoński <[email protected]>
Gerrit-Reviewer: Bartosz Dziewoński <[email protected]>
Gerrit-Reviewer: Edokter <[email protected]>
Gerrit-Reviewer: Jack Phoenix <[email protected]>
Gerrit-Reviewer: Jforrester <[email protected]>
Gerrit-Reviewer: MarkTraceur <[email protected]>
Gerrit-Reviewer: Prtksxna <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to