Module:Protection banner: Difference between revisions
Content added Content deleted
Enwikipedia>Mr. Stradivarius (expand the Image class) |
Enwikipedia>Mr. Stradivarius (start converting the getCategoryName function) |
||
Line 200: | Line 200: | ||
function Category:initialize() |
function Category:initialize() |
||
end |
|||
function Category:setName(name) |
|||
self._name = name |
|||
end |
end |
||
Line 219: | Line 223: | ||
local ProtectionCategory = Category:subclass('ProtectionCategory') |
local ProtectionCategory = Category:subclass('ProtectionCategory') |
||
function ProtectionCategory:setName(name, configObj, protectionStatusObj, namespace) |
|||
--[[ |
|||
-- Sets the protection category. If a category name is not provided, this |
|||
-- method gets a category name from the module config, given a combination |
|||
-- of the protection type, the protection level, the namespace number, the |
|||
-- reason for protection, and the expiry date. |
|||
--]] |
|||
local cats = configObj:getConfigTable('categories') |
|||
-- Get the namespace category key from the namespace number. |
|||
local nskey |
|||
do |
|||
local categoryNamespaces = configObj:getConfigTable('categoryNamespaces') |
|||
if not namespace or type(namespace) ~= 'number' then |
|||
nskey = nil |
|||
else |
|||
nskey = categoryNamespaces[ns] |
|||
if not nskey and ns % 2 == 1 then |
|||
nskey = 'talk' |
|||
end |
|||
end |
|||
end |
|||
--[[ |
|||
-- 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, keypos = 5, val = expiry}, |
|||
namespace = {order = 2, keypos = 3, val = nskey}, |
|||
reason = {order = 3, keypos = 4, val = reason}, |
|||
level = {order = 4, keypos = 2, val = level}, |
|||
action = {order = 5, keypos = 1, val = action} |
|||
} |
|||
--[[ |
|||
-- Load the category order configuration for the reason specified. |
|||
-- The configuration is stored in the categoryOrder field of each reason |
|||
-- subtable of cfg.reasons. If the value is a table, then the order is the |
|||
-- values specified in the table. If the value is a string, then 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 the value is of |
|||
-- any other type then the canonical order is used. |
|||
--]] |
|||
local reasonTable = reason and cfg.reasons[reason] |
|||
local categoryOrder = reasonTable and reasonTable.categoryOrder |
|||
local categoryOrderType = type(categoryOrder) |
|||
local configOrder = {} |
|||
if categoryOrderType == 'table' then |
|||
local dupes = {} |
|||
for i = 1, 5 do |
|||
local propertiesKey = categoryOrder[i] |
|||
if not propertiesKey then |
|||
local msg = 'no entry found for key ' |
|||
.. i |
|||
.. ' in the cfg.reasons.' |
|||
.. reason |
|||
.. '.categoryOrder table' |
|||
error(msg) |
|||
end |
|||
local property = properties[propertiesKey] |
|||
if not property then |
|||
local msg = 'invalid value "' |
|||
.. propertiesKey |
|||
.. '" detected in the cfg.reasons.' |
|||
.. reason |
|||
.. '.categoryOrder table' |
|||
error(msg) |
|||
end |
|||
if dupes[propertiesKey] then |
|||
local msg = 'duplicate values "' |
|||
.. propertiesKey |
|||
.. '" detected in the cfg.reasons.' |
|||
.. reason |
|||
.. '.categoryOrder table' |
|||
error(msg) |
|||
else |
|||
dupes[propertiesKey] = true |
|||
end |
|||
configOrder[i] = property |
|||
end |
|||
else |
|||
for propertiesKey, t in pairs(properties) do |
|||
configOrder[t.order] = t |
|||
end |
|||
if categoryOrderType == 'string' then |
|||
local property = properties[categoryOrder] |
|||
if not property then |
|||
local msg = '"' |
|||
.. categoryOrder |
|||
.. '" is not a valid value of cfg.reasons.' |
|||
.. reason |
|||
.. '.categoryOrder' |
|||
error(msg) |
|||
end |
|||
toTableEnd(configOrder, property.order) |
|||
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 active, inactive = {}, {} |
|||
for i, t in ipairs(configOrder) do |
|||
if t.val then |
|||
active[#active + 1] = t |
|||
else |
|||
inactive[#inactive + 1] = t |
|||
end |
|||
end |
|||
local noActive = #active |
|||
local attemptOrder = active |
|||
for i, t in ipairs(inactive) do |
|||
attemptOrder[#attemptOrder + 1] = t |
|||
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. |
|||
--]] |
|||
for i = 1, 2^noActive do |
|||
local key = {} |
|||
for j, t in ipairs(attemptOrder) do |
|||
if j > noActive then |
|||
key[t.keypos] = 'all' |
|||
else |
|||
local quotient = i / 2 ^ (j - 1) |
|||
quotient = math.ceil(quotient) |
|||
if quotient % 2 == 1 then |
|||
key[t.keypos] = t.val |
|||
else |
|||
key[t.keypos] = 'all' |
|||
end |
|||
end |
|||
end |
|||
key = table.concat(key, '-') |
|||
local attempt = cats[key] |
|||
if attempt then |
|||
return attempt |
|||
end |
|||
end |
|||
error( |
|||
'No category match found;' |
|||
.. ' please define the category for key "all-all-all-all-all"' |
|||
) |
|||
end |
|||
-------------------------------------------------------------------------------- |
-------------------------------------------------------------------------------- |