×
Create a new article
Write your page title here:
We currently have 47 articles on Ages of Conflict Wiki. Type your article name above or create one of the articles listed here!



    Ages of Conflict Wiki

    Documentation for this module may be created at Module:Category handler/doc

    --------------------------------------------------------------------------------
    --                                                                            --
    --                              CATEGORY HANDLER                              --
    --                                                                            --
    --      This module implements the {{category handler}} template in Lua,      --
    --      with a few improvements: all namespaces and all namespace aliases     --
    --      are supported, and namespace names are detected automatically for     --
    --      the local wiki. This module requires [[Module:Namespace detect]]      --
    --      and [[Module:Yesno]] to be available on the local wiki. It can be     --
    --      configured for different wikis by altering the values in              --
    --      [[Module:Category handler/config]], and pages can be blacklisted      --
    --      from categorisation by using [[Module:Category handler/blacklist]].   --
    --                                                                            --
    --------------------------------------------------------------------------------
    
    -- Load required modules
    local yesno = require('Module:Yesno')
    
    -- Lazily load things we don't always need
    local mShared, mappings
    
    local p = {}
    
    --------------------------------------------------------------------------------
    -- Helper functions
    --------------------------------------------------------------------------------
    
    local function trimWhitespace(s, removeBlanks)
    	if type(s) ~= 'string' then
    		return s
    	end
    	s = s:match('^%s*(.-)%s*$')
    	if removeBlanks then
    		if s ~= '' then
    			return s
    		else
    			return nil
    		end
    	else
    		return s
    	end
    end
    
    --------------------------------------------------------------------------------
    -- CategoryHandler class
    --------------------------------------------------------------------------------
    
    local CategoryHandler = {}
    CategoryHandler.__index = CategoryHandler
    
    function CategoryHandler.new(data, args)
    	local obj = setmetatable({ _data = data, _args = args }, CategoryHandler)
    	
    	-- Set the title object
    	do
    		local pagename = obj:parameter('demopage')
    		local success, titleObj
    		if pagename then
    			success, titleObj = pcall(mw.title.new, pagename)
    		end
    		if success and titleObj then
    			obj.title = titleObj
    			if titleObj == mw.title.getCurrentTitle() then
    				obj._usesCurrentTitle = true
    			end
    		else
    			obj.title = mw.title.getCurrentTitle()
    			obj._usesCurrentTitle = true
    		end
    	end
    
    	-- Set suppression parameter values
    	for _, key in ipairs{'nocat', 'categories'} do
    		local value = obj:parameter(key)
    		value = trimWhitespace(value, true)
    		obj['_' .. key] = yesno(value)
    	end
    	do
    		local subpage = obj:parameter('subpage')
    		local category2 = obj:parameter('category2')
    		if type(subpage) == 'string' then
    			subpage = mw.ustring.lower(subpage)
    		end
    		if type(category2) == 'string' then
    			subpage = mw.ustring.lower(category2)
    		end
    		obj._subpage = trimWhitespace(subpage, true)
    		obj._category2 = trimWhitespace(category2) -- don't remove blank values
    	end
    	return obj
    end
    
    function CategoryHandler:parameter(key)
    	local parameterNames = self._data.parameters[key]
    	local pntype = type(parameterNames)
    	if pntype == 'string' or pntype == 'number' then
    		return self._args[parameterNames]
    	elseif pntype == 'table' then
    		for _, name in ipairs(parameterNames) do
    			local value = self._args[name]
    			if value ~= nil then
    				return value
    			end
    		end
    		return nil
    	else
    		error(string.format(
    			'invalid config key "%s"',
    			tostring(key)
    		), 2)
    	end
    end
    
    function CategoryHandler:isSuppressedByArguments()
    	return
    		-- See if a category suppression argument has been set.
    		self._nocat == true
    		or self._categories == false
    		or (
    			self._category2
    			and self._category2 ~= self._data.category2Yes
    			and self._category2 ~= self._data.category2Negative
    		)
    
    		-- Check whether we are on a subpage, and see if categories are
    		-- suppressed based on our subpage status.
    		or self._subpage == self._data.subpageNo and self.title.isSubpage
    		or self._subpage == self._data.subpageOnly and not self.title.isSubpage
    end
    
    function CategoryHandler:shouldSkipBlacklistCheck()
    	-- Check whether the category suppression arguments indicate we
    	-- should skip the blacklist check.
    	return self._nocat == false
    		or self._categories == true
    		or self._category2 == self._data.category2Yes
    end
    
    function CategoryHandler:matchesBlacklist()
    	if self._usesCurrentTitle then
    		return self._data.currentTitleMatchesBlacklist
    	else
    		mShared = mShared or require('Module:Category handler/shared')
    		return mShared.matchesBlacklist(
    			self.title.prefixedText,
    			mw.loadData('Module:Category handler/blacklist')
    		)
    	end
    end
    
    function CategoryHandler:isSuppressed()
    	-- Find if categories are suppressed by either the arguments or by
    	-- matching the blacklist.
    	return self:isSuppressedByArguments()
    		or not self:shouldSkipBlacklistCheck() and self:matchesBlacklist()
    end
    
    function CategoryHandler:getNamespaceParameters()
    	if self._usesCurrentTitle then
    		return self._data.currentTitleNamespaceParameters
    	else
    		if not mappings then
    			mShared = mShared or require('Module:Category handler/shared')
    			mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData
    		end
    		return mShared.getNamespaceParameters(
    			self.title,
    			mappings
    		)
    	end
    end
    
    function CategoryHandler:namespaceParametersExist()
    	-- Find whether any namespace parameters have been specified.
    	-- We use the order "all" --> namespace params --> "other" as this is what
    	-- the old template did.
    	if self:parameter('all') then
    		return true
    	end
    	if not mappings then
    		mShared = mShared or require('Module:Category handler/shared')
    		mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData
    	end
    	for ns, params in pairs(mappings) do
    		for i, param in ipairs(params) do
    			if self._args[param] then
    				return true
    			end
    		end
    	end
    	if self:parameter('other') then
    		return true
    	end
    	return false
    end
    
    function CategoryHandler:getCategories()
    	local params = self:getNamespaceParameters()
    	local nsCategory
    	for i, param in ipairs(params) do
    		local value = self._args[param]
    		if value ~= nil then
    			nsCategory = value
    			break
    		end
    	end
    	if nsCategory ~= nil or self:namespaceParametersExist() then
    		-- Namespace parameters exist - advanced usage.
    		if nsCategory == nil then
    			nsCategory = self:parameter('other')
    		end
    		local ret = {self:parameter('all')}
    		local numParam = tonumber(nsCategory)
    		if numParam and numParam >= 1 and math.floor(numParam) == numParam then
    			-- nsCategory is an integer
    			ret[#ret + 1] = self._args[numParam]
    		else
    			ret[#ret + 1] = nsCategory
    		end
    		if #ret < 1 then
    			return nil
    		else
    			return table.concat(ret)
    		end
    	elseif self._data.defaultNamespaces[self.title.namespace] then
    		-- Namespace parameters don't exist, simple usage.
    		return self._args[1]
    	end
    	return nil
    end
    
    --------------------------------------------------------------------------------
    -- Exports
    --------------------------------------------------------------------------------
    
    local p = {}
    
    function p._exportClasses()
    	-- Used for testing purposes.
    	return {
    		CategoryHandler = CategoryHandler
    	}
    end
    
    function p._main(args, data)
    	data = data or mw.loadData('Module:Category handler/data')
    	local handler = CategoryHandler.new(data, args)
    	if handler:isSuppressed() then
    		return nil
    	end
    	return handler:getCategories()
    end
    
    function p.main(frame, data)
    	data = data or mw.loadData('Module:Category handler/data')
    	local args = require('Module:Arguments').getArgs(frame, {
    		wrappers = data.wrappers,
    		valueFunc = function (k, v)
    			v = trimWhitespace(v)
    			if type(k) == 'number' then
    				if v ~= '' then
    					return v
    				else
    					return nil
    				end
    			else
    				return v
    			end
    		end
    	})
    	return p._main(args, data)
    end
    
    return p
    
    Cookies help us deliver our services. By using our services, you agree to our use of cookies.
    Cookies help us deliver our services. By using our services, you agree to our use of cookies.