پودمان:Protection banner: تفاوت میان نسخه‌ها

جز ۱ نسخه واردشده
جز ۱ نسخه واردشده
 
(۱۰ نسخهٔ میانی ویرایش شده توسط ۶ کاربر نشان داده نشد)
خط ۵: خط ۵:
-- Initialise necessary modules.
-- Initialise necessary modules.
require('Module:No globals')
require('Module:No globals')
local convertString = require("Module:Numeral_converter").convert
local converter = require("Module:Numeral converter").convert
local newFileLink = require('Module:File link').new
local makeFileLink = require('Module:File link')._main
local effectiveProtectionLevel = require('Module:Effective protection level')._main
local effectiveProtectionLevel = require('Module:Effective protection level')._main
local effectiveProtectionExpiry = require('Module:Effective protection expiry')._main
local yesno = require('Module:Yesno')
local yesno = require('Module:Yesno')


خط ۱۶: خط ۱۷:
local CONFIG_MODULE = 'Module:Protection banner/config'
local CONFIG_MODULE = 'Module:Protection banner/config'


-- خط زیر از پایین صفحه به بالا آورده شده‌است بخاطر تابع p.replacePersianGreMonthName()
--------------------------------------------------------------------------------
local p = {}
-- Helper functions
--------------------------------------------------------------------------------


-- چون ممکنه نام ماه میلادی رو به فارسی کاربران بنویسند من این تابع رو تعریف کردم که به انگلیسی برگرداند تا خطای تاریخ نامعتبر ندهد.
-- چون ممکنه نام ماه میلادی رو به فارسی کاربران بنویسند من این تابع رو تعریف کردم که به انگلیسی برگرداند تا خطای تاریخ نامعتبر ندهد.
function p.replacePersianGreMonthName(frame)
local function replacePersianGreMonthName(frame)
getArgs = require('Module:Arguments').getArgs
getArgs = require('Module:Arguments').getArgs
local args = getArgs(frame)
local args = getArgs(frame)
خط ۲۸: خط ۳۰:
args[1] = mw.ustring.gsub(args[1], v, greMonth[k])
args[1] = mw.ustring.gsub(args[1], v, greMonth[k])
end
end
return convertString("en", args[1])
return converter("en", args[1])
end
end
--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------


-- از آنجا که تاریخ‌ها به صورت انگلیسی به پودمان داده می‌شوند، از mw.getLanguage('en') استفاده شده‌است
-- از آنجا که تاریخ‌ها به صورت انگلیسی به پودمان داده می‌شوند، از mw.getLanguage('en') استفاده شده‌است
خط ۴۸: خط ۴۶:


