Modul:Protection banner: Unterschied zwischen den Versionen
move the category methods to the Protection class, and get rid of all the category objects
(allow passing the config object into the exportToLua and exportToWiki functions) |
(move the category methods to the Protection class, and get rid of all the category objects) |
||
Zeile 19: | Zeile 19: | ||
function Protection:initialize(args, configObj, titleObj) | function Protection:initialize(args, configObj, titleObj) | ||
self._configObj = configObj | |||
self._titleObj = titleObj | |||
-- Set action | -- Set action | ||
do | do | ||
Zeile 123: | Zeile 126: | ||
function Protection:isProtected() | function Protection:isProtected() | ||
return self.level ~= '*' | return self.level ~= '*' | ||
end | |||
function Protection._makeCategoryLink(cat) | |||
-- Static method for rendering category wikitext. | |||
if cat then | |||
return string.format( | |||
'[[%s:%s]]', | |||
mw.site.namespaces[14].name, | |||
cat | |||
) | |||
else | |||
return '' | |||
end | |||
end | |||
function Protection:makeProtectionCategory() | |||
local configObj = self._configObj | |||
local titleObj = self._titleObj | |||
-- Exit if the page is not protected. | |||
if not self:isProtected() then | |||
return '' | |||
end | |||
-- Get the expiry. | |||
local expiry = self.expiry | |||
if type(expiry) == 'number' then | |||
expiry = 'temp' | |||
elseif expiry ~= 'indef' then | |||
expiry = nil | |||
end | |||
-- Get the namespace category key. | |||
local nskey | |||
do | |||
local namespace = titleObj.namespace | |||
local categoryNamespaces = configObj.cfg.categoryNamespaceKeys | |||
nskey = categoryNamespaces[namespace] | |||
if not nskey and namespace % 2 == 1 then | |||
nskey = 'talk' | |||
end | |||
end | |||
-- Get the other inputs. | |||
local reason = self.reason | |||
local action = self.action | |||
local level = self.level | |||
--[[ | |||
-- Define the properties table. Each property is a table containing the | |||
-- canonical order that the property is tested in, the position the | |||
-- property has in the category key strings, and the property value itself. | |||
--]] | |||
local properties = { | |||
expiry = {order = 1, val = expiry}, | |||
namespace = {order = 2, val = nskey}, | |||
reason = {order = 3, val = reason}, | |||
level = {order = 4, val = level}, | |||
action = {order = 5, val = action} | |||
} | |||
--[[ | |||
-- Apply the category order configuration, if any. The configuration value | |||
-- will be a property string, e.g. 'reason', 'namespace', etc. The property | |||
-- corresponding to that string is tested last (i.e. it is the most | |||
-- important, because it keeps its specified value the longest) and the | |||
-- other properties are tested in the canonical order. If no configuration | |||
-- value is specified then the canonical order is used. | |||
--]] | |||
local configOrder = {} | |||
do | |||
local reasonsWithNamespacePriority = configObj.cfg.reasonsWithNamespacePriority | |||
local namespaceFirst = reason and reasonsWithNamespacePriority[reason] or false | |||
for propertiesKey, t in pairs(properties) do | |||
configOrder[t.order] = t | |||
end | |||
if namespaceFirst then | |||
-- Swap namespace and reason around. | |||
local namespaceTable = table.remove(configOrder, 2) | |||
table.insert(configOrder, 3, namespaceTable) | |||
end | |||
end | |||
--[[ | |||
-- Define the attempt order. Properties with no value defined are moved | |||
-- to the end, where they will later be given the value "all". This is | |||
-- to cut down on the number of table lookups in the cats table, which | |||
-- grows exponentially with the number of properties with valid values. | |||
-- We keep track of the number of active properties with the noActive | |||
-- parameter. | |||
--]] | |||
local noActive, attemptOrder | |||
do | |||
local active, inactive = {}, {} | |||
for i, t in ipairs(configOrder) do | |||
if t.val then | |||
active[#active + 1] = t | |||
else | |||
inactive[#inactive + 1] = t | |||
end | |||
end | |||
noActive = #active | |||
attemptOrder = active | |||
for i, t in ipairs(inactive) do | |||
attemptOrder[#attemptOrder + 1] = t | |||
end | |||
end | |||
--[[ | |||
-- Check increasingly generic key combinations until we find a match. | |||
-- If a specific category exists for the combination of properties | |||
-- we are given, that match will be found first. If not, we keep | |||
-- trying different key combinations until we match using the key | |||
-- "all-all-all-all-all". | |||
-- | |||
-- To generate the keys, we index the property subtables using a | |||
-- binary matrix with indexes i and j. j is only calculated up to | |||
-- the number of active properties. For example, if there were three | |||
-- active properties, the matrix would look like this, with 0 | |||
-- corresponding to the string "all", and 1 corresponding to the | |||
-- val field in the property table: | |||
-- | |||
-- j 1 2 3 | |||
-- i | |||
-- 1 1 1 1 | |||
-- 2 0 1 1 | |||
-- 3 1 0 1 | |||
-- 4 0 0 1 | |||
-- 5 1 1 0 | |||
-- 6 0 1 0 | |||
-- 7 1 0 0 | |||
-- 8 0 0 0 | |||
-- | |||
-- Values of j higher than the number of active properties are set | |||
-- to the string "all". | |||
-- | |||
-- A key for the category table is constructed for each value of i. | |||
-- The correct position of the value in the key is determined by the | |||
-- pos field in the property table. | |||
--]] | |||
local cats = configObj.cfg.protectionCategories | |||
local cat | |||
for i = 1, 2^noActive do | |||
local key = {} | |||
for j, t in ipairs(attemptOrder) do | |||
if j > noActive then | |||
key[t.order] = 'all' | |||
else | |||
local quotient = i / 2 ^ (j - 1) | |||
quotient = math.ceil(quotient) | |||
if quotient % 2 == 1 then | |||
key[t.order] = t.val | |||
else | |||
key[t.order] = 'all' | |||
end | |||
end | |||
end | |||
key = table.concat(key, '-') | |||
local attempt = cats[key] | |||
if attempt then | |||
cat = attempt | |||
break | |||
end | |||
end | |||
return self._makeCategoryLink(cat) | |||
end | |||
function Protection:makeExpiryCategory() | |||
local reasonsWithoutExpiryCheck = self._configObj.cfg.reasonsWithoutExpiryCheck | |||
local expiryCheckActions = self._configObj.cfg.expiryCheckActions | |||
local cat | |||
if not self.expiry | |||
and expiryCheckActions[self.action] | |||
and self.reason -- the old {{pp-protected}} didn't check for expiry | |||
and not reasonsWithoutExpiryCheck[self.reason] | |||
then | |||
cat = self._configObj.msg['tracking-category-expiry'] | |||
end | |||
return self._makeCategoryLink(cat) | |||
end | |||
function Protection:makeErrorCategory() | |||
local configObj = self._configObj | |||
local cat | |||
if not self:isProtected() | |||
or type(self.expiry) == 'number' and self.expiry < os.time() | |||
then | |||
cat = configObj.msg['tracking-category-incorrect'] | |||
end | |||
return self._makeCategoryLink(cat) | |||
end | |||
function Protection:makeTemplateCategory() | |||
local configObj = self._configObj | |||
local titleObj = self._titleObj | |||
local cat | |||
if self.level == 'templateeditor' | |||
and ( | |||
(self.action ~= 'edit' and self.action ~= 'move') | |||
or (titleObj.namespace ~= 10 and titleObj.namespace ~= 828) | |||
) | |||
then | |||
cat = configObj.msg['tracking-category-template'] | |||
end | |||
return self._makeCategoryLink(cat) | |||
end | end | ||
Zeile 660: | Zeile 871: | ||
:wikitext(self:renderImage()) | :wikitext(self:renderImage()) | ||
return tostring(root) | return tostring(root) | ||
end | end | ||
Zeile 986: | Zeile 932: | ||
-- Render the categories | -- Render the categories | ||
if yesno(args.category) ~= false then | if yesno(args.category) ~= false then | ||
ret[#ret + 1] = protectionObj:makeProtectionCategory() | |||
ret[#ret + 1] = protectionObj:makeExpiryCategory() | |||
ret[#ret + 1] = protectionObj:makeErrorCategory() | |||
ret[#ret + 1] = protectionObj:makeTemplateCategory() | |||
end | end | ||
Zeile 1.008: | Zeile 949: | ||
Banner = Banner, | Banner = Banner, | ||
Padlock = Padlock, | Padlock = Padlock, | ||
} | } | ||
end | end | ||
return ProtectionBanner | return ProtectionBanner |