User:Indic-TechCom/Script/MoveAndReplace.js
Appearance
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/*
This is userscirpt is usefull for Move File on local wiki
This will move file and replace its usage.
@Author [[User:Jayprakash12345]]
@Author from Gadget-libGlobalReplace.js and mw.libs.wikiDOM.nowikiEscaper
@OwnBy [[meta:Indic-TechCom]]
*/
mw.loader.using( [ 'oojs-ui-windows', 'oojs-ui-widgets', 'oojs-ui-core', 'oojs-ui', 'oojs' ] ).then( function () {
// i18n for Gadget
var i18n_lang = mw.config.get( 'wgUserLanguage' );
var i18nFormoveAndreplace = {
'en' : {
'mainTitle' : 'Move & Replace' ,
'submit_acion' : 'Submit' ,
'cancel_acion' : 'Cancel' ,
'oldName' : 'Old File Name:' ,
'newName' : 'New File Name:' ,
'reason' : 'Reason:',
'noredirect': 'Don\'t leave the redirect behind (Be careful)',
'notsamename': 'New name should not same as old name.',
'notempty': 'New name should not empty.',
'dontClose': 'Don\'t Close the Dialog',
'reload': 'Reload the Page',
'reloadInst': 'Reload page When Query has stopped.',
'didnotmove': 'Did not move :(',
'moveFile': 'File has moved',
'failAftermove': 'File moved, but imageusage query failed :( Please do it manually',
'byUsing': 'By Using [[meta:Indic-TechCom/Tools|MoveAndReplace]]',
'notDone': 'has faild to done :( Please do it manually',
'Done': 'has done.',
'failBeforeReQu': 'Image uses has replace, But query for redirects failed :( Please do it manually',
'fixredirect': 'Fixed Redirect'
},
'hi' : {
'mainTitle' : 'मूव & रिप्लेस' ,
'submit_acion' : 'सबमिट' ,
'cancel_acion' : 'रद्द करें' ,
'oldName' : 'पुराना फ़ाइल नाम:' ,
'newName' : 'नया फ़ाइल नाम:' ,
'reason' : 'कारण:',
'noredirect': 'पीछे रीडायरेक्ट न छोड़ें (सावधान रहे)',
'notsamename': 'नया नाम पुराने नाम के समान नहीं होना चाहिए।',
'notempty': 'नया नाम खाली नहीं होना चाहिए।',
'dontClose': 'संवाद बंद मत करो',
'reload': 'पृष्ठ को पुन: लोड करें',
'reloadInst': 'पृष्ठ को फिर से लोड करें जब क्वेरी बंद हो।',
'didnotmove': 'स्थानांतरित नहीं किया :(',
'moveFile': 'फ़ाइल स्थानांतरित हो गया',
'failAftermove': 'फ़ाइल स्थानांतरित हो गया, लेकिन छवि उपयोग क्वेरी विफल रही :( कृपया इसे मैन्युअल रूप से करें',
'byUsing': '[[meta:Indic-TechCom/Tools|MoveAndReplace]] का उपयोग करके',
'notDone': 'करने में असफल रहा है। :( कृपया इसे मैन्युअल रूप से करें',
'Done': 'करने में सफल रहा है।',
'failBeforeReQu': 'छवि उपयोग प्रतिस्थापित किया गया है, लेकिन रीडायरेक्ट के लिए क्वेरी विफल रही :( कृपया इसे मैन्युअल रूप से करें',
'fixredirect': 'पुनर्निर्देशन ठीक किया'
},
'bn' : {
'mainTitle' : 'স্থানান্তর ও প্রতিস্থাপন' ,
'submit_acion' : 'জমা দিন' ,
'cancel_acion' : 'বাতিল' ,
'oldName' : 'চিত্রের পুরনো নাম:' ,
'newName' : 'চিত্রের নতুন নাম:' ,
'reason' : 'কারণ:',
'noredirect': 'পুনর্নির্দেশ রেখে দিবেন না (সতর্ক থাকুন)',
'notsamename': 'নতুন নামটি পুরানো নামের মত একই হওয়া উচিত নয়।',
'notempty': 'নতুন নাম খালি হতে পারবে না।',
'dontClose': 'এই বাক্সটি বন্ধ করবেন না',
'reload': 'পাতাটি পুনরায় লোড করুন',
'reloadInst': 'কোয়েরি শেষ হলে পাতাটি পুনরায় লোড করুন।',
'didnotmove': 'স্থানান্তর করা যায়নি :(',
'moveFile': 'চিত্র স্থানান্তর করা হয়েছে',
'failAftermove': 'চিত্র স্থানান্তর করা হয়েছে, কিন্তু চিত্রের ব্যবহারের কোয়েরি ব্যর্থ হয়েছে :( দয়া করে হাত দিয়ে ঠিক করুন',
'byUsing': '([[meta:Indic-TechCom/Tools|MoveAndReplace]] ব্যবহার করে)',
'notDone': 'সম্পন্ন হতে ব্যর্থ হয়েছে :( দয়া করে হাত দিয়ে ঠিক করুন',
'Done': 'সম্পন্ন হয়েছে',
'failBeforeReQu': 'চিত্রের ব্যবহার প্রতিস্থাপন করা হয়েছে, কিন্তু পুনর্নিদেশের জন্য কোয়েরি ব্যর্থ হয়েছে :( দয়া করে হাত দিয়ে ঠিক করুন',
'fixredirect': 'পুনর্নির্দেশ ঠিক করা হয়েছে'
}
};
function RunMoveAndReplace(){
var pageTitle = mw.config.get('wgTitle');
var Api = new mw.Api();
// Take from Gadget-libGlobalReplace.js
var sanitizeFileName = function (fn) {
return $.trim(fn.replace(/_/g, ' ')).replace(/^(?:File|Image)\:/, '');
};
// Take from Gadget-libGlobalReplace.js
var getFileRegEx = function (title, prefix) {
prefix = prefix || '[\\n\\[\\:\\=\\>\\|]\\s*';
return new RegExp('(' + prefix + ')[' + mw.RegExp.escape(title[0].toUpperCase() + title[0].toLowerCase()) + ']' + mw.RegExp.escape(
title.slice(1)).replace(/ /g, '[ _]'), 'g');
};
function MoveAndReplace( config ) {
MoveAndReplace.super.call( this, config );
}
OO.inheritClass( MoveAndReplace, OO.ui.ProcessDialog );
MoveAndReplace.static.title = i18nFormoveAndreplace[i18n_lang].mainTitle;
MoveAndReplace.static.name = 'moveAndreplace';
MoveAndReplace.static.actions = [
{ flags: [ 'primary', 'constructive' ], label: i18nFormoveAndreplace[i18n_lang].submit_acion , action: 'submit' },
{ flags: 'safe', label: i18nFormoveAndreplace[i18n_lang].cancel_acion }
];
MoveAndReplace.prototype.initialize = function () {
MoveAndReplace.super.prototype.initialize.call( this );
this.panel = new OO.ui.PanelLayout( { padded: true, expanded: false } );
this.content = new OO.ui.FieldsetLayout();
// TextInputWidget for oldFileName, newFileName, reason
this.oldFileName = new OO.ui.TextInputWidget( { disabled: true, value: pageTitle });
this.newFileName = new OO.ui.TextInputWidget( { value: pageTitle, required: true } );
this.reason = new OO.ui.TextInputWidget( { value: '' } );
// Add TextInputWidget in FieldLayout
this.field1 = new OO.ui.FieldLayout( this.oldFileName, { label: i18nFormoveAndreplace[i18n_lang].oldName, align: 'top' } );
this.field2 = new OO.ui.FieldLayout( this.newFileName, { label: i18nFormoveAndreplace[i18n_lang].newName, align: 'top' } );
this.field3 = new OO.ui.FieldLayout( this.reason, { label: i18nFormoveAndreplace[i18n_lang].reason, align: 'top' } );
// Add No redirect Check Widget only for sysop
if ( $.inArray( 'sysop', mw.config.get('wgUserGroups') ) ) {
this.notleaveredirect = new OO.ui.CheckboxInputWidget( { selected: false } );
this.field4 = new OO.ui.FieldLayout( this.notleaveredirect, { label: i18nFormoveAndreplace[i18n_lang].noredirect, align: 'inline' } );
this.content.addItems( [ this.field1, this.field2, this.field3, this.field4 ] );
} else {
this.content.addItems( [ this.field1, this.field2, this.field3 ] );
}
this.panel.$element.append( this.content.$element );
this.$body.append( this.panel.$element );
};
MoveAndReplace.prototype.getBodyHeight = function () {
return this.panel.$element.outerHeight( true );
};
MoveAndReplace.prototype.getActionProcess = function ( action ) {
// Trigger for submit button
if ( action === 'submit' ) {
var OldFileName = this.oldFileName.value;
var NewFileName = this.newFileName.value;
var Reason = this.reason.value;
var notLeaveRedirect = false;
if ( $.inArray( 'sysop', mw.config.get('wgUserGroups') ) ) {
notLeaveRedirect = this.notleaveredirect.isSelected();
}
if ( OldFileName == NewFileName ) {
mw.notify( i18nFormoveAndreplace[i18n_lang].notsamename, { type: 'error' } );
return new OO.ui.Process( function () { this.close( { action: action } ); }, this );
}
if ( NewFileName === '' ) {
mw.notify( i18nFormoveAndreplace[i18n_lang].notempty, { type: 'error' } );
return new OO.ui.Process( function () { this.close( { action: action } ); }, this );
}
OldFileName = sanitizeFileName(OldFileName);
NewFileName = sanitizeFileName(NewFileName);
var dialogforResult = $('<div id="dialogforResult"></div>' ).attr('title', i18nFormoveAndreplace[i18n_lang].dontClose);
$( dialogforResult ).append($( '<ul id="divforResult"></ul>' ));
$("body").append( dialogforResult );
$( dialogforResult ).dialog({
height: 300,
width: 400,
buttons: {
Submit: {
text: i18nFormoveAndreplace[i18n_lang].reload,
click: function(){
location.reload(true);
}
}
}
});
$( '#divforResult' ).append( $( '<p>' + i18nFormoveAndreplace[i18n_lang].reloadInst + '</p>' ) );
Api.postWithToken( 'csrf', {
action: 'move',
from: 'File:' + OldFileName,
to: 'File:' + NewFileName,
reason: Reason,
watchlist: 'nochange',
movetalk: true,
noredirect: notLeaveRedirect,
ignorewarnings: true
}).fail(function( move, errResp ){
$( '#divforResult' ).append( $( '<li style="color:red">' + i18nFormoveAndreplace[i18n_lang].didnotmove + '</li>' ) );
}).done( function() {
$( '#divforResult' ).append( $( '<li style="color:green">' + i18nFormoveAndreplace[i18n_lang].moveFile + '</li>' ) );
Api.get({
action: 'query',
format: 'json',
generator: 'imageusage',
giufilterredir: 'nonredirects',
giulimit: '5000',
prop: 'info|revisions',
inprop: 'protection',
rvprop: 'content|timestamp',
giuredirect: 1,
giutitle: 'File:' + pageTitle
}).fail(function( move, errResp ){
$( '#divforResult' ).append( $( '<li style="color:red">' + i18nFormoveAndreplace[i18n_lang].failAftermove + '</li>' ) );
}).done( function (obj) {
var localUsage = obj.query.pages;
$.each(localUsage, function (id, pg) {
var oldText = pg.revisions[0]['*'],
nwe1 = mw.libs.wikiDOM.nowikiEscaper(oldText),
newText = nwe1.secureReplace(getFileRegEx(OldFileName), '$1' + NewFileName).getText();
var summary = Reason + ' [[File:' + OldFileName + ']] → [[File:' + NewFileName + ']] ' + i18nFormoveAndreplace[i18n_lang].byUsing ;
var wpEditToken = mw.user.tokens.get( 'csrfToken' );
Api.post({
action: 'edit',
format: 'json',
title: pg.title,
text: newText,
editType: 'text',
watchlist: 'nochange',
minor: true,
summary: summary,
basetimestamp: pg.revisions[0].timestamp,
token: wpEditToken
}).fail(function( ){
$( '#divforResult' ).append( $( '<li style="color:red">'+ pg.title + ' ' + i18nFormoveAndreplace[i18n_lang].notDone + '</li>' ) );
}).done( function () {
$( '#divforResult' ).append( $( '<li style="color:green">'+ pg.title + ' ' + i18nFormoveAndreplace[i18n_lang].Done + '</i>' ) );
});
});
});
// Query and for redirects
Api.get({
action: 'query',
format: 'json',
generator: 'backlinks',
gblfilterredir: 'redirects',
gbllimit: '5000',
prop: 'revisions',
rvprop: 'content',
rvslots: 'main',
gbltitle: 'File:' + pageTitle
}).fail(function( ){
$( '#divforResult' ).append( $( '<li style="color:red">'+ i18nFormoveAndreplace[i18n_lang].failBeforeReQu +'</li>' ) );
}).done( function(redirectResult) {
if ( redirectResult.query && redirectResult.query.pages ) {
$.each( redirectResult.query.pages, function ( id, pg ) {
var wpEditToken = mw.user.tokens.get( 'csrfToken' );
var rv = pg.revisions[ 0 ]['slots']['main'][ '*' ];
Api.post({
action: 'edit',
format: 'json',
title: pg.title,
text: rv.replace( OldFileName, NewFileName ),
editType: 'text',
watchlist: 'nochange',
minor: true,
summary: i18nFormoveAndreplace[i18n_lang].fixredirect,
basetimestamp: pg.revisions[0].timestamp,
token: wpEditToken
}).fail(function( ){
$( '#divforResult' ).append( $( '<li style="color:red">'+ pg.title + ' ' + i18nFormoveAndreplace[i18n_lang].notDone + '</li>' ) );
}).done( function () {
$( '#divforResult' ).append( $( '<li style="color:green">' + pg.title + ' ' + i18nFormoveAndreplace[i18n_lang].Done + '</i>' ) );
} );
});
}
});
});
return new OO.ui.Process( function () { this.close( { action: action } ); }, this );
}
// Fallback to parent handler
return MoveAndReplace.super.prototype.getActionProcess.call( this, action );
};
var windowManager = new OO.ui.WindowManager();
$( 'body' ).append( windowManager.$element );
var moveAndreplace = new MoveAndReplace();
windowManager.addWindows( [ moveAndreplace ] );
windowManager.openWindow( moveAndreplace );
}
$(document).ready( function() {
// Load module for mw.libs.wikiDOM.nowikiEscaper
mw.loader.load( 'https://commons.wikimedia.org/w/index.php?title=MediaWiki:Gadget-libWikiDOM.js&action=raw&ctype=text/javascript' );
mw.loader.load( 'jquery.ui' );
// Check whether you are in file namespace or not
if (mw.config.get('wgNamespaceNumber') != 6 ) {
return;
}
// Set i18n for current user
if ( undefined === i18nFormoveAndreplace[i18n_lang] ) {
i18n_lang = 'en' ;
}
// Check whether the page is redirect or not
if ( mw.config.get('wgIsRedirect') === true ) {
return;
}
// Check current user's
var usergroup = mw.config.get('wgUserGroups');
if ( $.inArray( 'sysop', usergroup ) === -1 && $.inArray( 'filemover', usergroup ) === -1 ) {
return;
}
// This is for local wikis, commons already have the bunch of script and module
if ( mw.config.get('wgDBname') === 'commonswiki' ) {
return;
}
// Add a portlet link.
var link = mw.util.addPortletLink(
'p-views',
'#',
i18nFormoveAndreplace[i18n_lang].mainTitle
);
// Trigger for portlet link
$(link).click( function( e ) {
e.preventDefault();
RunMoveAndReplace();
});
});
} );