Jump to content

Module:Votings-global

Permanently protected module
From Meta, a Wikimedia project coordination wiki
Module documentation

Usage

See Template:Votings-global.


-- For attribution: [[:vi:Module:CurrentCandidateList]]
local p = {}

local perm = {'GRN', 'GP', 'GS', 'GR'}

local title = 'Steward requests/Global permissions' -- Here's our title...
local content = mw.title.new(title):getContent() -- ...and here's our content.

function p.list(frame) -- {{#invoke:Votings-global|list}} will output a pipe-separated list of numbers of requests.
	local list = { -- Data.
		GR = {
			pat = 'roll%s*backe?r?',
			num = 0,
			boo = false
		},
		GS = {
			pat = 'sysop',
			num = 0,
			boo = false
		},
		GRN = {
			pat = 'renamer?',
			num = 0,
			boo = false
		},
		GP = {
			num = 0
		}
	}
	local b = { -- Originally "b" means "boolean". Now it's a table that contains boolean values.
		a = false,
		b = false,
		c = {}
	}
	-- These statuses mark the requests as no longer active.
	local s = {'done', '+', 'cannot', 'notdone', '-', 'alreadydone', 'withdrawn', 'redundant'}
	
	for k, v in pairs(list) do -- Iterate the "list" table.
		if k ~= 'GP' then -- "GP" stands for "Other global permissions". The old template used it; I don't know why.
			for l in mw.text.gsplit(content, '\n') do -- Iterate lines of SRGP
				if p.catch(l, list, k) then -- See p.catch (case 1), then come back here.
					list[k].boo = true -- We're going through GR/GS/GRN h3 section(s).
				end
				if list[k].boo and mw.ustring.match(l, '%s*%|%s*status%s*=%s*.*') and not p.inc(p.status(l), s) then -- See p.inc and p.status.
					list[k].num = list[k].num + 1 -- If the line contains status param and its value is not one of "s", add one to total.
					list[k].boo = false -- One subsection can only contain one request.
				elseif mw.ustring.match(l, '===%s*.+%s*===') and not p.catch(l, list, k) then -- No longer in that subsection.
					list[k].boo = false -- Nothing caught, nothing added.
				end
			end
		else
			for l in mw.text.gsplit(content, '\n') do -- Iterate lines of SRGP, again.
				if mw.ustring.match(l, '==%s*Requests%s*for%s*other%s*global%s*permissions%s*==') ~= nil then -- We're going through the h2 section for other GPs.
					b.a = true -- Use a boolean value to remark that.
				end
				if p.catch(l) ~= nil then -- Case 2 of p.match, which returns <username>[|<username>] and let us know if we're in a subsection.
					b.b = true -- Subsection remarked.
					b.c = p.ins(b.c, p.getun(p.catch(l))) -- Add the name caught to a table. This doesn't affect anything.
				end
				if b.a and b.b and mw.ustring.match(l, '%s*%|%s*status%s*=%s*.*') and not p.inc(p.status(l), s) then -- Get status.
					list.GP.num = list.GP.num + 1 -- Found one, add it to our stock.
					b.b = false -- No longer in subsection.
				end
				if mw.ustring.match(l, '==%s*.+%s*==<!--%s*.+%s*-->') ~= nil then -- This is meant to catch == See also == section.
					b.a = false -- We're out of RfOGP, stop.
				end
			end
		end
	end
	
	if frame then -- If a parameter was specified,
		if frame.args[1] == 'GR' then -- outputs number of GR requests...
			return list.GR.num
		elseif frame.args[1] == 'GS' then -- ...GS...
			return list.GS.num
		elseif frame.args[1] == 'GRN' then -- ...GRN...
			return list.GRN.num
		elseif frame.args[1] == 'GP' then -- ...and the rest, accordingly.
			return list.GP.num
		end
	else -- Else, returns a pipe-separated list.
		local a = {} -- New table
		for k, v in pairs(list) do
			table.insert(a, list[k].num) -- Add all numbers to the table
		end
		return table.concat(a, '|')
	end
end

function p.main() -- Main function
	local num = mw.text.gsplit(p.list(), '|') -- p.list() returns a pipe-separated list (\d+|\d+|\d+|\d+); split it up.
	local req = {}
	local s = { -- "s" stands for `s`ection.
		'Requests for global rename permissions',
		'Requests for other global permissions',
		'Requests for global sysop permissions',
		'Requests for global rollback permissions'
	}
	local i = { -- Table for numbers.
		t = { -- "t" stands for `t`rue.
			0
		},
		f = { -- "f" stands for `f`alse.
			0
		},
		i = 0 -- "i" stands for `i`ndex.
	}
	
	for n in num do -- Iterate "num".
		i.i = i.i + 1 -- Add 1 to index before going.
		if tonumber(n) > 0 then -- Outputs something is number of requests is not 0.
			table.insert(req, '[[' .. title .. '#' .. s[i.i] .. '|' .. n .. '&nbsp;Rf' .. perm[i.i] .. ']]')
			table.insert(i.t, i.i) -- This is irrelevant; just ignore it.
		else
			table.insert(i.f, i.i) -- Idem.
		end
	end
	if #req > 0 then -- If our total is not 0,
		return '&nbsp;&bull; <b>' .. table.concat(req, '</b>&nbsp;&bull; <b>') .. '</b>' -- ...adds requests up.
	else
		return '' -- No requests atm, return nothing.
	end
end

function p.catch(l, list, k) -- This is meant to be a template for two cases: GR/GS/GRN and GP
	local j -- Splitting cases
	if list ~= nil
		then j = 1
	else
		j = 2
	end
	
	if j == 1 then -- If case 1, everything this function needs were provided. Returns a value (which we don't have to care about) or nil.
		return mw.ustring.match(l, '===%s*[Gg]lobal%s*' .. list[k].pat .. '%s*for%s*%[%[%s*[Uu][Ss][Ee][Rr]%s*:%s*..-%]%]%s*===')
	else -- Returns <username>[|<username>]. Some people writes [[User:Foo]] instead of [[User:Foo|Foo]], hence the function.
		return mw.ustring.match(l, '===%s*[^=]-for%s*%[%[%s*[Uu][Ss][Ee][Rr]%s*:%s*(..-)%]%][^=]-%s*===')
	end
end

function p.status(str) -- Return value of |status= parameter, or the first word of the hidden comment <!--don't change this line-->.
	return mw.ustring.lower(
		mw.ustring.gsub(
			mw.ustring.match(
				mw.ustring.match(str, '%s*%|%s*status%s*=%s*(.*)'),
				'([%w ]+)'
			) or '',
			'%s*',
			''
		)
	)
end

function p.inc(e, a) -- Return a boolean value if "e" is an `e`lement (key/value) of table (`a`rray) "a".
	local b = false
	for k, v in pairs(a) do
		if k == e or v == e then
			b = true
		end
	end
	return b
end

function p.split(str, sep) -- Splitting things up. "str" stands for `str`ing and "sep" stands for `sep`arator.
	local t = {}
	if sep == nil then
		sep = '%s*([^|]+)%s*'
	end
	for str in string.gmatch(str, sep) do
		table.insert(t, str)
	end
	return t
end

function p.getun(un, i) -- Outputs <username> from <username>[|<username>]. Generally this is irrelevant to our final result.
	local id
	if i ~= nil then
		id = i
	else
		id = 1
	end
	return p.split(un)[id]:gsub('%s+', ' ')
end

function p.ins(a, e) -- Adds `e`lement "e" to `a`rray "a".
	local i = #a
	a[i+1] = e
	return a
end

return p