Jump to content

Module:Editnotice load

From Wikipedia, the free encyclopedia

local p = {}
local getArgs = require('Module:Arguments').getArgs
local cfg = require("Module:Editnotice_load/config_loader")
local pseudoNs = mw.title.new(cfg.pseudo_ns_name)
local enTypes = cfg.editnotice_types
local enNames = cfg.editnotice_names
local protLevel = require("Module:Effective protection level")._main
local yn = require("Module:Yesno")

function fillStringWithArgs(text, valArray)
	if not valArray then
		return text
	end

	local function getVal(match)
		match = tonumber(match)
		return valArray[match] or ''
	end

	return mw.ustring.gsub(text, '$([1-9][0-9]*)', getVal) .. ''
end

local function detectParameters(text)
	return text and mw.ustring.find(text, '$([1-9][0-9]*)') and true or false
end

--[=[===========================================================================
- Gets the notice content of any editnotice.
- @param frame the current frame
- @param title the title of the page
- @param args the processing args
- @param hide whether to hide the notice
- @returns the contents of the editnotice
=============================================================================]=]
local function getNoticeContent(frame, title, args, hide)
	if hide then return '' end
	local t = mw.title.new(title)
	if t == nil or t.id == 0 or not t.exists then
		return ''
	end
	local result = frame:expandTemplate{ title = title, args = args }
	result = mw.text.trim(result)
	if result ~= '' and result ~= '-' then
		return result
	end
	return ''
end
p.getNoticeContent = getNoticeContent

--[=[===========================================================================
- Builds a link to any editnotice
- @param builder the main editnotice builder
- @param links the editnotice builder containing the links
- @param target the target of the editnotice
- @param text the text to use for displaying the editnotice
- @param contents the contents of the editnotice
=============================================================================]=]
local function makeLink(builder, links, target, text, contents)
	local builderLinksNodeSame = builder == links
	if (contents == '' or contents == nil) and not builderLinksNodeSame then
		builder = links
		builder = builder
			:tag('li')
	else
		builder = builder:tag('span')
	end
	builder = builder
		:addClass('editnotice-link')
		:css('clear', 'both')
		:css('margin', '0px 0.8em')
		:css('padding', 0)
		:css('line-height', '1em')
		:css('font-size', '90%')
	if not ((contents == '' or contents == nil) and not builderLinksNodeSame) then
		builder = builder:css('float', 'right')
	end
	builder:wikitext(string.format('[[%s|%s]] ', target, text))
end
p.makeLink = makeLink

--[=[===========================================================================
- Displays any editnotice
- @param builder the main editnotice builder
- @param class the classes to add to the editnotice
- @param content the contents of the editnotice
=============================================================================]=]
local function displayEditnotice(builder, class, content)
	if content ~= nil and content ~= '' then
		return builder:tag('div')
			:addClass(class)
			:css('clear', 'both')
			:css('width', '100%')
			:wikitext(content)
	end
end
p.displayEditnotice = displayEditnotice

--[=[===========================================================================
- Gets the editnotice type of any editnotice
- @param title a title object for the editnotice
- @returns the editnotice type
=============================================================================]=]
function getEditnoticeType(title)
	if title.baseText == title.rootText then
		return title.subpageText
	else
		return getEditnoticeType(title.basePageTitle)
	end
end

p.getEditnoticeType = getEditnoticeType

--[=[===========================================================================
- Gets the page that the editnotice is stored
- @param currPage the page the editnotice is being displayed on
- @param editnoticeType the editnotice type
- @returns the page which has the editnotice
=============================================================================]=]
function getEditnoticeMainPage(currPage, editnoticeType)
	return mw.ustring.sub(currPage.fullText, mw.ustring.len(pseudoNs.fullText .. "/" .. editnoticeType .. "/") + 1) .. ""
end

p.getEditnoticeMainPage = getEditnoticeMainPage

--[=[===========================================================================
- Gets the page the editnotice belongs to
- @param frame the calling frame
- @returns the page by which the editnotice belongs
=============================================================================]=]
function p.page(frame)
	local args = getArgs(frame)
	local currPage = args['title'] and mw.title.new(args['title']) or mw.title.getCurrentTitle()
	local editnoticeType = p.editnotice(frame)
	local titleName = mw.ustring.sub(currPage.fullText, mw.ustring.len(pseudoNs.fullText .. "/" .. enTypes[editnoticeType] .. "/") + 1) .. ""
	if editnoticeType == "page" or editnoticeType == "protection_id" then
		local page = mw.title.new(tonumber(titleName))
		return page and page.fullText or ""
	else
		return enTypes[editnoticeType] ~= nil and titleName .. "" or ''
	end
end

function key(title, var, name)
	return title ~= nil and title ~= 0 and (var[name] or name) or nil
end

