Module:Taxontree

-- 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 (P591) or when it reaches an entity whose taxon rank (P592) with value "kingdom" (Q2996) For stand-alone use: --

local p = {}

-- These are the qnumbers of taxon ranks that should have italicised values local italicvalues = { "Q2997", -- genus "Q2998", --subgenus "Q2999", -- section "Q3000", -- subsection "Q3001", -- series "Q3002", -- subseries "Q3003", -- species "Q3004", -- subspecies "Q3005", -- variety "Q3006", -- subvariety "Q3007", -- form "Q3008", -- subform }

-- _findlang takes a "langcode" parameter if supplied and valid Otherwise it tries to create it from the user's set language Failing that it uses the wiki's content language. It returns a language object Dependencies: none -- local _findlang = function(langcode) local langobj langcode = mw.text.trim(langcode or "") if mw.language.isKnownLanguageTag(langcode) then langobj = mw.language.new( langcode ) else langobj = mw.language.new( mw.getCurrentFrame:preprocess( '' ) ) if not langobj then langobj = mw.language.getContentLanguage end end return langobj end

-- _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 Gratisdata entity ID of the "category's main topic (P190)", if it exists failing that, the Gratisdata 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 (P190)": qid = mw.wikibase.getEntityIdForCurrentPage if qid then local prop190 = mw.wikibase.getBestStatements(qid, "P190") if prop190[1] then local mctid = prop190[1].mainsnak.datavalue.value.id			if mctid then return mctid end 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 P591 (parent taxon) qid is an entity-id  lang is an ISO-style language code first and authorcite are boolean Dependencies: _findlang -- local _show = function(qid, first, lang, authorcite) local langcode = _findlang(lang):getCode -- see if we want and can get a taxon author citation (P593, string value) local tac if authorcite then tac = mw.wikibase.getBestStatements(qid, "P593")[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, "P594")[1] taxonName = taxonName and taxonName.mainsnak.datavalue and taxonName.mainsnak.datavalue.value local taxonRank = mw.wikibase.getBestStatements(qid, "P592")[1] 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 == "Q2996" then finished = true end -- see if this entity-id has a Commons category local commonsCat = mw.wikibase.getBestStatements(qid, "P164")[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 for i, v in ipairs(italicvalues) do				if v == taxonRankID then taxonName = "''" .. taxonName .. "''"					break end end -- if there's a Commons category, make taxonName link to it			if commonsCat then taxonName = "" .. 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 = "" .. taxonRank .. " "				row = row .. "" row = row .. taxonName .. " " .. tac else row = "" .. taxonRank .. " "				row = row .. "" .. taxonName end rows[#rows+1] = row .. " "		end local parent = mw.wikibase.getBestStatements(qid, "P591")[1] if parent and parent.qualifiers and parent.qualifiers.P595 and parent.qualifiers.P595[1].datavalue then local rank = mw.wikibase.label(parent.qualifiers.P595[1].datavalue.value.id) if rank then rank = rank:sub(1, 1):upper .. rank:sub(2) local hdr = "" .. rank .. " "				rows[#rows+1] = hdr .. "incertae sedis " end 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 if #rows > 0 then for i, v in ipairs(rows) do			reversed[#rows + 1 - i] = v		end end return reversed end

--[[ This is the main entry point:

Dependencies: _parseparam; _getqid; _show; _findlang ]] 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 lang = mw.text.trim(frame.args.lang or "") local rows = table.concat( _show(qid, first, lang, authorcite), " ") if rows then return "" .. rows .. " "	end end

--[[ findLang returns the code property of the object returned from the _findlang function:

Dependencies: _findlang ]] p.findLang = function(frame) return _findlang( frame.args.lang or frame.args[1] ).code end

return p