File: ve.ui.MWTemplateTitleInputWidget.js

package info (click to toggle)
mediawiki 1%3A1.35.13-1%2Bdeb11u2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 274,932 kB
  • sloc: php: 677,563; javascript: 572,709; sql: 11,565; python: 4,447; xml: 3,145; sh: 892; perl: 788; ruby: 496; pascal: 365; makefile: 128
file content (154 lines) | stat: -rw-r--r-- 5,198 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*!
 * VisualEditor UserInterface MWTemplateTitleInputWidget class.
 *
 * @copyright 2011-2020 VisualEditor Team and others; see AUTHORS.txt
 * @license The MIT License (MIT); see LICENSE.txt
 */

/**
 * Creates an ve.ui.MWTemplateTitleInputWidget object.
 *
 * @class
 * @extends mw.widgets.TitleInputWidget
 *
 * @constructor
 * @param {Object} [config] Configuration options
 * @cfg {number} [namespace] Namespace to prepend to queries. Defaults to template namespace.
 */
ve.ui.MWTemplateTitleInputWidget = function VeUiMWTemplateTitleInputWidget( config ) {
	config = ve.extendObject( {}, {
		namespace: mw.config.get( 'wgNamespaceIds' ).template
	}, config );

	// Parent constructor
	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;

	// Properties
	this.descriptions = {};

	// Initialization
	this.$element.addClass( 've-ui-mwTemplateTitleInputWidget' );
};

/* Inheritance */

// FIXME: This should extend mw.widgets.TitleSearchWidget instead
OO.inheritClass( ve.ui.MWTemplateTitleInputWidget, mw.widgets.TitleInputWidget );

/* Methods */

// @inheritdoc mw.widgets.TitleInputWidget
ve.ui.MWTemplateTitleInputWidget.prototype.getLookupRequest = function () {
	var widget = this,
		originalResponse,
		templateDataMessage = mw.message( 'templatedata-doc-subpage' ),
		templateDataInstalled = templateDataMessage.exists(),
		templateDocPageFragment = '/' + templateDataMessage.text(),
		promise = ve.ui.MWTemplateTitleInputWidget.super.prototype.getLookupRequest.call( this );

	if ( this.showTemplateDescriptions ) {
		return promise
			.then( function ( response ) {
				var xhr, pageId, redirIndex,
					redirects = ( response.query && response.query.redirects ) || {},
					origPages = ( response.query && response.query.pages ) || {},
					newPages = [],
					titles = [];

				// 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;
							}
						}
					}
				}

				// 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;
					} );
				}

				titles = newPages.map( function ( page ) {
					return page.title;
				} );

				ve.setProp( response, 'query', 'pages', newPages );
				originalResponse = response; // lie!

				// Also get descriptions
				// FIXME: This should go through MWTransclusionModel rather than duplicate.
				if ( titles.length > 0 ) {
					xhr = widget.getApi().get( {
						action: 'templatedata',
						format: 'json',
						formatversion: 2,
						titles: titles,
						redirects: !!widget.showRedirects,
						doNotIgnoreMissingTitles: '1',
						lang: mw.config.get( 'wgUserLanguage' )
					} );
					return xhr.promise( { abort: xhr.abort } );
				}
			} )
			.then( function ( templateDataResponse ) {
				var index, page, missingTitle,
					pages = ( templateDataResponse && templateDataResponse.pages ) || {};
				// Look for descriptions and cache them
				for ( index in pages ) {
					page = pages[ index ];

					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;
					}
				}
				// Return the original response
				return originalResponse;
			}, function () {
				// API request failed; most likely, we're on a wiki which doesn't have TemplateData.
				return originalResponse;
			} )
			.promise( { abort: function () {} } );

	}

	return promise;
};

// @inheritdoc mw.widgets.TitleInputWidget
ve.ui.MWTemplateTitleInputWidget.prototype.getOptionWidgetData = function ( title ) {
	return ve.extendObject(
		ve.ui.MWTemplateTitleInputWidget.super.prototype.getOptionWidgetData.apply( this, arguments ),
		{ description: this.descriptions[ title ] }
	);
};