Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

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

local _debug=nil
local p = {}

----------------------------------------------------------------------------------------------------
---------- Debug utilities -------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
-- addDebug() in /sanbox templates/modules adds a debug information to a global variable.
-- in non sandbox templates/modules is does nothing
function p.addDebug(functionName, text)
	if not _debug then
		return
	end
	_debug = _debug .. functionName .. ': ' .. mw.text.nowiki(text) .. '<BR/>'
end

-- getDebug() returns '' or a string prefixed by <prefix> containing the debug to be displayed
function p.getDebug(prefix)
	if string.isNilOrEmpty(_debug) then
		return ''
	end
	return prefix .. _debug
end

----------------------------------------------------------------------------------------------------
---------- String utilities ------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
-- Equivalent to java startsWith()
-- It has a testcase/non-regression module Module:Biology/testcases using testcase_string_startsWith()
function string.startsWith(longString, start)
	if not longString or not start then
		return false
	end
	local startLen = string.len(start)
	if startLen > string.len(longString) then
		return false
	end
   	return string.sub(longString, 1, startLen) == start
end

-- Equivalent to java endsWith()
-- It has a testcase/non-regression module Module:Biology/testcases using testcase_string_endsWith()
function string.endsWith(longString, ending)
	if not longString or not ending then
		return false
	end
	local endingLen = string.len(ending)
	if endingLen > string.len(longString) then
		return false
	end
   	return ending=='' or string.sub(longString,-endingLen)==ending
end

-- stringContains(long,small) is an improvment of string.find(longlower, smalllower)
-- it is case insensitiv + also returns true if long == small
-- It has a testcase/non-regression module Module:Biology/testcases using testcase_string_contains()
function string.contains(long, small)
	if not long or not small then
		return false
	end
	local longlower = string.lower(long)
	local smalllower = string.lower(small)
	if longlower == smalllower or string.find(longlower, smalllower, 1, true) then -- true for plaintext
		return true
	else
		return false
	end
end

-- stringUpperFirstLowerOthers(str) returns "Hello" out of "heLLO"
-- It has a testcase/non-regression module Module:Biology/testcases using testcase_string_upperFirstLowerOthers()
function string.upperFirstLowerOthers(str)
	if not str then
		return Nil
	end
	local length = string.len(str)
	if length == 0 then
		return ''
	elseif length == 1 then
		return string.upper(str)
	else
		return string.upper(string.sub(str,1,1)) .. string.lower(string.sub(str,2))
	end
end

-- stringUpperFirst(str) returns "HeLlO" out of "heLlO"
-- It has a testcase/non-regression module Module:Biology/testcases using testcase_string_upperFirst()
function string.upperFirst(str)
	if not str then
		return Nil
	end
	local length = string.len(str)
	if length == 0 then
		return ''
	elseif length == 1 then
		return string.upper(str)
	else
		return string.upper(string.sub(str,1,1)) .. string.sub(str,2)
	end
end

-- isTrue() transforms a string into a bool
-- Nil, '', '0', 'false', 'no' return false
-- other values return true
-- It has a testcase/non-regression module Module:Biology/testcases using testcase_string_isTrue()
function string.isTrue(stringValue)
	if not stringValue then
		return false
	end
	if string.len(stringValue) == 0 then
		return false
	end
	stringValue = string.lower(mw.text.trim(stringValue))
	if stringValue == '0' or stringValue == 'false' or stringValue == 'no' then
		return false
	end
	return true
end

-- string.trimOrNullify() returns a trimmed string or nil if the trimmed string is empty
-- It has a testcase/non-regression module Module:Biology/testcases using testcase_string_trimOrNullify()
function string.trimOrNullify(str)
	if not str then
		return Nil
	end
	str = mw.text.trim(str)
	if str == '' then
		return Nil
	end
	return str
end

-- string.isNilOrEmpty() returns
-- * true for nil or '' or '   '
-- * false otherwise
-- It has a testcase/non-regression module Module:Biology/testcases using testcase_string_isNilOrEmpty()
function string.isNilOrEmpty(stringValue)
	if not stringValue then
		return true
	end
	if string.len(stringValue) == 0 then
		return true
	end
	stringValue = mw.text.trim(stringValue)
	if string.len(stringValue) == 0 then
		return true
	end
	return false
end

----------------------------------------------------------------------------------------------------
---------- Namespace/articleName utilities ---------------------------------------------------------
----------------------------------------------------------------------------------------------------
-- getCurrentNamespace() returns the current namespace name ('gallery' instead of '')
-- It has a testcase/non-regression module Module:Biology/testcases using getCurrentNamespace() directly
function p.getCurrentNamespace()
	local namespace = string.lower(mw.title.getCurrentTitle().nsText)
	if string.len(namespace) == 0 then
		namespace = 'gallery'
	end
	return namespace