--[=[===========================================================================
- Gets any editnotice and its associated data
- @param frame the processing frame
- @param noticeArgs the arguments to pass to the editnotice
- @param title the string for the page the editnotice belongs to
- @param type the editnotice type
- @returns a table with the editnotice name and contents
=============================================================================]=]
function p.getEditnotice(frame, noticeArgs, title, type, hide)
	-- return a table of values with the editnotice
	local noticeName = pseudoNs.prefixedText .. "/" .. type .. "/" ..  title
	local noticeContent = getNoticeContent(frame, noticeName, noticeArgs, hide)
	return {
		["title"] = noticeName,
		["content"] = noticeContent
	}
end

--[=[===========================================================================
- Shows any editnotice
- @param builder the builder for the editnotice
- @param links a container for all the links
- @param editnoticeData a table with editnotice data from p.getEditnotice
- @param editnoticeName the name of the editnotice
- @param editnoticeClass the class to add to the editnotice
=============================================================================]=]
function p.showEditnotice(builder, links, editnoticeData, editnoticeName, editnoticeClass)
	makeLink(builder, links, editnoticeData.title, editnoticeName, editnoticeData.content)
	displayEditnotice(builder, editnoticeClass, editnoticeData.content)
end

--[=[===========================================================================
- Generates only the contents for protection editnotices
=============================================================================]=]
function p.protectionEditnotice(frame)
	local args = getArgs(frame)
	local noticeAction = args['notice action']
	local noticeArgs = {['notice action'] = noticeAction}
	local currentTitle = args['title'] and mw.title.new(args['title']) or mw.title.getCurrentTitle()
	local builder = mw.html.create('div')
		:attr('id', 'editnotice-area')
		:addClass('editnotice-area mw-parser-output')
		:css('clear', 'both')
		:css('width', '100%')
	
	local protectionTitleNoticeData = p.getEditnotice(frame, noticeArgs, currentTitle.prefixedText, enTypes["protection"])
	if protectionTitleNoticeData.content ~= "" then
		p.showEditnotice(builder, builder, protectionTitleNoticeData, enNames["protection"], 'editnotice-protection-title')
	end
	
	local protectionNoticeData = p.getEditnotice(frame, noticeArgs, currentTitle.id .. '', enTypes["protection_id"])
	if protectionNoticeData.content ~= "" then
		p.showEditnotice(builder, builder, protectionNoticeData, enNames["protection_id"], 'editnotice-protection')
	end
	
	builder:tag('div')
		:css('clear', 'both')
	if protectionNoticeData.content == "" and protectionTitleNoticeData.content == "" then
		return ""
	end
	return builder
end

--[=[===========================================================================
- Gets the editnotice type
=============================================================================]=]
function p.editnotice(frame)
	local args = getArgs(frame)
	local currPage = args['title'] and mw.title.new(args['title']) or mw.title.getCurrentTitle()
	if currPage.rootText == pseudoNs.text and currPage.nsText == pseudoNs.nsText then
		local editNoticeType = getEditnoticeType(currPage)
		local title = mw.title.new(getEditnoticeMainPage(currPage, editNoticeType))
		if editNoticeType == enTypes["protection"] then
			return key(title, args, "protection") or args["#default"] or ''
		elseif editNoticeType == enTypes["protection_id"] then
			title = mw.title.new(tonumber(getEditnoticeMainPage(currPage, editNoticeType)) or 0)
			return key(title, args, "protection_id") or args["#default"] or ''
		elseif editNoticeType == enTypes["title"] then
			return key(title, args, "title") or args["#default"] or ''
		elseif editNoticeType == enTypes["page"] then
			title = mw.title.new(tonumber(getEditnoticeMainPage(currPage, editNoticeType)) or 0)
			return key(title, args, "page") or args["#default"] or ''
		elseif editNoticeType == enTypes["group"] then
			return key(title, args, "group") or args["#default"] or ''
		elseif editNoticeType == enTypes["category"] then
			return key(title, args, "category") or args["#default"] or ''
		elseif editNoticeType == enTypes["namespace"] then
			return key(title, args, "namespace") or args["#default"] or ''
		else
			return args["#default"] or ''
		end
	end
end

