A modult a Modul:workgroup ping/doc lapon tudod dokumentálni

local export = {}
local m_data = mw.loadData('Module:workgroup ping/data')

function export.ping(frame)
	local parent_frame = frame:getParent()
	local args = parent_frame.args
	local users, errors = {}, {}
	local had_ind = false
	
	local function gather_users(myself)
		local had_user = { }
		if myself and not args.fix then
			had_user[myself] = true
		end

		local empty = true		
		for _, wgid in ipairs(args) do
			local _, user = wgid:match("^User:(.*)")
			if user then
				table.insert(users, user)
				had_user[user] = true
				had_ind = true
			else
				local data = m_data[wgid]
				if data then
					if data[1] then
						for i, user in ipairs(data) do
							if not had_user[user] then
								table.insert(users, user)
							end
						end
					else
						table.insert(errors, ('%s=empty'):format(wgid))
					end
				else
					table.insert(errors, ('%s=404'):format(wgid))
				end
			end
			empty = false
		end
		
		if empty then
			table.insert(errors, "nogroups")
		end
	end
	
	local title = mw.title.getCurrentTitle()
	if mw.isSubsting() then
		local output = { '{{wgping' }
		
		local my_username = frame:callParserFunction("REVISIONUSER", title.fullText)
		gather_users(my_username)
		
		for _, wgid in ipairs(args) do
			table.insert(output, '|' .. wgid)
		end

		for i, user in ipairs(users) do
			table.insert(output, ('|u%u=%s'):format(i, user))
		end
		
		-- [[gerrit:159800]]
		if #users > 20 then
			table.insert(errors, "limit")
		end

		for i, err in ipairs(errors) do
			table.insert(output, ('|e%u=%s'):format(i, err))
		end
		
		table.insert(output, '}}')
		return table.concat(output)
	else
		if parent_frame:getTitle() == title.fullText then
			return '<small>(Notifying [[User:Example|Example]]): </small>'	
		end

		local output = { '<small>(Notifying ' }
		local i

		-- the |u#= and |e#= parameters are for internal use only.
		i = 1
		while args['e' .. i] do
			table.insert(errors, args['e' .. i])
			i = i + 1	
		end

		i = 1
		while args['u' .. i] do
			table.insert(users, args['u' .. i])
			i = i + 1	
		end

		local is_preview = frame:preprocess("{{REVISIONID}}") == ""

		if (#users + #errors) == 0 then
			if is_preview then
				local unfmted = {}
				for _, item in ipairs(args) do
					table.insert(unfmted, '|' .. item)
					-- XXX: more detailed?
				end

				return '<strong class="error">Error: <code>{{wgping}}</code> must be [[mw:Manual:Substitution|substituted]]! ' ..
					'Use <code>{{subst:wgping' .. table.concat(unfmted) .. '}}</code> instead</strong>'
			else
				table.insert(output, "[[Category:unsubstituted wgping]]")
				table.insert(errors, "subst")
				gather_users()
			end
		end

		for i, user in ipairs(users) do
			table.insert(output, ('%s[[User:%s|%s]]'):format(
				(i == 1) and "" or ", ",
				user, user
			))
		end

		local function explain_error(e)
			if e == "subst" then
				return "template was not substituted; please substitute passing |fix=1"
			elseif e == "nogroups" then
				return "no workgroups specified"
			else
				local g, e = e:match("(.-)=(.*)")
				if e == "404" then
					return "group '" .. g .. "' does not exist"
				elseif e == "empty" then
					return "group '" .. g .. "' is empty"
				elseif e == "limit" then
					return "more than 20 users to notify: notification will not work"
				end
			end
			return "unknown error '" .. e .. "'"
		end
	
		if #errors > 0 then
			if is_preview then
				table.insert(output, '; <strong class="error">errors: ')
				for i, e in ipairs(errors) do
					table.insert(output, ((i == 1) and "" or ", ") .. explain_error(e))
				end
				table.insert(output, '</strong>')
			else
				table.insert(output, '; <span style="border-bottom: 1px dotted red; color: red; font-weight: bold;" title="')
				for i, e in ipairs(errors) do
					table.insert(output, ((i == 1) and "" or ", ") .. explain_error(e))
				end
				table.insert(output, '">errors</span>')
			end
		end

		table.insert(output, '): </small>')
		return table.concat(output)
	end
end

function export.show_list(frame)
	local categories_list = {}
	local categories_map = {}
	local wg_codes, wg_aliases = {}, {}
	
	for key, data in pairs(m_data) do
		if type(data) == 'string' then
			if not wg_aliases[data] then
				wg_aliases[data] = {}	
			end
			table.insert(wg_aliases[data], ("<code>%s</code>"):format(key))
		else
			local categ = data.category or ""
			if not categories_map[categ] then
				local newcat = { desc = categ, groups = {} }
				table.insert(categories_list, newcat)
				categories_map[categ] = newcat
			end
			categ = categories_map[categ]
			wg_codes[data] = key
			
			table.insert(categ.groups, data)
		end
	end

	table.sort(categories_list, function (apple, orange)
		return apple.desc < orange.desc
	end)
	
	local output = {
		'{| class="wikitable" style="width: 90%;" \n|-\n! style="width: 8em;" | Shortcut(s) \n! Group name \n! Members'
	}
	for _, categ in pairs(categories_list) do
		table.sort(categ.groups, function (apple, orange)
			return apple.desc < orange.desc
		end)

		if categ.desc ~= "" then
			table.insert(output, '|-\n! colspan="3" style="font-size: smaller; text-align: left;" | ' .. categ.desc)
		end
		for _, wgdata in pairs(categ.groups) do
			local members = {}
			local had_users, had_tfs = {}, {}
			
			if type(wgdata) ~= 'table' then
				return	
			end
			
			for _, user in ipairs(wgdata) do
				if not had_users[user] then
					table.insert(members, ("[[User:%s|%s]]"):format(user, user))
					had_users[user] = true
				end
			end

			local wg_code = ("<code>%s</code>"):format(wg_codes[wgdata])
			if wg_aliases[wg_codes[wgdata]] then
				wg_code = ('%s<br/><small>(%s)</small>'):format(wg_code, table.concat(wg_aliases[wg_codes[wgdata]], ", "))
			end
			table.insert(output, ('|- id="%s" style="vertical-align: top;" \n|%s\n|%s\n|%s <small>(%u %s)</small>'):format(
				wg_codes[wgdata], wg_code, wgdata.desc, table.concat(members, ", "), #members, ((#members == 1) and 'user' or 'users')
			))
		end
	end
	table.insert(output, "|}")
	return table.concat(output, "\n")
end

return export