Difference between revisions of "Module:Category handler/sandbox"

From blackwiki
Jump to navigation Jump to search
blackwiki>Mr. Stradivarius
(remove blank values for suppression category parameters)
blackwiki>Mr. Stradivarius
(use new shared function for getting parameter mappings)
Line 19: Line 19:
  
 
-- Lazily load things we don't always need
 
-- Lazily load things we don't always need
local mShared, mNamespaceDetect, mappings
+
local mShared, mappings
  
 
local p = {}
 
local p = {}
Line 150: Line 150:
 
else
 
else
 
mShared = mShared or require('Module:Category handler/shared')
 
mShared = mShared or require('Module:Category handler/shared')
mNamespaceDetect = mNamespaceDetect or require('Module:Namespace detect')
+
mappings = mappings or mShared.getParamMappings(true) -- gets mappings with mw.loadData
mappings = mappings or mNamespaceDetect.getParamMappings()
 
 
return mShared.getNamespaceParameters(
 
return mShared.getNamespaceParameters(
 
self.title,
 
self.title,
Line 166: Line 165:
 
return true
 
return true
 
end
 
end
mappings = mappings or mNamespaceDetect.getParamMappings()
+
mappings = mappings or mShared.getParamMappings(true) -- gets mappings with mw.loadData
 
for ns, params in pairs(mappings) do
 
for ns, params in pairs(mappings) do
 
for i, param in ipairs(params) do
 
for i, param in ipairs(params) do

Revision as of 00:30, 8 July 2014

Documentation for this module may be created at Module:Category handler/sandbox/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 class = require('Module:Middleclass').class
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 = class('CategoryHandler')

function CategoryHandler:initialize(data, args)
	self._data = data
	self._args = args
	
	-- Set the title object
	do
		local pagename = self:parameter('demopage')
		local success, titleObj = pcall(mw.title.new, pagename)
		if success and titleObj then
			self.title = titleObj
		else
			self.title = mw.title.getCurrentTitle()
			self._usesCurrentTitle = true
		end
	end

	-- Set suppression parameter values
	for _, key in ipairs{'nocat', 'categories'} do
		local value = self:parameter(key)
		value = trimWhitespace(value, true)
		self['_' .. key] = yesno(value)
	end
	for _, key in ipairs{'category2', 'subpage'} do
		local value = self:parameter(key)
		if type(value) == 'string' then
			value = mw.ustring.lower(value)
		end
		self['_' .. key] = trimWhitespace(value, true)
	end
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
		mShared = mShared or require('Module:Category handler/shared')
		mappings = mappings or mShared.getParamMappings(true) -- gets mappings with mw.loadData
		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
	mappings = mappings or mShared.getParamMappings(true) -- gets mappings with mw.loadData
	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)
	local data = 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)
	local args = require('Module:Arguments').getArgs(frame, {
		wrappers = 'Template:Category handler',
		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)
end

return p