2015-04-10 20:28:38 +00:00
|
|
|
/*!
|
|
|
|
* VisualEditor UserInterface MWTemplateTitleInputWidget class.
|
|
|
|
*
|
2019-01-01 13:24:23 +00:00
|
|
|
* @copyright 2011-2019 VisualEditor Team and others; see AUTHORS.txt
|
2015-04-10 20:28:38 +00:00
|
|
|
* @license The MIT License (MIT); see LICENSE.txt
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates an ve.ui.MWTemplateTitleInputWidget object.
|
|
|
|
*
|
|
|
|
* @class
|
2015-06-15 10:25:44 +00:00
|
|
|
* @extends mw.widgets.TitleInputWidget
|
2015-04-10 20:28:38 +00:00
|
|
|
*
|
|
|
|
* @constructor
|
|
|
|
* @param {Object} [config] Configuration options
|
|
|
|
* @cfg {number} [namespace] Namespace to prepend to queries. Defaults to template namespace.
|
|
|
|
*/
|
|
|
|
ve.ui.MWTemplateTitleInputWidget = function VeUiMWTemplateTitleInputWidget( config ) {
|
2016-10-28 00:22:30 +00:00
|
|
|
config = ve.extendObject( {}, {
|
2015-06-15 10:25:44 +00:00
|
|
|
namespace: mw.config.get( 'wgNamespaceIds' ).template
|
|
|
|
}, config );
|
|
|
|
|
2015-04-10 20:28:38 +00:00
|
|
|
// Parent constructor
|
2015-06-15 10:25:44 +00:00
|
|
|
ve.ui.MWTemplateTitleInputWidget.super.call( this, config );
|
|
|
|
|
|
|
|
this.showTemplateDescriptions = this.showDescriptions;
|
|
|
|
// Clear the showDescriptions flag for subsequent requests as we implement
|
|
|
|
// description fetch ourselves
|
|
|
|
this.showDescriptions = false;
|
2015-04-10 20:28:38 +00:00
|
|
|
|
|
|
|
// Properties
|
|
|
|
this.descriptions = {};
|
|
|
|
|
|
|
|
// Initialization
|
|
|
|
this.$element.addClass( 've-ui-mwTemplateTitleInputWidget' );
|
|
|
|
};
|
2015-05-25 13:51:13 +00:00
|
|
|
|
2015-04-10 20:28:38 +00:00
|
|
|
/* Inheritance */
|
|
|
|
|
2017-04-21 01:51:11 +00:00
|
|
|
// FIXME: This should extend mw.widgets.TitleSearchWidget instead
|
2015-06-15 10:25:44 +00:00
|
|
|
OO.inheritClass( ve.ui.MWTemplateTitleInputWidget, mw.widgets.TitleInputWidget );
|
2015-04-10 20:28:38 +00:00
|
|
|
|
|
|
|
/* Methods */
|
|
|
|
|
|
|
|
/**
|
2015-05-25 13:51:13 +00:00
|
|
|
* See the parent documentation at <https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.widgets.TitleInputWidget>
|
2015-04-10 20:28:38 +00:00
|
|
|
*/
|
|
|
|
ve.ui.MWTemplateTitleInputWidget.prototype.getLookupRequest = function () {
|
2015-06-15 10:25:44 +00:00
|
|
|
var widget = this,
|
|
|
|
originalResponse,
|
2019-01-09 19:30:42 +00:00
|
|
|
templateDataMessage = mw.message( 'templatedata-doc-subpage' ),
|
|
|
|
templateDataInstalled = templateDataMessage.exists(),
|
|
|
|
templateDocPageFragment = '/' + templateDataMessage.text(),
|
2015-06-15 10:25:44 +00:00
|
|
|
promise = ve.ui.MWTemplateTitleInputWidget.super.prototype.getLookupRequest.call( this );
|
|
|
|
|
|
|
|
if ( this.showTemplateDescriptions ) {
|
|
|
|
return promise
|
|
|
|
.then( function ( response ) {
|
2019-01-09 19:30:42 +00:00
|
|
|
var xhr, pageId, redirIndex,
|
2015-09-10 16:13:36 +00:00
|
|
|
redirects = ( response.query && response.query.redirects ) || {},
|
|
|
|
origPages = ( response.query && response.query.pages ) || {},
|
|
|
|
newPages = [],
|
2015-06-15 10:25:44 +00:00
|
|
|
titles = [];
|
|
|
|
|
2015-09-10 16:13:36 +00:00
|
|
|
// Build a new array to replace response.query.pages, ensuring everything goes into
|
|
|
|
// the order defined by the page's index key, instead of whatever random order the
|
|
|
|
// browser would let you iterate over the old object in.
|
|
|
|
for ( pageId in origPages ) {
|
|
|
|
if ( 'index' in origPages[ pageId ] ) {
|
|
|
|
newPages[ origPages[ pageId ].index - 1 ] = origPages[ pageId ];
|
|
|
|
} else {
|
|
|
|
// Watch out for cases where the index is specified on the redirect object
|
|
|
|
// rather than the page object.
|
|
|
|
for ( redirIndex in redirects ) {
|
|
|
|
if ( redirects[ redirIndex ].to === origPages[ pageId ].title ) {
|
|
|
|
newPages[ redirects[ redirIndex ].index - 1 ] = origPages[ pageId ];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-06-15 10:25:44 +00:00
|
|
|
}
|
2015-04-10 20:28:38 +00:00
|
|
|
|
2019-01-09 19:30:42 +00:00
|
|
|
// T54448: Filter out matches which end in /doc or as configured on-wiki
|
|
|
|
if ( templateDataInstalled ) {
|
|
|
|
newPages = newPages.filter( function ( page ) {
|
|
|
|
// Can't use String.endsWith() as that's ES6.
|
|
|
|
// page.title.endsWith( templateDocPageFragment )
|
|
|
|
return page.title.slice( 0 - templateDocPageFragment.length ) !== templateDocPageFragment;
|
|
|
|
} );
|
|
|
|
} else {
|
|
|
|
// Even if not filtering /doc, collapse the sparse array
|
|
|
|
newPages = newPages.filter( function ( page ) {
|
|
|
|
return page;
|
|
|
|
} );
|
2015-09-10 16:13:36 +00:00
|
|
|
}
|
|
|
|
|
2019-01-09 19:30:42 +00:00
|
|
|
titles = newPages.map( function ( page ) {
|
|
|
|
return page.title;
|
|
|
|
} );
|
|
|
|
|
2015-09-24 21:35:38 +00:00
|
|
|
ve.setProp( response, 'query', 'pages', newPages );
|
2015-09-10 16:13:36 +00:00
|
|
|
originalResponse = response; // lie!
|
2015-04-10 20:28:38 +00:00
|
|
|
|
2015-09-10 16:13:36 +00:00
|
|
|
// Also get descriptions
|
2017-04-21 01:51:11 +00:00
|
|
|
// FIXME: This should go through MWTransclusionModel rather than duplicate.
|
2015-06-15 10:25:44 +00:00
|
|
|
if ( titles.length > 0 ) {
|
2017-04-21 01:51:11 +00:00
|
|
|
xhr = widget.getApi().get( {
|
2015-06-15 10:25:44 +00:00
|
|
|
action: 'templatedata',
|
2017-04-21 01:51:11 +00:00
|
|
|
format: 'json',
|
|
|
|
formatversion: '2',
|
2016-09-30 16:07:10 +00:00
|
|
|
titles: titles,
|
2017-04-21 01:51:11 +00:00
|
|
|
redirects: !!widget.showRedirects,
|
|
|
|
doNotIgnoreMissingTitles: '1',
|
2015-06-15 10:25:44 +00:00
|
|
|
lang: mw.config.get( 'wgUserLanguage' )
|
2017-04-21 01:51:11 +00:00
|
|
|
} );
|
2015-06-15 10:25:44 +00:00
|
|
|
return xhr.promise( { abort: xhr.abort } );
|
2015-04-10 20:28:38 +00:00
|
|
|
}
|
2015-06-15 10:25:44 +00:00
|
|
|
} )
|
|
|
|
.then( function ( templateDataResponse ) {
|
2017-04-21 01:51:11 +00:00
|
|
|
var index, page, missingTitle,
|
2015-06-15 10:25:44 +00:00
|
|
|
pages = ( templateDataResponse && templateDataResponse.pages ) || {};
|
|
|
|
// Look for descriptions and cache them
|
|
|
|
for ( index in pages ) {
|
2015-08-19 17:33:02 +00:00
|
|
|
page = pages[ index ];
|
2019-01-09 19:30:42 +00:00
|
|
|
|
2017-04-21 01:51:11 +00:00
|
|
|
if ( page.missing ) {
|
|
|
|
// Remmeber templates that don't exist in the link cache
|
|
|
|
// { title: { missing: true|false }
|
|
|
|
missingTitle = {};
|
|
|
|
missingTitle[ page.title ] = { missing: true };
|
|
|
|
ve.init.platform.linkCache.setMissing( missingTitle );
|
|
|
|
} else if ( !page.notemplatedata ) {
|
|
|
|
// Cache descriptions
|
|
|
|
widget.descriptions[ page.title ] = page.description;
|
|
|
|
}
|
2015-06-15 10:25:44 +00:00
|
|
|
}
|
|
|
|
// Return the original response
|
|
|
|
return originalResponse;
|
2018-02-21 17:52:42 +00:00
|
|
|
}, function () {
|
|
|
|
// API request failed; most likely, we're on a wiki which doesn't have TemplateData.
|
|
|
|
return originalResponse;
|
2015-06-15 10:25:44 +00:00
|
|
|
} )
|
|
|
|
.promise( { abort: function () {} } );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return promise;
|
2015-04-10 20:28:38 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2015-06-15 10:25:44 +00:00
|
|
|
* See the parent documentation at <https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.widgets.TitleInputWidget>
|
2016-10-28 19:02:36 +00:00
|
|
|
*
|
|
|
|
* @param {string} title
|
|
|
|
* @return {Object}
|
2015-04-10 20:28:38 +00:00
|
|
|
*/
|
2015-06-15 10:25:44 +00:00
|
|
|
ve.ui.MWTemplateTitleInputWidget.prototype.getOptionWidgetData = function ( title ) {
|
|
|
|
return ve.extendObject(
|
|
|
|
ve.ui.MWTemplateTitleInputWidget.super.prototype.getOptionWidgetData.apply( this, arguments ),
|
2015-08-19 17:33:02 +00:00
|
|
|
{ description: this.descriptions[ title ] }
|
2015-06-15 10:25:44 +00:00
|
|
|
);
|
2015-04-10 20:28:38 +00:00
|
|
|
};
|