local function makeCategoryLink(cat, sort)
local function makeCategoryLink(cat, sort)
local nsText = mw.site.namespaces[14].name
if cat then
if cat and sort then
return mw.ustring.format(
return string.format(
'[[%s:%s|%s]]',
'[[%s:%s|%s]]',
nsText,
mw.site.namespaces[14].name,
cat,
cat,
sort
sort
)
)
elseif cat then
return string.format(
'[[%s:%s]]',
nsText,
cat
)
else
return ''
end
end
end
end
خط ۶۹: خط ۵۸:
-- Validation function for the expiry and the protection date
-- Validation function for the expiry and the protection date
local function validateDate(dateString, dateType)
local function validateDate(dateString, dateType)
-- در خط زیر جای mw.language.getContentLanguage() از mw.getLanguage('en') استفاده کردم.
if not lang then
lang = lang or mw.getLanguage('en')
-- در خط زیر جای mw.language.getContentLanguage() از mw.getLanguage('en') استفاده کردم.
local success, result = pcall(lang.formatDate, lang, 'U', p.replacePersianGreMonthName{convertString('en', dateString)})
lang = mw.getLanguage('en')
end
local success, result = pcall(lang.formatDate, lang, 'U', converter('en', dateString))
if success then
if success then
result = tonumber(result)
result = tonumber(result)
خط ۷۸: خط ۶۹:
end
end
end
end
error(string.format(
error(mw.ustring.format(
'%s ("%s") نامعتبر است',
'%s نامعتبر: %s',
dateType,
dateType,
tostring(dateString)
tostring(dateString)
خط ۸۶: خط ۷۷:


local function makeFullUrl(page, query, display)
local function makeFullUrl(page, query, display)
return string.format(
return mw.ustring.format(
'[%s %s]',
'[%s %s]',
tostring(mw.uri.fullUrl(page, query)),
tostring(mw.uri.fullUrl(page, query)),
خط ۹۳: خط ۸۴:
end
end


local function toTableEnd(t, pos)
-- Given a directed graph formatted as node -> table of direct successors,
-- Sends the value at position pos to the end of array t, and shifts the
-- get a table of all nodes reachable from a given node (though always
-- other items down accordingly.
-- including the given node).
return table.insert(t, table.remove(t, pos))
local function getReachableNodes(graph, start)
end
 
local function walkHierarchy(hierarchy, start)
local toWalk, retval = {[start] = true}, {}
local toWalk, retval = {[start] = true}, {}
while true do
while true do
-- Can't use pairs() since we're adding and removing things as we're iterating
-- Can't use pairs() since we're adding and removing things as we're iterating
local k = next(toWalk)
local k = next(toWalk) -- This always gets the "first" key
if k == nil then break end
if k == nil then
return retval
end
toWalk[k] = nil
toWalk[k] = nil
retval[k] = true
retval[k] = true
for _,v in ipairs(hierarchy[k]) do
for _,v in ipairs(graph[k]) do
if not retval[v] then
if not retval[v] then
toWalk[v] = true
toWalk[v] = true
خط ۱۱۳: خط ۱۰۳:
end
end
end
end
return retval
end
end


خط ۱۲۶: خط ۱۱۵:
edit = true,
edit = true,
move = true,
move = true,
autoreview = true
autoreview = true,
upload = true
}
}


خط ۱۴۹: خط ۱۳۹:
obj.action = args.action
obj.action = args.action
else
else
error(string.format(
error(mw.ustring.format(
'عمل ("%s") نامعتبر است',
'اقدام نامعتبر: %s',
tostring(args.action)
tostring(args.action)
), 3)
), 3)
خط ۱۵۷: خط ۱۴۷:
-- Set level
-- Set level
obj.level = args.demolevel or effectiveProtectionLevel(obj.action, obj.title)
obj.level = args.demolevel or effectiveProtectionLevel(obj.action, obj.title)
if obj.level == 'accountcreator' then
if not obj.level or (obj.action == 'move' and obj.level == 'autoconfirmed') then
-- Lump titleblacklisted pages in with template-protected pages,
-- since templateeditors can do both.
obj.level = 'templateeditor'
elseif not obj.level or (obj.action == 'move' and obj.level == 'autoconfirmed') then
-- Users need to be autoconfirmed to move pages anyway, so treat
-- Users need to be autoconfirmed to move pages anyway, so treat
-- semi-move-protected pages as unprotected.
-- semi-move-protected pages as unprotected.
خط ۱۶۸: خط ۱۵۴:


-- Set expiry
-- Set expiry
if args.expiry then
local effectiveExpiry = effectiveProtectionExpiry(obj.action, obj.title)
if cfg.indefStrings[args.expiry] then
if effectiveExpiry == 'infinity' then
obj.expiry = 'indef'
obj.expiry = 'indef'
elseif type(args.expiry) == 'number' then
elseif effectiveExpiry ~= 'unknown' then
obj.expiry = args.expiry
obj.expiry = validateDate(effectiveExpiry, 'تاریخ انقضا')
else
obj.expiry = validateDate(args.expiry, 'expiry date')
end
end
end


خط ۱۸۲: خط ۱۶۵:
obj.reason = mw.ustring.lower(args[1])
obj.reason = mw.ustring.lower(args[1])
if obj.reason:find('|') then
if obj.reason:find('|') then
error('دلایل نمی‌تواند شامل نویسه خط عمودی ("|") شود', 3)
error('دلایل نمی‌تواند شامل نویسه خط عمودی («|») باشد', 3)
end
end
end
end
خط ۱۸۸: خط ۱۷۱:
-- Set protection date
-- Set protection date
if args.date then
if args.date then
obj.protectionDate = validateDate(args.date, 'protection date')
obj.protectionDate = validateDate(args.date, 'تاریخ حفاظت')
end
end
خط ۲۴۱: خط ۲۲۴:


-- Get the namespace key fragment.
-- Get the namespace key fragment.
local namespaceFragment
local namespaceFragment = cfg.categoryNamespaceKeys[title.namespace]
do
if not namespaceFragment and title.namespace % 2 == 1 then
namespaceFragment = cfg.categoryNamespaceKeys[title.namespace]
namespaceFragment = 'talk'
if not namespaceFragment and title.namespace % 2 == 1 then
namespaceFragment = 'talk'
end
end
end
   
   
خط ۲۷۱: خط ۲۵۱:
-- instead.
-- instead.
--]]
--]]
if self.reason and cfg.reasonsWithNamespacePriority[self.reason] then
table.insert(order, table.remove(order, self.reason and cfg.reasonsWithNamespacePriority[self.reason] and 2 or 3))
-- table.insert(order, 3, table.remove(order, 2))
toTableEnd(order, 2)
else
toTableEnd(order, 3)
end
   
   
--[[
--[[
خط ۳۵۷: خط ۳۳۲:
end
end
return ''
return ''
end
function Protection:needsExpiry()
local cfg = self._cfg
local actionNeedsCheck = cfg.expiryCheckActions[self.action]
return not self.expiry and (
actionNeedsCheck or (
actionNeedsCheck == nil
and self.reason -- the old {{pp-protected}} didn't check for expiry
and not cfg.reasonsWithoutExpiryCheck[self.reason]
)
)
end
end


خط ۳۸۹: خط ۳۵۲:
local msg = self._cfg.msg
local msg = self._cfg.msg
local ret = { self:makeProtectionCategory() }
local ret = { self:makeProtectionCategory() }
if self:needsExpiry() then
ret[#ret + 1] = makeCategoryLink(
msg['tracking-category-expiry'],
self.title.text
)
end
if self:isIncorrect() then
if self:isIncorrect() then
ret[#ret + 1] = makeCategoryLink(
ret[#ret + 1] = makeCategoryLink(
خط ۴۴۳: خط ۴۰۰:
lang,
lang,
self._cfg.msg['expiry-date-format'] or 'xij xiF xiY', -- The 'xi' prefix is the prefix for displaying Iranian time
self._cfg.msg['expiry-date-format'] or 'xij xiF xiY', -- The 'xi' prefix is the prefix for displaying Iranian time
'@' .. p.replacePersianGreMonthName{convertString('en', tostring(num))}
'@' .. replacePersianGreMonthName{converter('en', tostring(num))}
)
)
if success then
if success then
خط ۵۲۳: خط ۴۸۰:
if level == 'autoconfirmed' then
if level == 'autoconfirmed' then
requestType = 'semi'
requestType = 'semi'
elseif level == 'extendedconfirmed' then
requestType = 'extended'
elseif level == 'templateeditor' then
elseif level == 'templateeditor' then
requestType = 'template'
requestType = 'template'
خط ۵۶۹: خط ۵۲۸:
msg = explanations[action].default.default
msg = explanations[action].default.default
else
else
error(string.format(
error(mw.ustring.format(
'نمی‌توان explanation blurb را برای عمل "%s"، سطح "%s" و کلید بحث "%s" پیدا کرد',
'نمی‌توان explanation blurb را برای عمل «%s»، سطح «%و کلید بحث «%پیدا کرد',
action,
action,
level,
level,
خط ۵۹۶: خط ۵۵۵:
function Blurb:_makeIntroBlurbParameter()
function Blurb:_makeIntroBlurbParameter()
if self._protectionObj:isTemporary() then
if self._protectionObj:isTemporary() then
return convertString('fa', replacePersianMonthName(self:_getExpandedMessage('intro-blurb-expiry')))
return converter('fa', replacePersianMonthName(self:_getExpandedMessage('intro-blurb-expiry')))
else
else
return self:_getExpandedMessage('intro-blurb-noexpiry')
return self:_getExpandedMessage('intro-blurb-noexpiry')
خط ۶۰۴: خط ۵۶۳:
function Blurb:_makeIntroFragmentParameter()
function Blurb:_makeIntroFragmentParameter()
if self._protectionObj:isTemporary() then
if self._protectionObj:isTemporary() then
return convertString('fa', replacePersianMonthName(self:_getExpandedMessage('intro-fragment-expiry')))
return converter('fa', replacePersianMonthName(self:_getExpandedMessage('intro-fragment-expiry')))
else
else
return self:_getExpandedMessage('intro-fragment-noexpiry')
return self:_getExpandedMessage('intro-fragment-noexpiry')
خط ۶۸۰: خط ۶۳۹:


function Blurb:_makeTalkPageParameter()
function Blurb:_makeTalkPageParameter()
return string.format(
return mw.ustring.format(
'[[%s:%s#%s|%s]]',
'[[%s:%s#%s|%s]]',
mw.site.namespaces[self._protectionObj.title.namespace].talk.name,
mw.site.namespaces[self._protectionObj.title.namespace].talk.name,
خط ۶۹۱: خط ۶۵۰:
function Blurb:_makeTooltipBlurbParameter()
function Blurb:_makeTooltipBlurbParameter()
if self._protectionObj:isTemporary() then
if self._protectionObj:isTemporary() then
return convertString('fa', replacePersianMonthName(self:_getExpandedMessage('tooltip-blurb-expiry')))
return converter('fa', replacePersianMonthName(self:_getExpandedMessage('tooltip-blurb-expiry')))
else
else
return self:_getExpandedMessage('tooltip-blurb-noexpiry')
return self:_getExpandedMessage('tooltip-blurb-noexpiry')
خط ۶۹۹: خط ۶۵۸:
function Blurb:_makeTooltipFragmentParameter()
function Blurb:_makeTooltipFragmentParameter()
if self._protectionObj:isTemporary() then
if self._protectionObj:isTemporary() then
return convertString('fa', replacePersianMonthName(self:_getExpandedMessage('tooltip-fragment-expiry')))
return converter('fa', replacePersianMonthName(self:_getExpandedMessage('tooltip-fragment-expiry')))
else
else
return self:_getExpandedMessage('tooltip-fragment-noexpiry')
return self:_getExpandedMessage('tooltip-fragment-noexpiry')
خط ۷۱۶: خط ۶۷۵:
-- Validate input.
-- Validate input.
if not key or not Blurb.bannerTextFields[key] then
if not key or not Blurb.bannerTextFields[key] then
error(string.format(
error(mw.ustring.format(
'"%s" زمینه پیکربندی بنر معتبری نیست',
'«%زمینه پیکربندی بنر معتبری نیست',
tostring(key)
tostring(key)
), 2)
), 2)
خط ۷۲۹: خط ۶۸۸:
msg = msg(self._protectionObj, self._args)
msg = msg(self._protectionObj, self._args)
if type(msg) ~= 'string' then
if type(msg) ~= 'string' then
error(string.format(
error(mw.ustring.format(
'خروجی نامناسب از تابع پیکربندی بنر همراه کلید "%s"'
'خروجی نامناسب از تابع پیکربندی بنر همراه کلید "%s"'
.. ' (رشته انتظار می‌رود، %s داده شده‌است)',
.. ' (رشته انتظار می‌رود، %s داده شده‌است)',
خط ۷۸۹: خط ۷۴۸:
end
end
return setmetatable(obj, BannerTemplate)
return setmetatable(obj, BannerTemplate)
end
function BannerTemplate:setImageWidth(width)
self._imageWidth = width
end
function BannerTemplate:setImageTooltip(tooltip)
self._imageCaption = tooltip
end
end


خط ۸۰۳: خط ۷۵۴:
or self._cfg.msg['image-filename-default']
or self._cfg.msg['image-filename-default']
or 'Transparent.gif'
or 'Transparent.gif'
return newFileLink(filename)
return makeFileLink{
:width(self._imageWidth or 20)
file = filename,
:alt(self._imageAlt)
size = (self.imageWidth or 20) .. 'px',
:link(self._imageLink)
alt = self._imageAlt,
:caption(self._imageCaption)
link = self._imageLink,
:render()
caption = self.imageCaption
}
end
end


خط ۸۲۰: خط ۷۷۲:
function Banner.new(protectionObj, blurbObj, cfg)
function Banner.new(protectionObj, blurbObj, cfg)
local obj = BannerTemplate.new(protectionObj, cfg) -- This doesn't need the blurb.
local obj = BannerTemplate.new(protectionObj, cfg) -- This doesn't need the blurb.
obj:setImageWidth(40)
obj.imageWidth = 40
obj:setImageTooltip(blurbObj:makeBannerText('alt')) -- Large banners use the alt text for the tooltip.
obj.imageCaption = blurbObj:makeBannerText('alt') -- Large banners use the alt text for the tooltip.
obj._reasonText = blurbObj:makeBannerText('text')
obj._reasonText = blurbObj:makeBannerText('text')
obj._explanationText = blurbObj:makeBannerText('explanation')
obj._explanationText = blurbObj:makeBannerText('explanation')
خط ۸۳۷: خط ۷۸۹:
type = 'protection',
type = 'protection',
image = self:renderImage(),
image = self:renderImage(),
text = string.format(
text = mw.ustring.format(
"'''%s'''%s",
"'''%s'''%s",
reasonText,
reasonText,
خط ۸۵۵: خط ۸۰۷:
function Padlock.new(protectionObj, blurbObj, cfg)
function Padlock.new(protectionObj, blurbObj, cfg)
local obj = BannerTemplate.new(protectionObj, cfg) -- This doesn't need the blurb.
local obj = BannerTemplate.new(protectionObj, cfg) -- This doesn't need the blurb.
obj:setImageWidth(20)
obj.imageWidth = 20
obj:setImageTooltip(blurbObj:makeBannerText('tooltip'))
obj.imageCaption = blurbObj:makeBannerText('tooltip')
obj._imageAlt = blurbObj:makeBannerText('alt')
obj._imageAlt = blurbObj:makeBannerText('alt')
obj._imageLink = blurbObj:makeBannerText('link')
obj._imageLink = blurbObj:makeBannerText('link')
obj._left = cfg.padlockPositions[protectionObj.action]
obj._indicatorName = cfg.padlockIndicatorNames[protectionObj.action]
or cfg.padlockPositions.default
or cfg.padlockIndicatorNames.default
or '55px'
or 'pp-default'
return setmetatable(obj, Padlock)
return setmetatable(obj, Padlock)
end
end


function Padlock:__tostring()
function Padlock:__tostring()
local root = mw.html.create('div')
local frame = mw.getCurrentFrame()
root
-- The nowiki tag helps prevent whitespace at the top of articles.
:addClass('metadata topicon nopopups')
return frame:extensionTag{name = 'nowiki'} .. frame:extensionTag{
:attr('id', 'protected-icon')
name = 'indicator',
:css{display = 'none', left = self._left}
args = {name = self._indicatorName},
:wikitext(self:renderImage())
content = self:renderImage()
return tostring(root)
}
end
end


خط ۸۷۸: خط ۸۳۰:
-- Exports
-- Exports
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local p = {}


function p._exportClasses()
function p._exportClasses()
خط ۸۹۲: خط ۸۴۶:
function p._main(args, cfg, title)
function p._main(args, cfg, title)
args = args or {}
args = args or {}
-- local args
if args['کوچک'] then args.small = args['کوچک'] end
if args['عمل'] then args.action = args['عمل'] end
if args['تاریخ'] then args.date = args['تاریخ'] end
if args['کاربر'] then args.user = args['کاربر'] end
if args['بخش'] then args.section = args['بخش'] end
if args['رده'] then args.category = args['رده'] end
if args['فقط رده'] then args.catonly = args['فقط رده'] end
cfg = cfg or require(CONFIG_MODULE)
cfg = cfg or require(CONFIG_MODULE)


خط ۸۹۸: خط ۸۶۲:
local ret = {}
local ret = {}


-- If a page's edit protection is equally or more restrictive than its protection from some other action,
-- If a page's edit protection is equally or more restrictive than its
-- then don't bother displaying anything for the other action (except categories).
-- protection from some other action, then don't bother displaying anything
if protectionObj.action == 'edit' or args.demolevel or not walkHierarchy(cfg.hierarchy, protectionObj.level)[effectiveProtectionLevel('edit', protectionObj.title)] then
-- for the other action (except categories).
if protectionObj.action == 'edit' or
args.demolevel or
not getReachableNodes(
cfg.hierarchy,
protectionObj.level
)[effectiveProtectionLevel('edit', protectionObj.title)]
then
-- Initialise the blurb object
-- Initialise the blurb object
local blurbObj = Blurb.new(protectionObj, args, cfg)
local blurbObj = Blurb.new(protectionObj, args, cfg)