end

-- isCurrentNamespaceACategory() returns true when called from a category
-- It has a testcase/non-regression module Module:Biology/testcases using isCurrentNamespaceACategory() directly
function p.isCurrentNamespaceACategory()
	local namespace = string.lower(mw.title.getCurrentTitle().nsText)
	if namespace == 'category' then
		return true
	else
		return false
	end
end

-- isCurrentNamespaceACategoryOrAGallery() returns true when called from a category or gallery
-- It has a testcase/non-regression module Module:Biology/testcases using isCurrentNamespaceACategoryOrAGallery() directly
function p.isCurrentNamespaceACategoryOrAGallery()
	local namespace = string.lower(mw.title.getCurrentTitle().nsText)
	if string.len(namespace) == 0 then
		return true
	elseif namespace == 'category' then
		return true
	else
		return false
	end
end

-- isCurrentNamespaceACategoryOrAGalleryOrATemplate() returns true when called from a category or gallery or template
-- It has a testcase/non-regression module Module:Biology/testcases using isCurrentNamespaceACategoryOrAGalleryOrATemplate() directly
function p.isCurrentNamespaceACategoryOrAGalleryOrATemplate()
	local namespace = string.lower(mw.title.getCurrentTitle().nsText)
	if namespace == '' then
		return true
	elseif namespace == 'category' then
		return true
	elseif namespace == 'template' then
		return true
	else
		return false
	end
end

-- suppressCategory() returns "Platanthera" out of "Category:Platanthera"
-- It has a testcase/non-regression module Module:Biology/testcases using testcase_suppressCategory()
function p.suppressCategory(category)
	local twoPointStartPos, twoPointEndPos = string.find(category, ':', 1, true)
	if twoPointStartPos then
		category = string.sub(category,twoPointEndPos+1)
	end
	return category
end

-- suppressDisambiguation() returns "Platanthera" out of "Platanthera (genus)"
-- It has a testcase/non-regression module Module:Biology/testcases using testcase_suppressDisambiguation()
function p.suppressDisambiguation(name)
	name = string.gsub(name, '_', ' ')
	local start = string.find(name, '(', 1, true)
	if not start then
		return name
	end
	local endp = string.find(name, ')', start, true)
	if not endp then
		return name
	end
	local part1 = mw.text.trim(string.sub(name, 1, start-1))
	local part2 = mw.text.trim(string.sub(name, endp+1))
	if string.len(part1) == 0 then
		return part2
	elseif string.len(part2) == 0 then
		return part1
	else
		return part1 .. ' ' .. part2
	end
end

-- pageNameCorrespondToSpeciesOrInfraspecies() returns true for "Category:Pantera tigris" or "Pantera tigris subsp. tigris"
-- pageNameCorrespondToSpeciesOrInfraspecies() returns false for "Category:Phyllosasa", "× Phyllosasa", "Rosa nothosect. Cinnastylae", "Category:Rosa subg. Rosa"
-- It has a testcase/non-regression module Module:Biology/testcases using testcase_pageNameCorrespondToSpeciesOrInfraspecies()
function p.pageNameCorrespondToSpeciesOrInfraspecies(pageName)
	if string.find(pageName, ' nothosect. ') then
		return false
	end
	if string.find(pageName, ' subg. ') then
		return false
	end
	pageName = p.suppressCategory(pageName)
	pageName = p.suppressDisambiguation(pageName)
	pageName = string.gsub(pageName, '×', '') -- '× Phyllosasa' is not an infraspecies
	pageName = mw.text.trim(pageName)
	if string.find(pageName, ' ') then
		return true
	else
		return false
	end
end

----------------------------------------------------------------------------------------------------
---------- Error utilities -------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
-- incorrectBiologyTemplateUsage() returns an error text (optional) and a 'Category:Pages with incorrect biology template usage'
-- Param sortkey: the sortkey for the category Pages with incorrect biology template usage
-- Param errorToDisplayOrNil: the error to display or nil in which case no error is displayed (only the category is added)
-- Param templateNameForDocOrNil: name of a template (without Template:) to which the red error will link. Clicking on the link will lead you to the template documentation.
--                    If nil, the link will point to 'Category:Pages with incorrect biology template usage'
-- Param ignoreNamespaceOrNil:
-- It has a testcase/non-regression module Module:Biology/testcases using testcase_incorrectBiologyTemplateUsage()
function p.incorrectBiologyTemplateUsage(sortkey, errorToDisplayOrNil, templateNameForDocOrNil, ignoreNamespaceOrNil)
	if not string.isTrue(ignoreNamespaceOrNil) then
		if (templateNameForDocOrNil == 'Taxonavigation') then
			if not p.isCurrentNamespaceACategoryOrAGalleryOrATemplate() then
				return ''
			end
		else
			if not p.isCurrentNamespaceACategoryOrAGallery() then
				return ''
			end
		end
	end
	local text = ''
	if errorToDisplayOrNil then
		if templateNameForDocOrNil then
			templateNameForDocOrNil = 'Template:' .. templateNameForDocOrNil
		else
			templateNameForDocOrNil = ':Category:Pages with incorrect biology template usage'
		end
		text = ' [[' .. templateNameForDocOrNil .. '|<span class="error">Error: ' .. errorToDisplayOrNil .. '</span>]]'
	end
	text = text .. ' [[Category:Pages with incorrect biology template usage|' .. sortkey .. ']] '
	return text
