2022-04-15 15:59:54 +00:00
|
|
|
// eslint-disable-next-line spaced-comment
|
|
|
|
/// <reference path="../mw.ts" />
|
|
|
|
|
2022-04-14 23:11:07 +00:00
|
|
|
/**
|
|
|
|
* @class RelatedPagesGateway
|
2022-04-15 15:59:54 +00:00
|
|
|
* @param {MwApi} api
|
2022-04-14 23:11:07 +00:00
|
|
|
* @param {string} currentPage the page that the editorCuratedPages relate to
|
2022-04-15 15:59:54 +00:00
|
|
|
* @param {string[]|null} editorCuratedPages a list of pages curated by editors for the current page
|
2022-04-14 23:11:07 +00:00
|
|
|
* @param {boolean} useCirrusSearch whether to hit the API when no editor-curated pages are available
|
|
|
|
* @param {boolean} [onlyUseCirrusSearch=false] whether to ignore the list of editor-curated pages
|
|
|
|
* @param {boolean|string} [descriptionSource=false] source to get the page description from
|
|
|
|
*/
|
|
|
|
function RelatedPagesGateway(
|
|
|
|
api,
|
|
|
|
currentPage,
|
|
|
|
editorCuratedPages,
|
|
|
|
useCirrusSearch,
|
|
|
|
onlyUseCirrusSearch,
|
|
|
|
descriptionSource
|
|
|
|
) {
|
|
|
|
this.api = api;
|
|
|
|
this.currentPage = currentPage;
|
|
|
|
this.useCirrusSearch = useCirrusSearch;
|
|
|
|
this.descriptionSource = descriptionSource;
|
|
|
|
|
|
|
|
if ( onlyUseCirrusSearch ) {
|
|
|
|
editorCuratedPages = [];
|
2015-11-03 23:39:48 +00:00
|
|
|
}
|
|
|
|
|
2022-04-14 23:11:07 +00:00
|
|
|
this.editorCuratedPages = editorCuratedPages || [];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-11-08 22:06:07 +00:00
|
|
|
/**
|
|
|
|
* @param {JQuery.Promise<any>} jQP
|
|
|
|
* @return {Promise<any>}
|
|
|
|
*/
|
|
|
|
const toPromise = ( jQP ) => new Promise( ( resolve, reject ) => {
|
|
|
|
jQP.then( ( pages ) => resolve( pages ), ( e ) => reject( e ) );
|
|
|
|
} );
|
|
|
|
|
2022-04-14 23:11:07 +00:00
|
|
|
/**
|
|
|
|
* @ignore
|
2022-04-15 15:59:54 +00:00
|
|
|
* @param {MwApiQueryResponse} result
|
|
|
|
* @return {MwApiPageObject[]}}
|
2022-04-14 23:11:07 +00:00
|
|
|
*/
|
|
|
|
function getPages( result ) {
|
|
|
|
return result && result.query && result.query.pages ? result.query.pages : [];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2023-11-08 22:06:07 +00:00
|
|
|
* Gets the related pages for the list of pages
|
2022-04-14 23:11:07 +00:00
|
|
|
*
|
|
|
|
* If there are related pages assigned to this page using the `related`
|
|
|
|
* parser function, then they are returned.
|
|
|
|
*
|
|
|
|
* If there aren't any related pages assigned to the page, then the
|
|
|
|
* CirrusSearch extension's {@link https://www.mediawiki.org/wiki/Help:CirrusSearch#morelike: "morelike:" feature}
|
|
|
|
* is used. If the CirrusSearch extension isn't installed, then the API
|
|
|
|
* call will fail gracefully and no related pages will be returned.
|
|
|
|
* Thus the dependency on the CirrusSearch extension is soft.
|
|
|
|
*
|
|
|
|
* Related pages will have the following information:
|
|
|
|
*
|
|
|
|
* * The ID of the page corresponding to the title
|
|
|
|
* * The thumbnail, if any
|
|
|
|
* * The page description, if any
|
|
|
|
*
|
2023-11-08 22:06:07 +00:00
|
|
|
* @param {MwApiActionQuery} params for api
|
|
|
|
* @return {Promise<MwApiPageObject[]>}
|
2022-04-14 23:11:07 +00:00
|
|
|
*/
|
2023-11-08 22:06:07 +00:00
|
|
|
RelatedPagesGateway.prototype.getPagesFromApi = function ( params ) {
|
|
|
|
const parameters = /** @type {MwApiActionQuery} */ Object.assign( {
|
|
|
|
formatversion: 2,
|
|
|
|
origin: '*',
|
|
|
|
prop: 'pageimages',
|
|
|
|
piprop: 'thumbnail',
|
|
|
|
pithumbsize: 160 // FIXME: Revert to 80 once pithumbmode is implemented
|
|
|
|
}, params );
|
2022-04-14 23:11:07 +00:00
|
|
|
|
|
|
|
switch ( this.descriptionSource ) {
|
|
|
|
case 'wikidata':
|
|
|
|
parameters.prop += '|description';
|
|
|
|
break;
|
|
|
|
case 'textextracts':
|
|
|
|
parameters.prop += '|extracts';
|
|
|
|
parameters.exsentences = '1';
|
|
|
|
parameters.exintro = '1';
|
|
|
|
parameters.explaintext = '1';
|
|
|
|
break;
|
|
|
|
case 'pagedescription':
|
|
|
|
parameters.prop += '|pageprops';
|
|
|
|
parameters.ppprop = 'description';
|
|
|
|
break;
|
2017-04-07 20:21:12 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 22:06:07 +00:00
|
|
|
return toPromise(
|
|
|
|
this.api.get( parameters )
|
|
|
|
.then( getPages )
|
|
|
|
);
|
|
|
|
};
|
2022-04-14 23:11:07 +00:00
|
|
|
|
2023-11-08 22:06:07 +00:00
|
|
|
/**
|
|
|
|
* Gets the related pages for the list of pages
|
|
|
|
*
|
|
|
|
* @param {string[]} titles
|
|
|
|
* @return {Promise<MwApiPageObject[]>}
|
|
|
|
*/
|
|
|
|
RelatedPagesGateway.prototype.getPages = function ( titles ) {
|
|
|
|
return this.getPagesFromApi( {
|
|
|
|
action: 'query',
|
|
|
|
pilimit: titles.length,
|
|
|
|
continue: '',
|
|
|
|
titles
|
|
|
|
} );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the related pages for the list of pages
|
|
|
|
*
|
|
|
|
* @param {number} limit of pages to get. Should be between 1-20.
|
|
|
|
* @return {Promise<MwApiPageObject[]>}
|
|
|
|
*/
|
|
|
|
RelatedPagesGateway.prototype.getForCurrentPage = function ( limit ) {
|
|
|
|
const relatedPages = this.editorCuratedPages.slice( 0, limit );
|
|
|
|
if ( relatedPages.length ) {
|
|
|
|
return this.getPages( relatedPages );
|
2022-04-14 23:11:07 +00:00
|
|
|
} else if ( this.useCirrusSearch ) {
|
2023-11-08 22:06:07 +00:00
|
|
|
const parameters = /** @type {MwApiActionQuery} */( {
|
|
|
|
action: 'query'
|
|
|
|
} );
|
2022-04-14 23:11:07 +00:00
|
|
|
parameters.pilimit = limit;
|
|
|
|
|
|
|
|
parameters.generator = 'search';
|
2024-04-20 20:15:07 +00:00
|
|
|
parameters.gsrsearch = `morelike:${ this.currentPage }`;
|
2022-04-14 23:11:07 +00:00
|
|
|
parameters.gsrnamespace = '0';
|
|
|
|
parameters.gsrlimit = limit;
|
|
|
|
parameters.gsrqiprofile = 'classic_noboostlinks';
|
|
|
|
|
|
|
|
// Currently, if you're logged in, then the API uses your language by default ard so responses
|
|
|
|
// are always private i.e. they shouldn't be cached in a shared cache and can be cached by the
|
|
|
|
// browser.
|
|
|
|
//
|
|
|
|
// By make the API use the language of the content rather than that of the user, the API
|
|
|
|
// reponse is made public, i.e. they can be cached in a shared cache.
|
|
|
|
//
|
|
|
|
// See T97096 for more detail and discussion.
|
|
|
|
parameters.uselang = 'content';
|
|
|
|
|
|
|
|
// Instruct shared caches that the response will become stale in 24 hours.
|
|
|
|
parameters.smaxage = 86400;
|
|
|
|
|
|
|
|
// Instruct the browser that the response will become stale in 24 hours.
|
|
|
|
parameters.maxage = 86400;
|
2023-11-08 22:06:07 +00:00
|
|
|
return this.getPagesFromApi( parameters ).then( ( pages ) => Promise.resolve( pages ) );
|
2022-04-14 23:11:07 +00:00
|
|
|
} else {
|
2023-11-08 22:06:07 +00:00
|
|
|
return Promise.resolve( [] );
|
2022-04-14 23:11:07 +00:00
|
|
|
}
|
|
|
|
};
|
2015-11-03 23:39:48 +00:00
|
|
|
|
2022-04-14 23:11:07 +00:00
|
|
|
module.exports = RelatedPagesGateway;
|