مدیاویکی:Gadget-twinkleprod-2022.js

از ویکی‌پدیا، دانشنامهٔ آزاد

نکته: برای دیدن تغییرات، ممکن است نیاز باشد که حافظهٔ نهانی مرورگر خود را پس از انتشار پاک‌سازی کنید. گوگل کروم، فایرفاکس، مایکروسافت اج و سافاری: کلید Shift را نگه دارید و روی دکمهٔ Reload در نوار ابزار مرورگر کلیک کنید. برای آگاهی از جزئیات و نحوهٔ پاک‌سازی حافظهٔ نهانی سایر مرورگرها، صفحهٔ ویکی‌پدیا:میانگیر مرورگرتان را خالی کنید را ببینید.

// <nowiki>


(function($) {


/*
 ****************************************
 *** twinkleprod.js: PROD module
 ****************************************
 * Mode of invocation:     Tab ("PROD")
 * Active on:              Existing articles, files which are not redirects
 */

Twinkle.prod = function twinkleprod() {
	if (([0, 6].indexOf(mw.config.get('wgNamespaceNumber')) === -1) ||
		!mw.config.get('wgCurRevisionId') ||
		Morebits.isPageRedirect()) {
		return;
	}

	Twinkle.addPortletLink(Twinkle.prod.callback, 'حذف زمان‌دار', 'tw-prod', 'پیشنهاد حذف از طریق وپ:حز');
};

// Used in edit summaries, for comparisons, etc.
var namespace;

Twinkle.prod.callback = function twinkleprodCallback() {
	Twinkle.prod.defaultReason = Twinkle.getPref('prodReasonDefault');

	switch (mw.config.get('wgNamespaceNumber')) {
		case 0:
			namespace = 'مقاله';
			break;
		case 6:
			namespace = 'پرونده';
			break;
		// no default
	}

	var Window = new Morebits.simpleWindow(800, 410);
	Window.setTitle('حذف زمان‌دار (حز)');
	Window.setScriptName('توینکل');

	var form = new Morebits.quickForm(Twinkle.prod.callback.evaluate);

	if (namespace === 'مقاله') {
		Window.addFooterLink('سیاست حذف زمان‌دار', 'وپ:حز');
		Window.addFooterLink('سیاست حذف زمان‌دار زندگی‌نامه', 'وپ:حزز');
	} else { // if file
		Window.addFooterLink('سیاست حذف زمان‌دار', 'وپ:حز');
	}

	var field = form.append({
		type: 'field',
		label: 'نوع حذف زمان‌دار',
		id: 'prodtype_fieldset'
	});

	field.append({
		type: 'div',
		label: '', // Added later by Twinkle.makeFindSourcesDiv()
		id: 'twinkle-prod-findsources',
		style: 'margin-bottom: 5px; margin-top: -5px;'
	});

	field.append({
		type: 'radio',
		name: 'prodtype',
		event: Twinkle.prod.callback.prodtypechanged,
		list: [
			{
				label: 'حز (حذف زمان‌دار)',
				value: 'prod',
				checked: true,
				tooltip: 'حذف زمان‌دار معمولی، طبق [[وپ:حز]]'
			},
			{
				label: 'حزز (حذف زمان‌دار زندگی‌نامه زندگان بدون منبع)',
				value: 'prodblp',
				tooltip: 'حذف زمان‌دار زندگی‌نامه‌های افراد زندهٔ کاملاً بدون منبع طبق [[وپ:حزز]]'
			}
		]
	});

	// Placeholder fieldset to be replaced in Twinkle.prod.callback.prodtypechanged
	form.append({
		type: 'field',
		name: 'parameters'
	});

	Window.addFooterLink('ترجیحات حذف زمان‌دار', 'وپ:توینکل/ترجیحات#prod');
	Window.addFooterLink('راهنمای توینکل', 'وپ:توینکل/توضیحات#prod');
	Window.addFooterLink('ارائهٔ بازخورد', 'بوپ:توینکل');

	form.append({ type: 'submit', label: 'پیشنهاد حذف' });

	var result = form.render();
	Window.setContent(result);
	Window.display();

	// Hide fieldset for File PROD type since only normal PROD is allowed
	if (namespace !== 'مقاله') {
		$(result).find('#prodtype_fieldset').hide();
	}

	// Fake a change event on the first prod type radio, to initialize the type-dependent controls
	var evt = document.createEvent('Event');
	evt.initEvent('change', true, true);
	result.prodtype[0].dispatchEvent(evt);

};


Twinkle.prod.callback.prodtypechanged = function(event) {
	// prepare frame for prod type dependant controls
	var field = new Morebits.quickForm.element({
		type: 'field',
		label: 'پارامترها',
		name: 'parameters'
	});
	// create prod type dependant controls
	switch (event.target.values) {
		case 'prod':
			field.append({
				type: 'checkbox',
				list: [
					{
						label: 'آگاه‌سازی ایجادکنندهٔ صفحه در صورت امکان',
						value: 'notify',
						name: 'notify',
						tooltip: 'در صورت فعال بودن این گزینه، یک الگوی آگاه‌سازی در صفحهٔ بحث کاربر ایجادکننده قرار داده خواهد شد.',
						checked: true
					}
				]
			});
			field.append({
				type: 'textarea',
				name: 'reason',
				label: 'دلیل پیشنهاد حذف زمان‌دار:',
				value: Twinkle.prod.defaultReason
			});
			break;

		case 'prodblp':
			// first, remember the prod value that the user entered in the textarea, in case they want to switch back. We can abuse the config field for that.
			if (event.target.form.reason) {
				Twinkle.prod.defaultReason = event.target.form.reason.value;
			}

			field.append({
				type: 'checkbox',
				list: [
					{
						label: 'آگاه‌سازی ایجادکنندهٔ صفحه در صورت امکان',
						value: 'notify',
						name: 'notify',
						tooltip: 'ایجادکنندهٔ مقاله باید از این پیشنهاد حذف آگاه شود.',
						checked: true,
						disabled: true
					}
				]
			});
			// temp warning, can be removed down the line once BLPPROD is more established. Amalthea, May 2010.
			var boldtext = document.createElement('b');
			boldtext.appendChild(document.createTextNode('لطفاً دقت داشته باشید که تنها زندگی‌نامه‌های بدون منبع افراد زنده برای این برچسب مناسب هستند.'));
			field.append({
				type: 'div',
				label: boldtext
			});
			break;

		default:
			break;
	}

	Twinkle.makeFindSourcesDiv('#twinkle-prod-findsources');

	event.target.form.replaceChild(field.render(), $(event.target.form).find('fieldset[name="parameters"]')[0]);
};

// global params object, initially set in evaluate(), and
// modified in various callback functions
var params = {};

Twinkle.prod.callbacks = {
	checkPriors: function twinkleprodcheckPriors() {
		var talk_title = new mw.Title(mw.config.get('wgPageName')).getTalkPage().getPrefixedText();
		// Talk page templates for PROD-able discussions
		var blocking_templates = 'الگو:Old XfD multi|الگو:Old MfD|الگو:Oldffdfull|' + // Common prior XfD talk page templates
			'الگو:Oldpuffull|' + // Legacy prior XfD template
			'الگو:Olddelrev|' + // Prior DRV template
			'الگو:Old prod' +
			'الگو:پیشینه حذف زماندار|' + 
			'الگو:پیشینه حذف زمان‌دار|' +
			'الگو:حذف زمان‌دار قبلی|' +
			'الگو:پیشحذف قبلی|' +
			'الگو:پیشینه حذف زمان دار|' +
			'الگو:Old prod full';
		var query = {
			action: 'query',
			titles: talk_title,
			prop: 'templates',
			tltemplates: blocking_templates,
			format: 'json',
			tllimit: 12 // 12 templates above
		};

		var wikipedia_api = new Morebits.wiki.api('در حال بررسی صفحهٔ بحث برای نامزدی‌های پیشین', query);
		return wikipedia_api.post().then(function(apiobj) {
			var statelem = apiobj.statelem;

			// Check talk page for templates indicating prior XfD or PROD
			var templates = apiobj.getResponse().query.pages[0].templates;
			var numTemplates = templates && templates.length;
			if (numTemplates) {
				var template = templates[0].title;
				if (numTemplates === 1 && (
						template === 'الگو:Old prod' ||
						template === 'الگو:پیشینه حذف زماندار' ||
						template === 'الگو:پیشینه حذف زمان‌دار' ||
						template === 'الگو:پیشینه حذف زمان دار' ||
						template === 'الگو:حذف زمان‌دار قبلی' ||
						template === 'الگو:پیشحذف قبلی' ||
						template === 'الگو:Old prod full'
				)) {
					params.oldProdPresent = true; // Mark for reference later, when deciding if to endorse
				// if there are multiple templates, at least one of them would be a prior xfd template
				} else {
					statelem.warn('الگوی نبح پیشین در صفحهٔ بحث یافت شد؛ در حال صرف نظر از فرایند');
					return $.Deferred().reject();
				}
			}
		});
	},

	fetchCreationInfo: function twinkleprodFetchCreationInfo() {
		var def = $.Deferred();
		var ts = new Morebits.wiki.page(mw.config.get('wgPageName'), 'در حال جستجو برای ایجادکنندهٔ صفحه');
		ts.setFollowRedirect(true);  // for NPP, and also because redirects are ineligible for PROD
		ts.setLookupNonRedirectCreator(true); // Look for author of first non-redirect revision
		ts.lookupCreation(function(pageobj) {
			params.initialContrib = pageobj.getCreator();
			params.creation = pageobj.getCreationTimestamp();
			pageobj.getStatusElement().info('انجام شد، ' + params.initialContrib + ' یافت شد');
			def.resolve();
		}, def.reject);
		return def;
	},

	taggingPage: function twinkleprodTaggingPage() {
		var def = $.Deferred();

		var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), 'در حال برچسب زدن به صفحه');
		wikipedia_page.setFollowRedirect(true);  // for NPP, and also because redirects are ineligible for PROD
		wikipedia_page.load(function(pageobj) {
			var statelem = pageobj.getStatusElement();

			if (!pageobj.exists()) {
				statelem.error("به‌نظر می‌رسد که صفحه موجود نیست. شاید پیش از این حذف شده باشد.");
				// reject, so that all dependent actions like notifyAuthor() and
				// addToLog() are cancelled
				return def.reject();
			}

			var text = pageobj.getPageText();

			// Check for already existing deletion tags
			var tag_re = /{{(?:(db|حس)-?|(delete|حذف)\b|(article for deletion|نظرخواهی برای حذف)\/(dated|تاریخ‌دار)|AfDM|(ffd|پیشنهاد حذف تصویر)\b)|#invoke:RfD/i;
			if (tag_re.test(text)) {
				statelem.warn('این صفحه از پیش با یک الگوی حذف برچسب خورده است؛ در حال صرف نظر از فرایند');
				return def.reject();
			}


			// Remove tags that become superfluous with this action
			text = text.replace(/{{\s*(userspace draft|پیش‌نویس صفحه کاربری|mtc|(copy|move|انتقال) (to wikimedia commons|به ویکی‌انبار|به انبار)|(copy |move )?to ?commons)\s*(\|(?:{{[^{}]*}}|[^{}])*)?}}\s*/gi, '');
			var prod_re = /{{\s*(?:Prod blp|حز زنز|Proposed deletion|حذف زمان‌دار)\/(dated|پیغام)(?: files)?\s*\|(?:{{[^{}]*}}|[^{}])*}}/i;
			var summaryText;

			if (!prod_re.test(text)) {

				// Page previously PROD-ed
				if (params.oldProdPresent) {
					if (params.blp) {
						if (!confirm('نامزدی پیشین برای حذف زمان‌دار در صفحهٔ بحث یافت شد. آیا همچنان می‌خواهید به نامزد کردن صفحه برای حذف زمان‌دار زندگی‌نامه زندگان ادامه دهید؟ ')) {
							statelem.warn('حذف زمان‌دار پیشین در صفحهٔ بحث یافت شد؛ توسط کاربر لغو شد');
							return def.reject();
						}
						statelem.info('حذف زمان‌دار پیشین در صفحهٔ بحث یافت شد؛ در حال ادامه دادن');
					} else {
						statelem.warn('حذف زمان‌دار پیشین در صفحهٔ بحث یافت شد؛ در حال صرف نظر از فرایند');
						return def.reject();
					}
				}

				var tag;
				if (params.blp) {
					summaryText = 'پیشنهاد حذف مقاله طبق [[وپ:حزز]].';
					tag = '{{جا:حز زنز' + (params.usertalk ? '|help=off' : '') + '}}';
				} else {
					summaryText = 'پیشنهاد حذف ' + namespace + ' طبق [[وپ:حز]].';
					tag = '{{جا:حذف زمان‌دار|1=' + Morebits.string.formatReasonText(params.reason) + (params.usertalk ? '|help=off' : '') + '}}';
				}

				// Insert tag after short description or any hatnotes
				var wikipage = new Morebits.wikitext.page(text);
				text = wikipage.insertAfterTemplates(tag + '\n', Twinkle.hatnoteRegex).getText();

			} else {  // already tagged for PROD, so try endorsing it
				var prod2_re = /{{(?:تأیید حذف زمان‌دار|prod-?2|حذف زمان‌دار تأییدشده).*?}}/i;
				if (prod2_re.test(text)) {
					statelem.warn('صفحه از پیش با الگوهای {{حذف زمان‌دار}} و {{تأیید حذف زمان‌دار}} برچسب خورده است؛ در حال صرف نظر از فرایند');
					return def.reject();
				}
				var confirmtext = 'یک برچسب {{حذف زمان‌دار}} از پیش در این صفحه موجود است. \nآیا می‌خواهید یک برچسب {{تأیید حذف زمان‌دار}} به‌همراه توضیحات خود را به آن بیافزایید؟';
				if (params.blp && !/{{\s*(Prod blp\/dated|حذف زمان‌دار\/پیغام)/.test(text)) {
					confirmtext = 'یک برچسب غیرزندگی‌نامه‌ای {{حذف زمان‌دار}} در این مقاله یافت شد.\nآیا می‌خواهید یک برچسب {{تأیید حذف زمان‌دار}} با این توضیح که «این مقاله زندگی‌نامهٔ یک فرد زنده است که هیچ منبعی ندارد» به آن بیافزایید؟';
				}
				if (!confirm(confirmtext)) {
					statelem.warn('به درخواست کاربر لغو شد');
					return def.reject();
				}

				summaryText = 'تأیید حذف زمان‌دار بر پایهٔ [[وپ:حز' + (params.blp ? ' زنز' : '') + ']].';
				text = text.replace(prod_re, text.match(prod_re) + '\n{{تأیید حذف زمان‌دار|1=' + (params.blp ?
					'این مقاله [[وپ:حز زنز|زندگی‌نامهٔ یک فرد زنده است که هیچ منبعی ندارد]]' :
					Morebits.string.formatReasonText(params.reason)) + '}}\n');

				params.logEndorsing = true;
			}

			// curate/patrol the page
			if (Twinkle.getPref('markProdPagesAsPatrolled')) {
				pageobj.patrol();
			}

			pageobj.setPageText(text);
			pageobj.setEditSummary(summaryText);
			pageobj.setChangeTags(Twinkle.changeTags);
			pageobj.setWatchlist(Twinkle.getPref('watchProdPages'));
			pageobj.setCreateOption('nocreate');
			pageobj.save(def.resolve, def.reject);

		}, def.reject);
		return def;
	},

	addOldProd: function twinkleprodAddOldProd() {
		var def = $.Deferred();

		if (params.oldProdPresent || params.blp) {
			return def.resolve();
		}

		// Add {{Old prod}} to the talk page
		var oldprodfull = '{{پیشینه حذف زمان‌دار|نامزدکننده=' + mw.config.get('wgUserName') + '|تاریخ نامزدی={{جا:#زمان: j F Y}}}}\n';
		var talktitle = new mw.Title(mw.config.get('wgPageName')).getTalkPage().getPrefixedText();
		var talkpage = new Morebits.wiki.page(talktitle, 'در حال قرار دادن {{پیشینه حذف زمان‌دار}} در صفحهٔ بحث');
		talkpage.setPrependText(oldprodfull);
		talkpage.setEditSummary('افزودن {{پیشینه حذف زمان‌دار}}');
		talkpage.setChangeTags(Twinkle.changeTags);
		talkpage.setFollowRedirect(true);  // match behavior for page tagging
		talkpage.setCreateOption('recreate');
		talkpage.prepend(def.resolve, def.reject);
		return def;
	},

	notifyAuthor: function twinkleprodNotifyAuthor() {
		var def = $.Deferred();

		if (!params.blp && !params.usertalk) {
			return def.resolve();
		}

		// Disallow warning yourself
		if (params.initialContrib === mw.config.get('wgUserName')) {
			Morebits.status.info('آگاه‌سازی ایجادکننده', 'خودتان (' + params.initialContrib + ') این صفحه را ایجاد کرده‌اید؛ در حال چشم‌پوشی از آگاه‌سازی');
			return def.resolve();
		}
		// [[Template:Proposed deletion notify]] supports File namespace
		var notifyTemplate;
		if (params.blp) {
			notifyTemplate = 'هشدار حذف زماندار زندگی‌نامه زندگان';
		} else {
			notifyTemplate = 'هشدار حذف زمان‌دار';
		}
		var notifytext = '\n{{جا:' + notifyTemplate + '|1=' + Morebits.pageNameNorm + '|اهمیت=' + params.reason + '}} ~~~~';

		var usertalkpage = new Morebits.wiki.page('بحث کاربر:' + params.initialContrib, 'در حال آگاه‌سازی مشارکت‌کنندهٔ اولیه (' + params.initialContrib + ')');
		usertalkpage.setAppendText(notifytext);
		usertalkpage.setEditSummary('آگاه‌سازی: پیشنهاد حذف [[:' + Morebits.pageNameNorm + ']].');
		usertalkpage.setChangeTags(Twinkle.changeTags);
		usertalkpage.setCreateOption('recreate');
		usertalkpage.setFollowRedirect(true, false);
		usertalkpage.append(function onNotifySuccess() {
			// add nomination to the userspace log, if the user has enabled it
			params.logInitialContrib = params.initialContrib;
			def.resolve();
		}, def.resolve); // resolves even if notification was unsuccessful

		return def;
	},

	addToLog: function twinkleprodAddToLog() {
		if (!Twinkle.getPref('logProdPages')) {
			return $.Deferred().resolve();
		}
		var usl = new Morebits.userspaceLogger(Twinkle.getPref('prodLogPageName'));
		usl.initialText =
			"این صفحه فهرستی از مواردی که این کاربر با استفاده از [[وپ:توینکل|توینکل]] برای [[وپ:حز|حذف زمان‌دار]] نامزد کرده‌است را نشان می‌دهد.\n\n" + // localized
			'اگر نمی‌خواهید موارد جدید به این سیاهه اضافه شوند، آن را از طریق [[وپ:توینکل تر|ترجیحات توینکل]] غیرفعال کنید' + // localized
			' و اگر می‌خواهید سیاهه کلاً حذف شود آن را بر اساس معیار [[وپ:محس#ک۱|ک۱]] نامزد حذف سریع کنید.\n'; // localized

		var logText = '# [[:' + Morebits.pageNameNorm + ']]';
		var summaryText;
		// If a logged file is deleted but exists on commons, the wikilink will be blue, so provide a link to the log
		logText += namespace === 'پرونده' ? ' ([{{نشانی‌کامل:ویژه:سیاهه‌ها|page=' + mw.util.wikiUrlencode(mw.config.get('wgPageName')) + '}} سیاهه]): ' : ': ';
		if (params.logEndorsing) {
			logText += 'تأیید حذف زمان‌دار' + (params.blp ? 'زندگی‌نامه زندگان' : '') + '. ~~~~~';
			if (params.reason) {
				logText += "\n#* '''دلیل''': " + params.reason + '\n';
			}
			summaryText = 'ثبت سیاههٔ نامزد کردن [[:' + Morebits.pageNameNorm + ']] برای حذف زمان‌دار.';
		} else {
			logText += ' – حذف زمان‌دار' + (params.blp ? ' زندگی‌نامه زندگان' : '');
			if (params.logInitialContrib) {
				logText += '؛ {{userv|' + params.logInitialContrib + '}} آگاه شد';
			}
			logText += ' ~~~~~\n';
			if (!params.blp && params.reason) {
				logText += "#* '''دلیل''': " + Morebits.string.formatReasonForLog(params.reason) + '\n';
			}
			summaryText = 'ثبت سیاههٔ نامزد کردن [[:' + Morebits.pageNameNorm + ']] برای حذف زمان‌دار.';
		}
		usl.changeTags = Twinkle.changeTags;

		return usl.log(logText, summaryText);
	}

};

Twinkle.prod.callback.evaluate = function twinkleprodCallbackEvaluate(e) {
	var form = e.target;
	var input = Morebits.quickForm.getInputData(form);

	params = {
		usertalk: input.notify || input.prodtype === 'prodblp',
		blp: input.prodtype === 'prodblp',
		reason: input.reason || '' // using an empty string here as fallback will help with prod-2.
	};

	if (!params.blp && !params.reason) {
		if (!confirm('شما فیلد دلیل را خالی گذاشته‌اید؛ آیا واقعاً می‌خواهید بدون ارائهٔ دلیل ادامه دهید؟')) {
			return;
		}
	}

	Morebits.simpleWindow.setButtonsEnabled(false);
	Morebits.status.init(form);

	var tm = new Morebits.taskManager();
	var cbs = Twinkle.prod.callbacks; // shortcut reference, cbs for `callbacks`

	// Disable Morebits.wiki.numberOfActionsLeft system
	Morebits.wiki.numberOfActionsLeft = 1000;

	// checkPriors() and fetchCreationInfo() have no dependencies, they'll run first
	tm.add(cbs.checkPriors, []);
	tm.add(cbs.fetchCreationInfo, []);
	// tag the page once we're clear of the pre-requisites
	tm.add(cbs.taggingPage, [ cbs.checkPriors, cbs.fetchCreationInfo ]);
	// notify the author once we know who's the author, and also wait for the
	// taggingPage() as we don't need to notify if tagging was not done, such as
	// there was already a tag and the user chose not to endorse.
	tm.add(cbs.notifyAuthor, [ cbs.fetchCreationInfo, cbs.taggingPage ]);
	// oldProd needs to be added only if there wasn't one before, so need to wait
	// for checkPriors() to finish. Also don't add oldProd if tagging itself was
	// aborted or unsuccessful
	tm.add(cbs.addOldProd, [ cbs.taggingPage, cbs.checkPriors ]);
	// add to log only after notifying author so that the logging can be adjusted if
	// notification wasn't successful. Also, don't run if tagging was not done.
	tm.add(cbs.addToLog, [ cbs.notifyAuthor, cbs.taggingPage ]);
	// All set, go!
	tm.execute().then(function() {
		Morebits.status.actionCompleted('برچسب زدن کامل شد');
		setTimeout(function () {
			window.location.href = mw.util.getUrl(mw.config.get('wgPageName'));
		}, Morebits.wiki.actionCompleted.timeOut);
	});
};

Twinkle.addInitCallback(Twinkle.prod, 'prod');
})(jQuery);


// </nowiki>