end

-- incorrectBiologyTemplateUsageNoLink() returns an error text (optional) and a Category:Pages with incorrect biology template usage
-- Param sortkey: the sortkey for the category Pages with incorrect biology template usage
-- Param errorToDisplayOrNil: the error to display or nil in which case no error is displayed (only the category is added)
-- Param templateNameForDocOrNil:
-- Param ignoreNamespaceOrNil:
-- It has a testcase/non-regression module Module:Biology/testcases using testcase_incorrectBiologyTemplateUsageNoLink()
function p.incorrectBiologyTemplateUsageNoLink(sortkey, errorToDisplayOrNil, templateNameForDocOrNil, ignoreNamespaceOrNil)
	if not string.isTrue(ignoreNamespaceOrNil) then
		if (templateNameForDocOrNil == 'Taxonavigation') then
			if not p.isCurrentNamespaceACategoryOrAGalleryOrATemplate() then
				return ''
			end
		else
			if not p.isCurrentNamespaceACategoryOrAGallery() then
				return ''
			end
		end
	end
	local text = ''
	if errorToDisplayOrNil then
		text = ' <span class="error">Error: ' .. errorToDisplayOrNil .. '</span>'
	end
	text = text .. ' [[Category:Pages with incorrect biology template usage|' .. sortkey .. ']] '
	return text
end

----------------------------------------------------------------------------------------------------
---------- Testcase public functions (return string) -----------------------------------------------
----------------------------------------------------------------------------------------------------
function p.testcase_string_startsWith(frame)
	return tostring(string.startsWith(frame.args['string'],frame.args['start']))
end

function p.testcase_string_endsWith(frame)
	return tostring(string.endsWith(frame.args['string'],frame.args['end']))
end

function p.testcase_string_contains(frame)
	return tostring(string.contains(frame.args['long'],frame.args['small']))
end

function p.testcase_string_upperFirstLowerOthers(frame)
	return tostring(string.upperFirstLowerOthers(frame.args['1'])) -- tostring for nil
end

function p.testcase_string_upperFirst(frame)
	return tostring(string.upperFirst(frame.args['1'])) -- tostring for nil
end

function p.testcase_string_isTrue(frame)
	return tostring(string.isTrue(frame.args['1']))
end

function p.testcase_string_trimOrNullify(frame)
	return tostring(string.trimOrNullify(frame.args['1'])) -- tostring for nil
end

function p.testcase_string_isNilOrEmpty(frame)
	return tostring(string.isNilOrEmpty(frame.args['1']))
end

function p.testcase_suppressCategory(frame)
	return p.suppressCategory(frame.args['1'])
end

function p.testcase_suppressDisambiguation(frame)
	return p.suppressDisambiguation(frame.args['1'])
end

function p.testcase_pageNameCorrespondToSpeciesOrInfraspecies(frame)
	return tostring(p.pageNameCorrespondToSpeciesOrInfraspecies(frame.args['1']))
end

function p.testcase_incorrectBiologyTemplateUsage(frame)
	local sortkey = frame.args['1']
	local errorToDisplayOrNil = frame.args['2']
	local templateNameForDocOrNil = frame.args['3']
	local ignoreNamespaceOrNil = frame.args.ignoreNamespaceOrNil
	if not ignoreNamespaceOrNil then
		ignoreNamespaceOrNil = frame.args['4']
	end
	return mw.text.nowiki(p.incorrectBiologyTemplateUsage(sortkey, errorToDisplayOrNil, templateNameForDocOrNil, ignoreNamespaceOrNil))
end

function p.testcase_incorrectBiologyTemplateUsageNoLink(frame)
	local sortkey = frame.args['1']
	local errorToDisplayOrNil = frame.args['2']
	local templateNameForDocOrNil = frame.args['3']
	local ignoreNamespaceOrNil = frame.args.ignoreNamespaceOrNil
	if not ignoreNamespaceOrNil then
		ignoreNamespaceOrNil = frame.args['4']
	end
	return mw.text.nowiki(p.incorrectBiologyTemplateUsageNoLink(sortkey, errorToDisplayOrNil, templateNameForDocOrNil, ignoreNamespaceOrNil))
end

return p