Difference between revisions of "Module:Taxonbar"
m (1 revision) |
m (1 revision: Suaeda) |
||
(15 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
require('Module:No globals') | require('Module:No globals') | ||
− | local conf = require( | + | local conf = require( 'Module:Taxonbar/conf' ) --configuration module |
+ | local TaxonItalics = require('Module:TaxonItalics') --use a function from Module:TaxonItalics to italicize a taxon name | ||
− | local function | + | --[[==========================================================================]] |
− | local | + | --[[ Local functions ]] |
− | if | + | --[[==========================================================================]] |
− | return | + | |
+ | local function isNilOrEmpty( thing ) | ||
+ | if thing == nil or thing == '' then | ||
+ | return true | ||
+ | end | ||
+ | return nil | ||
+ | end | ||
+ | |||
+ | local function getIdFromWikidata( item, property ) | ||
+ | local id = nil | ||
+ | if property == 'PWikispecies:$1' then | ||
+ | local siteLinks = item.sitelinks | ||
+ | if siteLinks then | ||
+ | local speciesWiki = item.sitelinks.specieswiki | ||
+ | if speciesWiki then | ||
+ | id = speciesWiki.title | ||
+ | end | ||
+ | end | ||
+ | return id | ||
+ | elseif item.claims[property] == nil then | ||
+ | return id | ||
end | end | ||
for _, statement in pairs( item.claims[property] ) do | for _, statement in pairs( item.claims[property] ) do | ||
if statement.mainsnak.datavalue then | if statement.mainsnak.datavalue then | ||
− | + | id = statement.mainsnak.datavalue.value | |
+ | break | ||
end | end | ||
end | end | ||
− | return | + | return id |
end | end | ||
local function getLink( property, val ) | local function getLink( property, val ) | ||
− | local link = '' | + | local link, returnVal = '', {} |
+ | |||
+ | returnVal.isError = false | ||
+ | |||
if mw.ustring.find( val, '//' ) then | if mw.ustring.find( val, '//' ) then | ||
link = val | link = val | ||
else | else | ||
− | if type(property) == 'number' then | + | if type(property) == 'number' and property > 0 then |
− | + | local entityObject = mw.wikibase.getEntity('P'..property) | |
+ | local dataType | ||
+ | |||
+ | if entityObject then dataType = entityObject.datatype | ||
+ | else returnVal.isError = true end | ||
+ | |||
+ | if dataType == 'external-id' then | ||
+ | local formatterURL = nil | ||
+ | if property == 3746 or --Wildflowers of Israel | ||
+ | property == 3795 or --Flora of Israel Online | ||
+ | property == 5397 --Tierstimmenarchiv | ||
+ | then | ||
+ | formatterURL = entityObject:getBestStatements('P1630')[2] --use 2nd formatterURL for English version | ||
+ | end | ||
+ | if formatterURL == nil then formatterURL = entityObject:getBestStatements('P1630')[1] end --default to [1] | ||
+ | if formatterURL then | ||
+ | if formatterURL.mainsnak.datavalue and formatterURL.mainsnak.datavalue.value then --nil check for ABA | ||
+ | link = formatterURL.mainsnak.datavalue.value | ||
+ | end | ||
+ | end | ||
+ | elseif dataType == 'url' then | ||
+ | local subjectItem = entityObject:getBestStatements('P1629')[1] | ||
+ | if subjectItem then | ||
+ | local officialWebsite = mw.wikibase.getEntity(subjectItem.mainsnak.datavalue.value.id):getBestStatements('P856')[1] | ||
+ | if officialWebsite then link = officialWebsite.mainsnak.datavalue.value end | ||
+ | end | ||
+ | elseif dataType == 'string' then | ||
+ | local formatterURL = entityObject:getBestStatements('P1630')[1] | ||
+ | if formatterURL then | ||
+ | link = formatterURL.mainsnak.datavalue.value | ||
+ | else | ||
+ | local subjectItem = entityObject:getBestStatements('P1629')[1] | ||
+ | if subjectItem then | ||
+ | local officialWebsite = mw.wikibase.getEntity(subjectItem.mainsnak.datavalue.value.id):getBestStatements('P856')[1] | ||
+ | if officialWebsite then link = officialWebsite.mainsnak.datavalue.value end | ||
+ | end | ||
+ | end | ||
+ | else | ||
+ | returnVal.isError = true | ||
+ | end | ||
elseif type(property) == 'string' then | elseif type(property) == 'string' then | ||
link = property | link = property | ||
end | end | ||
− | link = mw.ustring.gsub(link, '$1', | + | |
+ | local valurl = val | ||
+ | if mw.ustring.find( link, 'antweb.org' ) then valurl = mw.ustring.gsub(valurl, ' ', '%%20') end | ||
+ | if type(property) == 'number' then | ||
+ | --doublecheck language for Wildflowers of Israel ID | ||
+ | if property == 3746 then link = mw.ustring.gsub(link, '/hebrew/', '/english/') end | ||
+ | --format spaces in PfaF, e.g. for "Elaeagnus x ebbingei" | ||
+ | if property == 4301 then valurl = mw.ustring.gsub(valurl, ' ', '+') end | ||
+ | end | ||
+ | valurl = mw.ustring.gsub(valurl,'%%','%%%%') | ||
+ | link = mw.ustring.gsub(link, '$1', valurl) | ||
end | end | ||
+ | |||
link = mw.ustring.gsub(link, '^[Hh][Tt][Tt][Pp]([Ss]?)://', 'http%1://') -- fix wikidata URL | link = mw.ustring.gsub(link, '^[Hh][Tt][Tt][Pp]([Ss]?)://', 'http%1://') -- fix wikidata URL | ||
val = mw.ustring.match(val, '([^=/]*)/?$') -- get display name from end of URL | val = mw.ustring.match(val, '([^=/]*)/?$') -- get display name from end of URL | ||
if mw.ustring.find( link, '//' ) then | if mw.ustring.find( link, '//' ) then | ||
− | + | returnVal.text = '['..link..' '..mw.text.encode(mw.uri.decode(val, 'PATH'),'%[%]')..']' | |
+ | elseif link == '' then | ||
+ | returnVal.text = val | ||
else | else | ||
− | + | returnVal.text = '<span class="external">[['..link..'|'..val..']]</span>' | |
end | end | ||
+ | return returnVal | ||
end | end | ||
Line 43: | Line 121: | ||
return outStr..'>' .. link .. '</span></span>\n' | return outStr..'>' .. link .. '</span></span>\n' | ||
else | else | ||
− | return '* | + | return '* ' .. mw.text.tag('span', {class='error'}, 'The identifier ' .. id .. ' ' .. rawValue .. ' is not valid.') .. '\n' |
end | end | ||
end | end | ||
Line 55: | Line 133: | ||
local p = {} | local p = {} | ||
+ | |||
+ | --[[==========================================================================]] | ||
+ | --[[ Main ]] | ||
+ | --[[==========================================================================]] | ||
function p.authorityControlTaxon( frame ) | function p.authorityControlTaxon( frame ) | ||
+ | local resolveEntity = require( 'Module:ResolveEntityId' ) | ||
local parentArgs = copyTable(frame:getParent().args) | local parentArgs = copyTable(frame:getParent().args) | ||
+ | local currentTitle = mw.title.getCurrentTitle() | ||
+ | local currentEntityId = mw.wikibase.getEntityIdForCurrentPage() | ||
+ | |||
local stringArgs = false | local stringArgs = false | ||
− | -- | + | local fromTitleCount, firstRow, rowCount = 1, 0, 0 |
+ | local outString, errors = '', '' | ||
+ | local tFroms = {} --non-sequential table of unique froms | ||
+ | local iFroms = 0 --integer size of tFroms, b/c Lua | ||
+ | local categories = { | ||
+ | '[[Category:Taxonbars without from parameter]]', | ||
+ | '[[Category:Taxonbars desynced from Wikidata]]', | ||
+ | '', -- [3] placeholder for [[Category:Taxonbars using multiple manual Wikidata items]] | ||
+ | '', -- [4] placeholder for [[Category:Taxonbars with invalid from parameters]] | ||
+ | '', -- [5] placeholder for [[Category:Taxonbars using manual taxon IDs]] | ||
+ | '', -- [6] placeholder for [[Category:Taxonbar pages requiring a Wikidata item]] | ||
+ | '', -- [7] placeholder for [[Category:Taxonbar pages without Wikidata taxon IDs]] | ||
+ | '', -- [8] placeholder for [[Category:Taxonbars with duplicate from parameters]] | ||
+ | '', -- [9] placeholder for [[Category:Taxonbars with manual taxon IDs differing from Wikidata]] | ||
+ | '', --[10] placeholder for [[Category:Taxonbars with manual taxon IDs identical to Wikidata]] | ||
+ | '', --[11] placeholder for [[Category:Taxonbars on possible non-taxon pages]] | ||
+ | '', --[12] placeholder for [[Category:Taxonbars with 20–24 taxon IDs]] | ||
+ | '', --[13] placeholder for [[Category:Taxonbars with 25–29 taxon IDs]] | ||
+ | '', --[14] placeholder for [[Category:Taxonbars with 30–34 taxon IDs]] | ||
+ | '', --[15] placeholder for [[Category:Taxonbars with automatically added basionyms]] | ||
+ | '', --[16] placeholder for [[Category:Taxonbars with automatically added original combinations]] | ||
+ | '', --[17] placeholder for [[Category:Taxonbars with automatically added monotypic genera]] | ||
+ | '', --[18] placeholder for [[Category:Taxonbars of monotypic species missing genera]] | ||
+ | '', --[19] placeholder for [[Category:Taxonbars with unknown parameters]] | ||
+ | '', --[20] placeholder for [[Category:Taxonbars with 35–39 taxon IDs]] | ||
+ | '', --[21] placeholder for [[Category:Taxonbars with 40+ taxon IDs]] | ||
+ | } | ||
+ | |||
+ | --Assess the page's relationship with Wikidata | ||
+ | local currentItem = nil | ||
+ | if currentTitle.namespace == 10 then --i.e. Module:Taxonbar/sandbox, Template:Taxonbar/doc, etc. | ||
+ | if resolveEntity._id(parentArgs['from']) then | ||
+ | currentItem = mw.wikibase.getEntity(parentArgs['from']) | ||
+ | end | ||
+ | if currentItem == nil then | ||
+ | if resolveEntity._id(parentArgs['from1']) then | ||
+ | currentItem = mw.wikibase.getEntity(parentArgs['from1']) | ||
+ | end | ||
+ | end | ||
+ | elseif resolveEntity._id(currentEntityId) then | ||
+ | currentItem = mw.wikibase.getEntity(currentEntityId) | ||
+ | else --currentEntityId == nil/unresolvable | ||
+ | categories[6] = '[[Category:Taxonbar pages requiring a Wikidata item]]' | ||
+ | end | ||
+ | if currentItem then | ||
+ | local acceptable = { | ||
+ | ['Q16521'] = 'taxon', --strict | ||
+ | ['Q310890'] = 'monotypic taxon', --strict | ||
+ | ['Q2568288'] = 'ichnotaxon', --strict | ||
+ | ['Q23038290'] = 'fossil taxon', --strict | ||
+ | ['Q47487597'] = 'monotypic fossil taxon', --strict | ||
+ | ['Q42621'] = 'hybrid', --lax | ||
+ | ['Q235536'] = 'incertae sedis', --lax | ||
+ | ['Q713623'] = 'clade', --lax | ||
+ | ['Q848328'] = 'serotype', --lax | ||
+ | ['Q857968'] = 'candidatus', --lax | ||
+ | ['Q17487588'] = 'unavailable combination', --lax | ||
+ | } | ||
+ | categories[11] = '[[Category:Taxonbars on possible non-taxon pages]]' --unset if acceptable found | ||
+ | for _, instanceOfState in pairs ( currentItem:getBestStatements('P31') ) do --instance of | ||
+ | local instanceOf = instanceOfState.mainsnak.datavalue.value.id | ||
+ | if acceptable[instanceOf] then | ||
+ | categories[11] = '' | ||
+ | break | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | |||
+ | --Cleanup args | ||
for k, v in pairs( frame:getParent().args ) do | for k, v in pairs( frame:getParent().args ) do | ||
if type(k) == 'string' then | if type(k) == 'string' then | ||
− | + | --make args case insensitive | |
local lowerk = mw.ustring.lower(k) | local lowerk = mw.ustring.lower(k) | ||
− | if | + | if isNilOrEmpty( parentArgs[lowerk] ) then |
+ | parentArgs[k] = nil | ||
parentArgs[lowerk] = v | parentArgs[lowerk] = v | ||
− | |||
end | end | ||
− | if v and v ~= '' and v | + | --remap abc to abc1 |
+ | if mw.ustring.find(lowerk,'%d$') == nil then --if no number at end of param | ||
+ | if isNilOrEmpty( parentArgs[lowerk..'1'] ) then | ||
+ | parentArgs[lowerk] = nil | ||
+ | lowerk = lowerk..'1' | ||
+ | parentArgs[lowerk] = v | ||
+ | end | ||
+ | end | ||
+ | if v and v ~= '' then | ||
+ | --remap 'for' to 'title' | ||
+ | if mw.ustring.sub(lowerk,1,3) == 'for' then | ||
+ | local forTitle = mw.ustring.gsub(lowerk,'^for','title',1) | ||
+ | if isNilOrEmpty( parentArgs[forTitle] ) then | ||
+ | parentArgs[lowerk] = nil | ||
+ | lowerk = forTitle | ||
+ | parentArgs[lowerk] = v | ||
+ | end | ||
+ | end | ||
+ | --find highest from or title param | ||
+ | if mw.ustring.sub(lowerk,1,4) == 'from' then | ||
+ | local fromNumber = tonumber(mw.ustring.sub(lowerk,5,-1)) | ||
+ | if fromNumber and fromNumber >= fromTitleCount then fromTitleCount = fromNumber end | ||
+ | --look for duplicate froms while we're here | ||
+ | if mw.ustring.find(v, '^Q%d') then | ||
+ | if tFroms[v] then | ||
+ | categories[8] = '[[Category:Taxonbars with duplicate from parameters]]' | ||
+ | tFroms[v] = tFroms[v] + 1 | ||
+ | else | ||
+ | tFroms[v] = 1 | ||
+ | iFroms = iFroms + 1 | ||
+ | end | ||
+ | if iFroms == 2 then | ||
+ | categories[3] = '[[Category:Taxonbars using multiple manual Wikidata items]]' | ||
+ | end | ||
+ | end | ||
+ | elseif mw.ustring.sub(lowerk,1,5) == 'title' then | ||
+ | local titleNumber = tonumber(mw.ustring.sub(lowerk,4,-1)) | ||
+ | if titleNumber and titleNumber >= fromTitleCount then fromTitleCount = titleNumber end | ||
+ | elseif mw.ustring.lower(v) ~= 'no' then | ||
+ | stringArgs = true | ||
+ | categories[5] = '[[Category:Taxonbars using manual taxon IDs]]' | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | |||
+ | --Check for unknown parameters | ||
+ | --create knowns list | ||
+ | local acceptableArgs = { from = true, } --master list of l/c acceptable args | ||
+ | for _, d in pairs( conf.databases ) do | ||
+ | if d[1] ~= 'Wikidata' then --made obsolete by from | ||
+ | acceptableArgs[mw.ustring.lower(d[1])] = true | ||
end | end | ||
end | end | ||
− | |||
for _, a in pairs( conf.aliases ) do | for _, a in pairs( conf.aliases ) do | ||
− | + | acceptableArgs[mw.ustring.lower(a[1])] = true | |
− | + | end | |
− | + | --create trimmed parents list | |
− | + | local baseParentArgs = {} --condensed list of l/c parent args w/o trailing #s | |
+ | for k, v in pairs( parentArgs ) do | ||
+ | if type(k) == 'string' then --ignore unnamed params, which have keys of type 'number' | ||
+ | local lowerk = mw.ustring.lower(k) | ||
+ | local base = mw.ustring.gsub(lowerk, '[%d]*$', '') | ||
+ | baseParentArgs[base] = true | ||
+ | end | ||
+ | end | ||
+ | --compare lists and spit out unknowns | ||
+ | local unknownParams = {} | ||
+ | for k, v in pairs( baseParentArgs ) do | ||
+ | if acceptableArgs[k] == nil then | ||
+ | categories[19] = '[[Category:Taxonbars with unknown parameters|' .. k ..']]' | ||
+ | unknownParams[#unknownParams + 1] = k | ||
end | end | ||
end | end | ||
− | -- | + | --warn if unknown(s) present |
− | local | + | if #unknownParams > 0 then |
− | + | local plural = nil | |
− | + | local itthem = nil | |
− | + | if #unknownParams == 1 then | |
− | + | plural = '' | |
− | + | itthem = 'it' | |
+ | else | ||
+ | plural = 's' | ||
+ | itthem = 'them' | ||
+ | end | ||
+ | if frame:preprocess( '{{REVISIONID}}' ) == '' then | ||
+ | errors = errors..'<div class="hatnote" style="color:red">'.. | ||
+ | '<strong>Warning:</strong> unknown parameter'..plural..' <strong>'..table.concat(unknownParams, ', ')..'</strong>.<br />'.. | ||
+ | 'Please correct '..itthem..' or consider adding '..itthem..' to Wikidata.<br />'.. | ||
+ | 'This message is only shown in preview.</div>' | ||
+ | end | ||
end | end | ||
− | if | + | |
− | + | --Append basionym to arg list, if not already provided | |
− | + | if currentItem then | |
− | + | local currentBasState = currentItem:getBestStatements('P566')[1] --basionym | |
− | + | if currentBasState then | |
− | if ( | + | local basionymId = currentBasState.mainsnak.datavalue.value.id |
− | local | + | if basionymId and resolveEntity._id(basionymId) and tFroms[basionymId] == nil then |
− | + | --check that basionym is a strict instance of taxon | |
− | + | local basionymItem = mw.wikibase.getEntity(basionymId) | |
+ | if basionymItem then | ||
+ | local acceptable = { | ||
+ | ['Q16521'] = 'taxon', --strict | ||
+ | ['Q310890'] = 'monotypic taxon', --strict | ||
+ | ['Q2568288'] = 'ichnotaxon', --strict | ||
+ | ['Q23038290'] = 'fossil taxon', --strict | ||
+ | ['Q47487597'] = 'monotypic fossil taxon', --strict | ||
+ | } | ||
+ | for _, instanceOfState in pairs ( basionymItem:getBestStatements('P31') ) do --instance of | ||
+ | local instanceOf = instanceOfState.mainsnak.datavalue.value.id | ||
+ | if acceptable[instanceOf] then | ||
+ | --housekeeping | ||
+ | tFroms[basionymId] = 1 | ||
+ | iFroms = iFroms + 1 | ||
+ | fromTitleCount = fromTitleCount + 1 | ||
+ | --append basionym & track | ||
+ | parentArgs['from'..fromTitleCount] = basionymId | ||
+ | categories[15] = '[[Category:Taxonbars with automatically added basionyms]]' | ||
+ | break | ||
+ | end end end end end end | ||
+ | |||
+ | --Append original combination to arg list, if not already provided | ||
+ | if currentItem then | ||
+ | local currentOCState = currentItem:getBestStatements('P1403')[1] --original combination | ||
+ | if currentOCState then | ||
+ | local orcoId = currentOCState.mainsnak.datavalue.value.id | ||
+ | if orcoId and resolveEntity._id(orcoId) and tFroms[orcoId] == nil then | ||
+ | --check that orco is a strict instance of taxon | ||
+ | local orcoItem = mw.wikibase.getEntity(orcoId) | ||
+ | if orcoItem then | ||
+ | local acceptable = { | ||
+ | ['Q16521'] = 'taxon', --strict | ||
+ | ['Q310890'] = 'monotypic taxon', --strict | ||
+ | ['Q2568288'] = 'ichnotaxon', --strict | ||
+ | ['Q23038290'] = 'fossil taxon', --strict | ||
+ | ['Q47487597'] = 'monotypic fossil taxon', --strict | ||
+ | } | ||
+ | for _, instanceOfState in pairs ( orcoItem:getBestStatements('P31') ) do --instance of | ||
+ | local instanceOf = instanceOfState.mainsnak.datavalue.value.id | ||
+ | if acceptable[instanceOf] then | ||
+ | --housekeeping | ||
+ | tFroms[orcoId] = 1 | ||
+ | iFroms = iFroms + 1 | ||
+ | fromTitleCount = fromTitleCount + 1 | ||
+ | --append orco & track | ||
+ | parentArgs['from'..fromTitleCount] = orcoId | ||
+ | categories[16] = '[[Category:Taxonbars with automatically added original combinations]]' | ||
+ | break | ||
+ | end end end end end end | ||
+ | |||
+ | --Append monotypic genus/species to arg list of monotypic species/genus, if not already provided | ||
+ | if currentItem then | ||
+ | for _, instanceOfState in pairs ( currentItem:getBestStatements('P31') ) do --instance of | ||
+ | local taxonRank = nil | ||
+ | local parentItem = nil | ||
+ | local parentTaxon = nil | ||
+ | local parentTaxonRank = nil | ||
+ | local parentMonoGenus = nil --holy grail/tbd | ||
+ | local instanceOf = instanceOfState.mainsnak.datavalue.value.id | ||
+ | if instanceOf and (instanceOf == 'Q310890' or instanceOf == 'Q47487597') then --monotypic/fossil taxon | ||
+ | local taxonRankState = currentItem:getBestStatements('P105')[1] --taxon rank | ||
+ | if taxonRankState then taxonRank = taxonRankState.mainsnak.datavalue.value.id end | ||
+ | |||
+ | if taxonRank and taxonRank == 'Q7432' then --species | ||
+ | --is monotypic species; add genus | ||
+ | local parentTaxonState = currentItem:getBestStatements('P171')[1] --parent taxon | ||
+ | if parentTaxonState then parentTaxon = parentTaxonState.mainsnak.datavalue.value.id end | ||
+ | --confirm parent taxon rank == genus & monotypic | ||
+ | if parentTaxon and resolveEntity._id(parentTaxon) then | ||
+ | parentItem = mw.wikibase.getEntity(parentTaxon) | ||
+ | if parentItem then | ||
+ | local parentTaxonRankState = parentItem:getBestStatements('P105')[1] --taxon rank | ||
+ | if parentTaxonRankState then parentTaxonRank = parentTaxonRankState.mainsnak.datavalue.value.id end | ||
+ | if parentTaxonRank and parentTaxonRank == 'Q34740' then --parent == genus | ||
+ | for _, parentInstanceOfState in pairs ( parentItem:getBestStatements('P31') ) do --instance of | ||
+ | local parentInstanceOf = parentInstanceOfState.mainsnak.datavalue.value.id | ||
+ | if parentInstanceOf and | ||
+ | (parentInstanceOf == 'Q310890' or parentInstanceOf == 'Q47487597') then --monotypic/fossil taxon | ||
+ | parentMonoGenus = parentTaxon --confirmed | ||
+ | break | ||
+ | end | ||
+ | end | ||
+ | if parentMonoGenus and tFroms[parentMonoGenus] == nil then | ||
+ | --housekeeping | ||
+ | tFroms[parentMonoGenus] = 1 | ||
+ | iFroms = iFroms + 1 | ||
+ | fromTitleCount = fromTitleCount + 1 | ||
+ | --append monotypic genus & track | ||
+ | parentArgs['from'..fromTitleCount] = parentMonoGenus | ||
+ | categories[17] = '[[Category:Taxonbars with automatically added monotypic genera]]' | ||
+ | break | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | if parentMonoGenus == nil or tFroms[parentMonoGenus] == nil then | ||
+ | categories[18] = '[[Category:Taxonbars of monotypic species missing genera]]' | ||
+ | break | ||
+ | end | ||
+ | elseif taxonRank and taxonRank == 'Q34740' then --genus | ||
+ | --is monotypic genus; add species | ||
+ | --... | ||
end | end | ||
+ | |||
end | end | ||
− | + | end | |
− | + | end --if currentItem | |
− | + | ||
− | + | --Setup navbox | |
+ | local navboxParams = { | ||
+ | name = 'Taxonbar', | ||
+ | bodyclass = 'hlist', | ||
+ | listclass = '', | ||
+ | groupstyle = 'text-align: left;', | ||
+ | } | ||
+ | |||
+ | for f = 1, fromTitleCount, 1 | ||
+ | do | ||
+ | local elements, title = {}, nil | ||
+ | --cleanup parameters | ||
+ | if parentArgs['from'..f] == '' then parentArgs['from'..f] = nil end | ||
+ | if parentArgs['title'..f] == '' then parentArgs['title'..f] = nil end | ||
+ | --remap aliases | ||
+ | for _, a in pairs( conf.aliases ) do | ||
+ | local alias, name = mw.ustring.lower(a[1]), mw.ustring.lower(a[2]) | ||
+ | if parentArgs[alias..f] and parentArgs[name..f] == nil then | ||
+ | parentArgs[name..f] = parentArgs[alias..f] | ||
+ | parentArgs[alias..f] = nil | ||
+ | end | ||
+ | end | ||
+ | --Fetch Wikidata item | ||
+ | local from = resolveEntity._id(parentArgs['from'..f]) | ||
+ | local item = mw.wikibase.getEntity(from) | ||
+ | local label = nil | ||
+ | if type(item) == 'table' then | ||
+ | local statements = item:getBestStatements('P225')[1] --taxon name | ||
+ | if statements then | ||
+ | local datavalue = statements.mainsnak.datavalue | ||
+ | if datavalue then | ||
+ | label = datavalue.value | ||
+ | end | ||
+ | end | ||
+ | label = label or item:getLabel() | ||
+ | else | ||
+ | if parentArgs['from'..f] then | ||
+ | categories[1] = '' | ||
+ | categories[4] = '[[Category:Taxonbars with invalid from parameters]]' | ||
+ | errors = errors .. mw.text.tag('strong', {class='error'}, 'Error: "' .. | ||
+ | parentArgs['from'..f] .. '" is not a valid Wikidata entity ID.<br />') | ||
end | end | ||
+ | end | ||
+ | if label and label ~= '' then | ||
+ | title = mw.title.new(label) | ||
+ | end | ||
+ | if title == nil and parentArgs['title'..f] then | ||
+ | title = mw.title.new(parentArgs['title'..f]) | ||
+ | end | ||
+ | if title == nil and f == 1 then | ||
+ | title = currentTitle | ||
end | end | ||
+ | if title then | ||
+ | if isNilOrEmpty( parentArgs['wikidata'..f] ) and | ||
+ | (title.namespace == 0) then | ||
+ | if parentArgs['from'..f] then | ||
+ | parentArgs['wikidata'..f] = parentArgs['from'..f] | ||
+ | elseif item then | ||
+ | parentArgs['wikidata'..f] = item.id | ||
+ | end | ||
+ | end | ||
+ | if title.namespace == 0 or stringArgs then --only in mainspace or if manual overrides exist | ||
+ | local sourceCount = 0 | ||
+ | for _, params in pairs( conf.databases ) do | ||
+ | params[1] = mw.ustring.lower(params[1]) | ||
+ | local propId = params[3] | ||
+ | --Wikidata fallback if requested | ||
+ | if (item and item.claims) and | ||
+ | (type(propId) == 'string' or (type(propId) == 'number' and propId > 0)) then | ||
+ | local wikidataId = getIdFromWikidata( item, 'P' .. propId ) | ||
+ | local v = parentArgs[params[1]..f] | ||
+ | if wikidataId then | ||
+ | if isNilOrEmpty(v) then | ||
+ | parentArgs[params[1]..f] = wikidataId | ||
+ | else | ||
+ | if v and v ~= 'no' and v ~= wikidataId then | ||
+ | categories[9] = '[[Category:Taxonbars with manual taxon IDs differing from Wikidata]]' | ||
+ | elseif v and v == wikidataId then | ||
+ | categories[10] = '[[Category:Taxonbars with manual taxon IDs identical to Wikidata]]' | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | local val = parentArgs[params[1]..f] | ||
+ | if val and val ~= '' and mw.ustring.lower(val) ~= 'no' then | ||
+ | if type(propId) == 'number' then | ||
+ | if propId < 0 then propId = -propId end --allow link | ||
+ | if propId > 0 then --link | ||
+ | table.insert( elements, createRow( params[1], params[2]..':', val, getLink( propId, val ).text, true ) ) | ||
+ | else --propId == 0; no link | ||
+ | table.insert( elements, createRow( params[1], params[2]..':', val, val, true ) ) | ||
+ | end | ||
+ | else | ||
+ | table.insert( elements, createRow( params[1], params[2]..':', val, getLink( propId, val ).text, true ) ) | ||
+ | end | ||
+ | if params[1] ~= 'wikidata' and params[1] ~= 'wikispecies' then | ||
+ | sourceCount = sourceCount + 1 | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | |||
+ | if sourceCount >= 40 then categories[21] = '[[Category:Taxonbars with 40+ taxon IDs]]' | ||
+ | elseif sourceCount >= 35 then categories[20] = '[[Category:Taxonbars with 35–39 taxon IDs]]' --endashes | ||
+ | elseif sourceCount >= 30 then categories[14] = '[[Category:Taxonbars with 30–34 taxon IDs]]' | ||
+ | elseif sourceCount >= 25 then categories[13] = '[[Category:Taxonbars with 25–29 taxon IDs]]' | ||
+ | elseif sourceCount >= 20 then categories[12] = '[[Category:Taxonbars with 20–24 taxon IDs]]' | ||
+ | end | ||
+ | |||
+ | --Generate navbox title | ||
+ | if sourceCount > 0 then | ||
+ | rowCount = rowCount + 1 | ||
+ | if firstRow == 0 then firstRow = f end | ||
+ | --set title from wikidata if it doesn't exist | ||
+ | if isNilOrEmpty( parentArgs['title'..f] ) then | ||
+ | parentArgs['noTitle'..f] = true | ||
+ | parentArgs['title'..f] = title.text | ||
+ | end | ||
+ | --if it exists now, set row heading to title | ||
+ | if not isNilOrEmpty( parentArgs['title'..f] ) then | ||
+ | navboxParams['group'..f] = TaxonItalics.italicizeTaxonName(parentArgs['title'..f], false) | ||
+ | else | ||
+ | navboxParams['group'..f] = '' | ||
+ | end | ||
+ | navboxParams['list'..f] = table.concat( elements ) | ||
+ | elseif currentEntityId then | ||
+ | categories[7] = '[[Category:Taxonbar pages without Wikidata taxon IDs]]' | ||
+ | end | ||
+ | |||
+ | --Categorize | ||
+ | if not isNilOrEmpty( parentArgs['from'..f] ) then | ||
+ | --blank "missing from" if 'from' exists | ||
+ | categories[1] = '' | ||
+ | --blank "desynced" if 'from' matches current page | ||
+ | if parentArgs['from'..f] == currentEntityId then categories[2] = '' end | ||
+ | end | ||
+ | --cannot be "desynced" if no 'from' params | ||
+ | if categories[1] ~= '' then categories[2] = '' end | ||
+ | end | ||
+ | end | ||
+ | end --for f = 1, fromTitleCount, 1 | ||
+ | |||
+ | if rowCount > 0 then | ||
local Navbox = require('Module:Navbox') | local Navbox = require('Module:Navbox') | ||
− | + | if rowCount > 1 then | |
− | if | + | --remove duplicates and move page title to top |
− | + | local rowIDs = {} | |
− | + | for f = 1,fromTitleCount,1 | |
− | + | do | |
− | + | if not isNilOrEmpty( parentArgs['title'..f] ) then | |
− | + | if rowIDs[parentArgs['wikidata'..f]] then --remove duplicate | |
− | + | navboxParams['group'..f] = nil | |
− | + | navboxParams['list'..f] = nil | |
+ | else | ||
+ | rowIDs[parentArgs['wikidata'..f]] = true | ||
+ | if f > firstRow and (parentArgs['title'..f] == currentTitle.text or | ||
+ | parentArgs['wikidata'..f] == currentEntityId) then --move item linked to page to top | ||
+ | if navboxParams['group'..f] and | ||
+ | navboxParams['group'..f] ~= '' and | ||
+ | navboxParams['list'..f] and | ||
+ | navboxParams['list'..f] ~= '' then | ||
+ | local tempGroup, tempList = navboxParams['group'..f], navboxParams['list'..f] | ||
+ | navboxParams['group'..f], navboxParams['list'..f] = navboxParams['group'..firstRow], navboxParams['list'..firstRow] | ||
+ | navboxParams['group'..firstRow], navboxParams['list'..firstRow] = tempGroup, tempList | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | --adjust navbox for number of rows | ||
+ | navboxParams['title'] = '[[Help:Taxon identifiers|Taxon identifiers]]' | ||
+ | if rowCount > 2 then | ||
+ | navboxParams['navbar'] = 'plain' | ||
+ | else | ||
+ | navboxParams['state'] = 'off' | ||
+ | navboxParams['navbar'] = 'off' | ||
+ | end | ||
+ | elseif parentArgs['noTitle'..firstRow] then | ||
+ | navboxParams['group'..firstRow] = '[[Help:Taxon identifiers|Taxon identifiers]]' | ||
else | else | ||
− | + | navboxParams['group'..firstRow] = '[[Help:Taxon identifiers|Taxon identifiers]]<br />' .. navboxParams['group'..firstRow] | |
end | end | ||
+ | |||
+ | --return navbox | ||
+ | outString = Navbox._navbox(navboxParams) | ||
+ | end --if rowCount > 0 | ||
+ | |||
+ | --Add categories | ||
+ | if string.sub(currentTitle.subpageText,1,9) == 'testcases' then parentArgs['demo'] = true end | ||
+ | if not isNilOrEmpty( parentArgs['demo'] ) then | ||
+ | outString = outString .. mw.text.nowiki(table.concat(categories)) .. '<br />' | ||
+ | elseif currentTitle.namespace == 0 then | ||
+ | outString = outString .. table.concat(categories) | ||
end | end | ||
+ | |||
+ | return outString .. errors | ||
end | end | ||
return p | return p |
Latest revision as of 17:35, 18 December 2018
require('Module:No globals')
local conf = require( 'Module:Taxonbar/conf' ) --configuration module local TaxonItalics = require('Module:TaxonItalics') --use a function from Module:TaxonItalics to italicize a taxon name
--========================================================================== --Local functions --==========================================================================
local function isNilOrEmpty( thing ) if thing == nil or thing == then return true end return nil end
local function getIdFromWikidata( item, property ) local id = nil if property == 'PWikispecies:$1' then local siteLinks = item.sitelinks if siteLinks then local speciesWiki = item.sitelinks.specieswiki if speciesWiki then id = speciesWiki.title end end return id elseif item.claims[property] == nil then return id end for _, statement in pairs( item.claims[property] ) do if statement.mainsnak.datavalue then id = statement.mainsnak.datavalue.value break end end return id end
local function getLink( property, val ) local link, returnVal = , {}
returnVal.isError = false
if mw.ustring.find( val, '//' ) then link = val else if type(property) == 'number' and property > 0 then local entityObject = mw.wikibase.getEntity('P'..property) local dataType
if entityObject then dataType = entityObject.datatype else returnVal.isError = true end
if dataType == 'external-id' then local formatterURL = nil if property == 3746 or --Wildflowers of Israel property == 3795 or --Flora of Israel Online property == 5397 --Tierstimmenarchiv then formatterURL = entityObject:getBestStatements('P1630')[2] --use 2nd formatterURL for English version end if formatterURL == nil then formatterURL = entityObject:getBestStatements('P1630')[1] end --default to [1] if formatterURL then if formatterURL.mainsnak.datavalue and formatterURL.mainsnak.datavalue.value then --nil check for ABA link = formatterURL.mainsnak.datavalue.value end end elseif dataType == 'url' then local subjectItem = entityObject:getBestStatements('P1629')[1] if subjectItem then local officialWebsite = mw.wikibase.getEntity(subjectItem.mainsnak.datavalue.value.id):getBestStatements('P856')[1] if officialWebsite then link = officialWebsite.mainsnak.datavalue.value end end elseif dataType == 'string' then local formatterURL = entityObject:getBestStatements('P1630')[1] if formatterURL then link = formatterURL.mainsnak.datavalue.value else local subjectItem = entityObject:getBestStatements('P1629')[1] if subjectItem then local officialWebsite = mw.wikibase.getEntity(subjectItem.mainsnak.datavalue.value.id):getBestStatements('P856')[1] if officialWebsite then link = officialWebsite.mainsnak.datavalue.value end end end else returnVal.isError = true end elseif type(property) == 'string' then link = property end
local valurl = val if mw.ustring.find( link, 'antweb.org' ) then valurl = mw.ustring.gsub(valurl, ' ', '%%20') end if type(property) == 'number' then --doublecheck language for Wildflowers of Israel ID if property == 3746 then link = mw.ustring.gsub(link, '/hebrew/', '/english/') end --format spaces in PfaF, e.g. for "Elaeagnus x ebbingei" if property == 4301 then valurl = mw.ustring.gsub(valurl, ' ', '+') end end valurl = mw.ustring.gsub(valurl,'%%','%%%%') link = mw.ustring.gsub(link, '$1', valurl) end
link = mw.ustring.gsub(link, '^[Hh][Tt][Tt][Pp]([Ss]?)://', 'http%1://') -- fix wikidata URL val = mw.ustring.match(val, '([^=/]*)/?$') -- get display name from end of URL if mw.ustring.find( link, '//' ) then returnVal.text = '['..link..' '..mw.text.encode(mw.uri.decode(val, 'PATH'),'%[%]')..']' elseif link == then returnVal.text = val else returnVal.text = ''..val..'' end return returnVal end
local function createRow( id, label, rawValue, link, withUid ) if link then local outStr = '*' .. label .. ' <span' if withUid then outStr = outStr..' class="uid"' end return outStr..'>' .. link .. '\n' else return '* ' .. mw.text.tag('span', {class='error'}, 'The identifier ' .. id .. ' ' .. rawValue .. ' is not valid.') .. '\n' end end
local function copyTable(inTable) if type(inTable) ~= 'table' then return inTable end local outTable = setmetatable({}, getmetatable(inTable)) for key, value in pairs (inTable) do outTable[copyTable(key)] = copyTable(value) end return outTable end
local p = {}
--========================================================================== --Main --==========================================================================
function p.authorityControlTaxon( frame ) local resolveEntity = require( 'Module:ResolveEntityId' ) local parentArgs = copyTable(frame:getParent().args) local currentTitle = mw.title.getCurrentTitle() local currentEntityId = mw.wikibase.getEntityIdForCurrentPage()
local stringArgs = false local fromTitleCount, firstRow, rowCount = 1, 0, 0 local outString, errors = , local tFroms = {} --non-sequential table of unique froms local iFroms = 0 --integer size of tFroms, b/c Lua local categories = { , , , -- [3] placeholder for , -- [4] placeholder for , -- [5] placeholder for , -- [6] placeholder for , -- [7] placeholder for , -- [8] placeholder for , -- [9] placeholder for , --[10] placeholder for , --[11] placeholder for , --[12] placeholder for , --[13] placeholder for , --[14] placeholder for , --[15] placeholder for , --[16] placeholder for , --[17] placeholder for , --[18] placeholder for , --[19] placeholder for , --[20] placeholder for , --[21] placeholder for }
--Assess the page's relationship with Wikidata local currentItem = nil if currentTitle.namespace == 10 then --i.e. Module:Taxonbar/sandbox, Template:Taxonbar/doc, etc. if resolveEntity._id(parentArgs['from']) then currentItem = mw.wikibase.getEntity(parentArgs['from']) end if currentItem == nil then if resolveEntity._id(parentArgs['from1']) then currentItem = mw.wikibase.getEntity(parentArgs['from1']) end end elseif resolveEntity._id(currentEntityId) then currentItem = mw.wikibase.getEntity(currentEntityId) else --currentEntityId == nil/unresolvable categories[6] = end if currentItem then local acceptable = { ['Q16521'] = 'taxon', --strict ['Q310890'] = 'monotypic taxon', --strict ['Q2568288'] = 'ichnotaxon', --strict ['Q23038290'] = 'fossil taxon', --strict ['Q47487597'] = 'monotypic fossil taxon', --strict ['Q42621'] = 'hybrid', --lax ['Q235536'] = 'incertae sedis', --lax ['Q713623'] = 'clade', --lax ['Q848328'] = 'serotype', --lax ['Q857968'] = 'candidatus', --lax ['Q17487588'] = 'unavailable combination', --lax } categories[11] = --unset if acceptable found for _, instanceOfState in pairs ( currentItem:getBestStatements('P31') ) do --instance of local instanceOf = instanceOfState.mainsnak.datavalue.value.id if acceptable[instanceOf] then categories[11] = break end end end
--Cleanup args for k, v in pairs( frame:getParent().args ) do if type(k) == 'string' then --make args case insensitive local lowerk = mw.ustring.lower(k) if isNilOrEmpty( parentArgs[lowerk] ) then parentArgs[k] = nil parentArgs[lowerk] = v end --remap abc to abc1 if mw.ustring.find(lowerk,'%d$') == nil then --if no number at end of param if isNilOrEmpty( parentArgs[lowerk..'1'] ) then parentArgs[lowerk] = nil lowerk = lowerk..'1' parentArgs[lowerk] = v end end if v and v ~= then --remap 'for' to 'title' if mw.ustring.sub(lowerk,1,3) == 'for' then local forTitle = mw.ustring.gsub(lowerk,'^for','title',1) if isNilOrEmpty( parentArgs[forTitle] ) then parentArgs[lowerk] = nil lowerk = forTitle parentArgs[lowerk] = v end end --find highest from or title param if mw.ustring.sub(lowerk,1,4) == 'from' then local fromNumber = tonumber(mw.ustring.sub(lowerk,5,-1)) if fromNumber and fromNumber >= fromTitleCount then fromTitleCount = fromNumber end --look for duplicate froms while we're here if mw.ustring.find(v, '^Q%d') then if tFroms[v] then categories[8] = tFroms[v] = tFroms[v] + 1 else tFroms[v] = 1 iFroms = iFroms + 1 end if iFroms == 2 then categories[3] = end end elseif mw.ustring.sub(lowerk,1,5) == 'title' then local titleNumber = tonumber(mw.ustring.sub(lowerk,4,-1)) if titleNumber and titleNumber >= fromTitleCount then fromTitleCount = titleNumber end elseif mw.ustring.lower(v) ~= 'no' then stringArgs = true categories[5] = end end end end
--Check for unknown parameters --create knowns list local acceptableArgs = { from = true, } --master list of l/c acceptable args for _, d in pairs( conf.databases ) do if d[1] ~= 'Wikidata' then --made obsolete by from acceptableArgs[mw.ustring.lower(d[1])] = true end end for _, a in pairs( conf.aliases ) do acceptableArgs[mw.ustring.lower(a[1])] = true end --create trimmed parents list local baseParentArgs = {} --condensed list of l/c parent args w/o trailing #s for k, v in pairs( parentArgs ) do if type(k) == 'string' then --ignore unnamed params, which have keys of type 'number' local lowerk = mw.ustring.lower(k) local base = mw.ustring.gsub(lowerk, '[%d]*$', ) baseParentArgs[base] = true end end --compare lists and spit out unknowns local unknownParams = {} for k, v in pairs( baseParentArgs ) do if acceptableArgs[k] == nil then categories[19] = unknownParams[#unknownParams + 1] = k end end --warn if unknown(s) present if #unknownParams > 0 then local plural = nil local itthem = nil if #unknownParams == 1 then plural = itthem = 'it' else plural = 's' itthem = 'them' end if frame:preprocess( '15169' ) == then
errors = errors..'
'Warning: unknown parameter'..plural..' '..table.concat(unknownParams, ', ')..'.
'..
'Please correct '..itthem..' or consider adding '..itthem..' to Wikidata.
'..
'
end end
--Append basionym to arg list, if not already provided if currentItem then local currentBasState = currentItem:getBestStatements('P566')[1] --basionym if currentBasState then local basionymId = currentBasState.mainsnak.datavalue.value.id if basionymId and resolveEntity._id(basionymId) and tFroms[basionymId] == nil then --check that basionym is a strict instance of taxon local basionymItem = mw.wikibase.getEntity(basionymId) if basionymItem then local acceptable = { ['Q16521'] = 'taxon', --strict ['Q310890'] = 'monotypic taxon', --strict ['Q2568288'] = 'ichnotaxon', --strict ['Q23038290'] = 'fossil taxon', --strict ['Q47487597'] = 'monotypic fossil taxon', --strict } for _, instanceOfState in pairs ( basionymItem:getBestStatements('P31') ) do --instance of local instanceOf = instanceOfState.mainsnak.datavalue.value.id if acceptable[instanceOf] then --housekeeping tFroms[basionymId] = 1 iFroms = iFroms + 1 fromTitleCount = fromTitleCount + 1 --append basionym & track parentArgs['from'..fromTitleCount] = basionymId categories[15] = break end end end end end end
--Append original combination to arg list, if not already provided if currentItem then local currentOCState = currentItem:getBestStatements('P1403')[1] --original combination if currentOCState then local orcoId = currentOCState.mainsnak.datavalue.value.id if orcoId and resolveEntity._id(orcoId) and tFroms[orcoId] == nil then --check that orco is a strict instance of taxon local orcoItem = mw.wikibase.getEntity(orcoId) if orcoItem then local acceptable = { ['Q16521'] = 'taxon', --strict ['Q310890'] = 'monotypic taxon', --strict ['Q2568288'] = 'ichnotaxon', --strict ['Q23038290'] = 'fossil taxon', --strict ['Q47487597'] = 'monotypic fossil taxon', --strict } for _, instanceOfState in pairs ( orcoItem:getBestStatements('P31') ) do --instance of local instanceOf = instanceOfState.mainsnak.datavalue.value.id if acceptable[instanceOf] then --housekeeping tFroms[orcoId] = 1 iFroms = iFroms + 1 fromTitleCount = fromTitleCount + 1 --append orco & track parentArgs['from'..fromTitleCount] = orcoId categories[16] = break end end end end end end
--Append monotypic genus/species to arg list of monotypic species/genus, if not already provided if currentItem then for _, instanceOfState in pairs ( currentItem:getBestStatements('P31') ) do --instance of local taxonRank = nil local parentItem = nil local parentTaxon = nil local parentTaxonRank = nil local parentMonoGenus = nil --holy grail/tbd local instanceOf = instanceOfState.mainsnak.datavalue.value.id if instanceOf and (instanceOf == 'Q310890' or instanceOf == 'Q47487597') then --monotypic/fossil taxon local taxonRankState = currentItem:getBestStatements('P105')[1] --taxon rank if taxonRankState then taxonRank = taxonRankState.mainsnak.datavalue.value.id end
if taxonRank and taxonRank == 'Q7432' then --species --is monotypic species; add genus local parentTaxonState = currentItem:getBestStatements('P171')[1] --parent taxon if parentTaxonState then parentTaxon = parentTaxonState.mainsnak.datavalue.value.id end --confirm parent taxon rank == genus & monotypic if parentTaxon and resolveEntity._id(parentTaxon) then parentItem = mw.wikibase.getEntity(parentTaxon) if parentItem then local parentTaxonRankState = parentItem:getBestStatements('P105')[1] --taxon rank if parentTaxonRankState then parentTaxonRank = parentTaxonRankState.mainsnak.datavalue.value.id end if parentTaxonRank and parentTaxonRank == 'Q34740' then --parent == genus for _, parentInstanceOfState in pairs ( parentItem:getBestStatements('P31') ) do --instance of local parentInstanceOf = parentInstanceOfState.mainsnak.datavalue.value.id if parentInstanceOf and (parentInstanceOf == 'Q310890' or parentInstanceOf == 'Q47487597') then --monotypic/fossil taxon parentMonoGenus = parentTaxon --confirmed break end end if parentMonoGenus and tFroms[parentMonoGenus] == nil then --housekeeping tFroms[parentMonoGenus] = 1 iFroms = iFroms + 1 fromTitleCount = fromTitleCount + 1 --append monotypic genus & track parentArgs['from'..fromTitleCount] = parentMonoGenus categories[17] = break end end end end if parentMonoGenus == nil or tFroms[parentMonoGenus] == nil then categories[18] = break end elseif taxonRank and taxonRank == 'Q34740' then --genus --is monotypic genus; add species --... end
end end end --if currentItem
--Setup navbox local navboxParams = { name = 'Taxonbar', bodyclass = 'hlist', listclass = , groupstyle = 'text-align: left;', }
for f = 1, fromTitleCount, 1
do
local elements, title = {}, nil
--cleanup parameters
if parentArgs['from'..f] == then parentArgs['from'..f] = nil end
if parentArgs['title'..f] == then parentArgs['title'..f] = nil end
--remap aliases
for _, a in pairs( conf.aliases ) do
local alias, name = mw.ustring.lower(a[1]), mw.ustring.lower(a[2])
if parentArgs[alias..f] and parentArgs[name..f] == nil then
parentArgs[name..f] = parentArgs[alias..f]
parentArgs[alias..f] = nil
end
end
--Fetch Wikidata item
local from = resolveEntity._id(parentArgs['from'..f])
local item = mw.wikibase.getEntity(from)
local label = nil
if type(item) == 'table' then
local statements = item:getBestStatements('P225')[1] --taxon name
if statements then
local datavalue = statements.mainsnak.datavalue
if datavalue then
label = datavalue.value
end
end
label = label or item:getLabel()
else
if parentArgs['from'..f] then
categories[1] =
categories[4] =
errors = errors .. mw.text.tag('strong', {class='error'}, 'Error: "' ..
parentArgs['from'..f] .. '" is not a valid Wikidata entity ID.
')
end
end
if label and label ~= then
title = mw.title.new(label)
end
if title == nil and parentArgs['title'..f] then
title = mw.title.new(parentArgs['title'..f])
end
if title == nil and f == 1 then
title = currentTitle
end
if title then if isNilOrEmpty( parentArgs['wikidata'..f] ) and (title.namespace == 0) then if parentArgs['from'..f] then parentArgs['wikidata'..f] = parentArgs['from'..f] elseif item then parentArgs['wikidata'..f] = item.id end end if title.namespace == 0 or stringArgs then --only in mainspace or if manual overrides exist local sourceCount = 0 for _, params in pairs( conf.databases ) do params[1] = mw.ustring.lower(params[1]) local propId = params[3] --Wikidata fallback if requested if (item and item.claims) and (type(propId) == 'string' or (type(propId) == 'number' and propId > 0)) then local wikidataId = getIdFromWikidata( item, 'P' .. propId ) local v = parentArgs[params[1]..f] if wikidataId then if isNilOrEmpty(v) then parentArgs[params[1]..f] = wikidataId else if v and v ~= 'no' and v ~= wikidataId then categories[9] = elseif v and v == wikidataId then categories[10] = end end end end local val = parentArgs[params[1]..f] if val and val ~= and mw.ustring.lower(val) ~= 'no' then if type(propId) == 'number' then if propId < 0 then propId = -propId end --allow link if propId > 0 then --link table.insert( elements, createRow( params[1], params[2]..':', val, getLink( propId, val ).text, true ) ) else --propId == 0; no link table.insert( elements, createRow( params[1], params[2]..':', val, val, true ) ) end else table.insert( elements, createRow( params[1], params[2]..':', val, getLink( propId, val ).text, true ) ) end if params[1] ~= 'wikidata' and params[1] ~= 'wikispecies' then sourceCount = sourceCount + 1 end end end
if sourceCount >= 40 then categories[21] = elseif sourceCount >= 35 then categories[20] = --endashes elseif sourceCount >= 30 then categories[14] = elseif sourceCount >= 25 then categories[13] = elseif sourceCount >= 20 then categories[12] = end
--Generate navbox title if sourceCount > 0 then rowCount = rowCount + 1 if firstRow == 0 then firstRow = f end --set title from wikidata if it doesn't exist if isNilOrEmpty( parentArgs['title'..f] ) then parentArgs['noTitle'..f] = true parentArgs['title'..f] = title.text end --if it exists now, set row heading to title if not isNilOrEmpty( parentArgs['title'..f] ) then navboxParams['group'..f] = TaxonItalics.italicizeTaxonName(parentArgs['title'..f], false) else navboxParams['group'..f] = end navboxParams['list'..f] = table.concat( elements ) elseif currentEntityId then categories[7] = end
--Categorize if not isNilOrEmpty( parentArgs['from'..f] ) then --blank "missing from" if 'from' exists categories[1] = --blank "desynced" if 'from' matches current page if parentArgs['from'..f] == currentEntityId then categories[2] = end end --cannot be "desynced" if no 'from' params if categories[1] ~= then categories[2] = end end end end --for f = 1, fromTitleCount, 1
if rowCount > 0 then
local Navbox = require('Module:Navbox')
if rowCount > 1 then
--remove duplicates and move page title to top
local rowIDs = {}
for f = 1,fromTitleCount,1
do
if not isNilOrEmpty( parentArgs['title'..f] ) then
if rowIDs[parentArgs['wikidata'..f]] then --remove duplicate
navboxParams['group'..f] = nil
navboxParams['list'..f] = nil
else
rowIDs[parentArgs['wikidata'..f]] = true
if f > firstRow and (parentArgs['title'..f] == currentTitle.text or
parentArgs['wikidata'..f] == currentEntityId) then --move item linked to page to top
if navboxParams['group'..f] and
navboxParams['group'..f] ~= and
navboxParams['list'..f] and
navboxParams['list'..f] ~= then
local tempGroup, tempList = navboxParams['group'..f], navboxParams['list'..f]
navboxParams['group'..f], navboxParams['list'..f] = navboxParams['group'..firstRow], navboxParams['list'..firstRow]
navboxParams['group'..firstRow], navboxParams['list'..firstRow] = tempGroup, tempList
end
end
end
end
end
--adjust navbox for number of rows
navboxParams['title'] = 'Taxon identifiers'
if rowCount > 2 then
navboxParams['navbar'] = 'plain'
else
navboxParams['state'] = 'off'
navboxParams['navbar'] = 'off'
end
elseif parentArgs['noTitle'..firstRow] then
navboxParams['group'..firstRow] = 'Taxon identifiers'
else
navboxParams['group'..firstRow] = 'Taxon identifiers
' .. navboxParams['group'..firstRow]
end
--return navbox outString = Navbox._navbox(navboxParams) end --if rowCount > 0
--Add categories
if string.sub(currentTitle.subpageText,1,9) == 'testcases' then parentArgs['demo'] = true end
if not isNilOrEmpty( parentArgs['demo'] ) then
outString = outString .. mw.text.nowiki(table.concat(categories)) .. '
'
elseif currentTitle.namespace == 0 then
outString = outString .. table.concat(categories)
end
return outString .. errors end
return p
- Taxonbars without from parameter
- Taxonbars desynced from Wikidata
- Taxonbars using multiple manual Wikidata items
- Taxonbars with invalid from parameters
- Taxonbars using manual taxon IDs
- Taxonbar pages requiring a Wikidata item
- Taxonbar pages without Wikidata taxon IDs
- Taxonbars with duplicate from parameters
- Taxonbars with manual taxon IDs differing from Wikidata
- Taxonbars with manual taxon IDs identical to Wikidata
- Taxonbars on possible non-taxon pages
- Taxonbars with 20–24 taxon IDs
- Taxonbars with 25–29 taxon IDs
- Taxonbars with 30–34 taxon IDs
- Taxonbars with automatically added basionyms
- Taxonbars with automatically added original combinations
- Taxonbars with automatically added monotypic genera
- Taxonbars of monotypic species missing genera
- Taxonbars with unknown parameters
- Taxonbars with 35–39 taxon IDs
- Taxonbars with 40+ taxon IDs