Improve TitleWidget search results

Add the query value as a redlink in the result list,
as is already done if the query value is *not* a prefix
of some other (existing) title.

Bug: T291056
Change-Id: I1569ad5a57cd98fe7deb034512b46e948a3561e1
This commit is contained in:
Sam Wilson 2021-10-05 18:18:59 +08:00
parent df729bc7ae
commit 84ef41addb

View file

@ -148,8 +148,7 @@
* @return {jQuery.Promise} Suggestions promise
*/
mw.widgets.TitleWidget.prototype.getSuggestionsPromise = function () {
var req,
api = this.getApi(),
var api = this.getApi(),
query = this.getQueryValue(),
widget = this,
promiseAbortObject = { abort: function () {
@ -180,19 +179,67 @@
} } ).promise( promiseAbortObject );
}
}
// Not a interwiki: do an API lookup of the query
req = api.get( widget.getApiParams( query ) );
promiseAbortObject.abort = req.abort.bind( req ); // TODO ew
return req.then( function ( ret ) {
if ( widget.showMissing && ret.query === undefined ) {
ret = api.get( { action: 'query', titles: query } );
promiseAbortObject.abort = ret.abort.bind( ret );
// Not a interwiki: do a prefix-search API lookup of the query.
var prefixSearchRequest = api.get( widget.getApiParams( query ) );
promiseAbortObject.abort = prefixSearchRequest.abort.bind( prefixSearchRequest ); // TODO ew
return prefixSearchRequest.then( function ( prefixSearchResponse ) {
if ( !widget.showMissing ) {
return prefixSearchResponse;
}
return ret;
// Add the query title as the first result, after looking up its details.
var queryTitleRequest = api.get( { action: 'query', titles: query } );
promiseAbortObject.abort = queryTitleRequest.abort.bind( queryTitleRequest );
return queryTitleRequest.then( function ( queryTitleResponse ) {
// By default, return the prefix-search result.
var result = prefixSearchResponse;
if ( prefixSearchResponse.query === undefined ) {
// There are no prefix-search results, so make the only result the query title.
// The API response structures are identical because both API calls are action=query.
result.query = queryTitleResponse.query;
} else if ( queryTitleResponse.query.pages[ -1 ] !== undefined &&
!widget.responseContainsNonExistingTitle( prefixSearchResponse, queryTitleResponse.query.pages[ -1 ].title )
) {
// There are prefix-search results, but the query title isn't in them,
// so add it as a new result. It's under the new key 'queryTitle', because
// all other results will be under their page ID or a negative integer ID,
// and the keys aren't actually used for anything.
result.query.pages.queryTitle = queryTitleResponse.query.pages[ -1 ];
// Give it the lowest possible sort-index (the API only returns index > 0)
// to make this result be sorted at the top.
result.query.pages.queryTitle.index = 0;
}
return result;
} );
} );
} ).promise( promiseAbortObject );
};
/**
* Check for the existence of a given title in an API result set.
*
* As the title is known not to exist, this doesn't check in apiResponse.query.pages,
* but only in the redirect targets in apiResponse.query.redirects.
*
* @private
* @param {Object} apiResponse The API result set to search in.
* @param {string} title The page title to search for.
* @return {boolean}
*/
mw.widgets.TitleWidget.prototype.responseContainsNonExistingTitle = function ( apiResponse, title ) {
// Make sure there are redirects in the data.
if ( apiResponse.query.redirects === undefined ) {
return false;
}
// Check the targets against the given title.
for ( var redirect in apiResponse.query.redirects ) {
if ( apiResponse.query.redirects[ redirect ].to === title ) {
return true;
}
}
// The title wasn't found.
return false;
};
/**
* Get API params for a given query
*
@ -279,7 +326,7 @@
imageUrl: OO.getProp( suggestionPage, 'thumbnail', 'source' ),
description: suggestionPage.description,
// Sort index
index: suggestionPage.index || redirectIndices[ suggestionPage.title ],
index: suggestionPage.index !== undefined ? suggestionPage.index : redirectIndices[ suggestionPage.title ],
originalData: suggestionPage
};