Module:Taxontree

From Wikimedia Commons, the free media repository
Jump to navigation Jump to search
Lua

CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules

Module to display chain of taxon information in table format by following the links of parent taxon (P171).

This only returns table rows, so it needs to be invoked inside a table.

Each row displays the taxon rank (P105) as the row label and the taxon name (P225) linked to Commons category (P373) as the value.

If the parameter first=true, it displays the row for the item invoked, otherwise it doesn't. The default is false.

To display taxon author citation (P6507) set |authorcite=true (aliases |ac= and 'yes'). The default is false.

It finishes when it reaches an entity that has no parent taxon (P171) or when it reaches an entity whose taxon rank (P105) has the value kingdom (Q36732).

For stand-alone use:

{|
    {{#invoke:Taxontree |show |qid=<Qnnn> |first=yes/no |lang=<langcode>}}
|}

Code

--[[
Module:Taxontree
Module to display chain of taxon informatiom in table format.
This only returns table rows, so needs to be invoked inside a table.
Each row displays Taxon-Rank as row label and Taxon-Name linked to Commons Category as value
If parameter first=true, it displays the row for the item invoked
{default is false)
It finishes when it reaches an entity that has no parent taxon (P171)
or when it reaches an entity whose taxon rank (P105) with value "kingdom" (Q36732)
For stand-alone use:
{|
{{#invoke:Taxontree |show |qid=<Qnnn> |first=yes/no}}
|}
--]]


local p = {}


-- These are the qnumbers of taxon ranks that should have italicised values
local italicvalues = {
	Q34740    = true, -- genus
	Q3238261  = true, -- subgenus
	Q3181348  = true, -- section
	Q5998839  = true, -- subsection
	Q3025161  = true, -- series
	Q13198444 = true, -- subseries
	Q7432     = true, -- species
	Q68947    = true, -- subspecies
	Q767728   = true, -- variety
	Q630771   = true, -- subvariety
	Q279749   = true, -- form
	Q12774043 = true, -- subform
}


--[[
_parseparam takes a (string) parameter, e.g. from the list of frame arguments,
and makes "false", "no", and "0" into the (boolean) false
It makes the empty string and nil into the (boolean) value passed as default
allowing the parameter to be true or false by default.
Dependencies: none
--]]
local _parseparam = function(param, default)
	param = mw.text.trim(param or ""):lower()
	if param ~= "" then
		if (param == "false") or (param:sub(1,1) == "n") or (param == "0") then
			return false
		else
			return true
		end
	else
		return default
	end
end


--[[
_getqid returns the qid if supplied (uppercased and trimmed)
failing that, the Wikidata entity ID of the "category's main topic (P301)", if it exists
failing that, the Wikidata entity ID asociated with the curent page, if it exists
otherwise, nothing
Dependencies: none
--]]
local _getqid = function(qid)
	qid = mw.text.trim(qid or ""):upper()
	if qid ~= "" then return qid end
	-- check if there's a "category's main topic (P301)":
	qid = mw.wikibase.getEntityIdForCurrentPage()
	if qid then
		local prop301 = mw.wikibase.getBestStatements(qid, "P301")
		if prop301[1] then
			return prop301[1].mainsnak.datavalue.value.id
		end
	end
	-- otherwise return the page qid (if any)
	return qid
end


--[[
_show returns a Lua table containing the rows of an html table
Each row is one step in the chain of P171 (parent taxon)
qid is an entity-id <Qnnnn>
first and authorcite are boolean
--]]
local _show = function(qid, first, authorcite)
	-- see if we want and can get a taxon author citation (P6507, string value)
	local tac
	if authorcite then
		tac = mw.wikibase.getBestStatements(qid, "P6507")[1]
		tac = tac and tac.mainsnak.datavalue and tac.mainsnak.datavalue.value
	end
	local rows = {}
	local finished = false
	local count = 0
	repeat
		-- get the taxon name, rank and rank-id for this entity-id
		local taxonName = mw.wikibase.getBestStatements(qid, "P225")[1]
		taxonName = taxonName and taxonName.mainsnak.datavalue and taxonName.mainsnak.datavalue.value
		local taxonRank = mw.wikibase.getBestStatements(qid, "P105")[1]
		local taxonRankID = taxonRank and taxonRank.mainsnak.datavalue and taxonRank.mainsnak.datavalue.value.id
		taxonRank = taxonRankID and mw.wikibase.label(taxonRankID)
		-- if the rank is kingdom, finish looping
		if taxonRankID == "Q36732" then finished = true end
		-- see if this entity-id has a Commons category
		local commonsCat = mw.wikibase.getBestStatements(qid, "P373")[1]
		commonsCat = commonsCat and commonsCat.mainsnak.datavalue and commonsCat.mainsnak.datavalue.value
		if taxonRank and taxonName then
			taxonRank = taxonRank:gsub("^(%l)", string.upper) -- ucfirst
			-- test for ranks that should have italicised values
			if italicvalues[taxonRankID] then
				taxonName = "<i>" .. taxonName .. "</i>"
			end
			-- if there's a Commons category, make taxonName link to it
			if commonsCat then
				taxonName = "[[:Category:" .. commonsCat .. "|" .. taxonName .. "]]"
			end
			local row
			-- if this is the first one and taxon author citation is set, span the 2 columns
			if count == 0 and tac then
				row = "<th colspan='2' class='taxontree-hdrcell'>" .. taxonRank .. "</th></tr>"
				row = row .. "<tr class='taxontree-row'><td colspan='2' class='taxontree-fullcell'>"
				row = row .. taxonName .. "<br>" .. tac
			else
				row = "<th class='taxontree-lcell'>" .. taxonRank .. "</th>"
				row = row .. "<td class='taxontree-rcell'>" .. taxonName
			end
			rows[#rows+1] = row .. "</td>"
		end
		local parent = mw.wikibase.getBestStatements(qid, "P171")[1]
		local dv = parent and parent.qualifiers and parent.qualifiers.P678 and parent.qualifiers.P678[1].datavalue
		local rank = dv and mw.wikibase.label(dv.value.id)
		if rank then
			rank = rank:gsub("^%l", string.upper) -- ucfirst
			local hdr = "<th class='taxontree-lcell'>" .. rank .. "</th>"
			rows[#rows+1] = hdr .. "<td class='taxontree-rcell'>incertae sedis</td>"
		end
		if parent and parent.mainsnak.datavalue then
			qid = parent.mainsnak.datavalue.value.id
		else
			-- This is top-level location
			finished = true
		end
		count = count + 1
	until finished or count >= 30 -- limit to 30 levels to avoid infinite loops
	if not first and not tac then table.remove(rows, 1) end
	local reversed = {} -- reverse the table order
	for i = #rows, 1, -1 do
		reversed[#reversed+1] = rows[i]
	end
	return reversed
end


--[[
This is the main entry point:
{{#invoke:Taxontree |show |qid=<Qnnn> |first=yes/no |authorcite=yes/no}}
Dependencies: _parseparam(); _getqid(); _show()
]]
p.show = function(frame)
	local qid = _getqid(frame.args.qid or frame.args[1]) or ""
	if qid == "" then return "No id supplied" end
	local first = _parseparam(frame.args.first, false)
	local authorcite = _parseparam(frame.args.authorcite or frame.args.ac, false)
	local rows = table.concat( _show(qid, first, authorcite), "</tr><tr class='taxontree-row'>")
	if rows then
		return "<tr class='taxontree-row'>" .. rows .. "</tr>"
	end
end


return p