--[=[===========================================================================
- The main entry point for the editnotice loader
=============================================================================]=]
function p.main(frame)
	local args = getArgs(frame)
	local noticeAction = args['notice action']
	local noticeArgs = {['notice action'] = noticeAction}
	local noText = yn(args['notext']) or false
	local currentTitle = args['title'] and mw.title.new(args['title']) or mw.title.getCurrentTitle()
	
	local builder = mw.html.create('div')
		:attr('id', 'editnotice-area')
		:addClass('editnotice-area mw-parser-output')
		:css('clear', 'both')
		:css('width', '100%')
	local hide = noText
	if noText then
		local editNoticePage = mw.title.new("MediaWiki:Editnotice-" .. tostring(currentTitle.namespace))
		if not editNoticePage.exists then
			builder
				:tag("span")
				:addClass("sysop-show")
				:tag("strong")
				:addClass("error")
				:wikitext(frame:preprocess(fillStringWithArgs(cfg.noEditnoticePage, {'[[' .. editNoticePage.fullText .. ']]', '<code><nowiki>{{</nowiki>#invoke:[[Module:Editnotice load|editnotice load]]|main<nowiki>}}</nowiki></code>'})))
			hide = false
		end
	end
	
	local links = builder:tag("table")
		:addClass('wikitable editnotice-links mw-collapsible mw-collapsed')
		:addClass(cfg.editnotice_classes)
		:css("width", "100%")
		:tag("tr")
		:tag("th")
		:wikitext(cfg.links):done():done()
		:tag("td")
		:tag("ul")
		:attr("id", "editnotice-links")
		:css("display", "block")
		:addClass('hlist')

	local editnotices = ''

	if noticeAction ~= 'view' and noticeAction ~= 'protect' then
		local namespace = currentTitle.nsText
		if namespace == '' then namespace = (cfg.mainspace or mw.site.namespaces[0].displayName) end
		local nsNoticeData = p.getEditnotice(frame, noticeArgs, namespace, enTypes["namespace"], hide)
		p.showEditnotice(builder, links, nsNoticeData, enNames["namespace"], 'editnotice-namespace')
		editnotices = editnotices .. nsNoticeData.content
	end
	if protLevel("edit", currentTitle.fullText) or 
		protLevel("move", currentTitle.fullText) or 
		protLevel("create", currentTitle.fullText) or 
		protLevel("upload", currentTitle.fullText) then
		local protectionTitleNoticeData = p.getEditnotice(frame, noticeArgs, currentTitle.prefixedText, enTypes["protection"], hide)
		if noticeAction ~= "protect" then protectionTitleNoticeData.content = "" end
		p.showEditnotice(builder, links, protectionTitleNoticeData, enNames["protection"], 'editnotice-protection-title')
		editnotices = editnotices .. protectionTitleNoticeData.content
		
		if currentTitle.id ~= 0 then
			local protectionNoticeData = p.getEditnotice(frame, noticeArgs, currentTitle.id .. '', enTypes["protection_id"], hide)
			if noticeAction ~= "protect" then protectionNoticeData.content = "" end
			p.showEditnotice(builder, links, protectionNoticeData, enNames["protection_id"], 'editnotice-protection')
			editnotices = editnotices .. protectionNoticeData.content
		end
	end

	if mw.site.namespaces[currentTitle.namespace].hasSubpages then
		local splitTitle = mw.text.split(currentTitle.prefixedText, "/")
		local groupTitle = ''
		for k,v in ipairs(splitTitle) do
			groupTitle = groupTitle .. v
			local groupNoticeData = p.getEditnotice(frame, noticeArgs, groupTitle, enTypes["group"], hide)
			p.showEditnotice(builder, links, groupNoticeData, enNames["group"] .. " (" .. groupTitle .. ")", "editnotice-group")
			editnotices = editnotices .. groupNoticeData.content
			groupTitle = groupTitle .. '/'
		end
	end
	
	if cfg.user_editnotice ~= nil and ((currentTitle:hasSubjectNamespace(2) or currentTitle:hasSubjectNamespace(3)) and not currentTitle.isSubpage) then
		-- display user page notice
		local userPageNoticeName = currentTitle.prefixedText .. '/' .. cfg.user_editnotice
		local userPageNoticeContent = getNoticeContent(frame, userPageNoticeName, noticeArgs, hide)
		makeLink(builder, builder, userPageNoticeName, enNames["user"], userPageNoticeContent)
		displayEditnotice(builder, 'usernotice-page', userPageNoticeContent)
		editnotices = editnotices .. userPageNoticeContent
	end
	
	local titleNoticeData = p.getEditnotice(frame, noticeArgs, currentTitle.prefixedText, enTypes["title"], hide)
	p.showEditnotice(builder, links, titleNoticeData, enNames["title"], "editnotice-title")
	editnotices = editnotices .. titleNoticeData.content
	
	if currentTitle.id ~= 0 then
		local pageNoticeData = p.getEditnotice(frame, noticeArgs, currentTitle.prefixedText, enTypes["page"], hide)
		p.showEditnotice(builder, links, pageNoticeData, enNames["page"], "editnotice-page")
		editnotices = editnotices .. pageNoticeData.content
	end
	
	local categories = currentTitle.categories or {}
	mw.logObject(categories)
	for k,v in ipairs(categories) do
		local categoryNoticeData = p.getEditnotice(frame, noticeArgs, v, enTypes["category"], hide)
		p.showEditnotice(builder, links, categoryNoticeData, enNames["category"] .. " (" .. v .. ")", "editnotice-page")
		editnotices = editnotices .. categoryNoticeData.content
	end
	if editnotices == '' and not noText then return '' end

	builder:tag('div')
		:css('clear', 'both')
	local success, templateStyles = pcall(function(frame)
		return frame:callParserFunction('#tag:templatestyles', {'', src = cfg.templateStyles})
	end, frame) 
	if not success then return builder end
	return tostring( builder ) .. templateStyles
end

p.cfg = cfg
return p