Difference between revisions of "Module:Taxonbar"

From Eat Every Plant
Jump to navigation Jump to search
m (1 revision: Rhodiola rosea)
 
m (1 revision: Suaeda)
 
(11 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
require('Module:No globals')
 
require('Module:No globals')
  
local conf = require( "Module:Taxonbar/conf" ) -- configuration module
+
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 TaxonItalics = require('Module:TaxonItalics') --use a function from Module:TaxonItalics to italicize a taxon name
  
local function getIdsFromWikidata( item, property )
+
--[[==========================================================================]]
local ids = {}
+
--[[                            Local functions                              ]]
if not item.claims[property] then
+
--[[==========================================================================]]
return ids
+
 
 +
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
table.insert( ids, statement.mainsnak.datavalue.value )
+
id = statement.mainsnak.datavalue.value
 +
break
 
end
 
end
 
end
 
end
return ids
+
return id
 
end
 
end
  
 
local function getLink( property, val )
 
local function getLink( property, val )
local link, returnVal = "", {}
+
local link, returnVal = '', {}
 
 
 
returnVal.isError = false
 
returnVal.isError = false
Line 32: Line 53:
 
else returnVal.isError = true end
 
else returnVal.isError = true end
 
 
if dataType == "external-id" then
+
if dataType == 'external-id' then
local formatterURL = entityObject:getBestStatements('P1630')[1]
+
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 then
 
if formatterURL.mainsnak.datavalue and formatterURL.mainsnak.datavalue.value then --nil check for ABA
 
if formatterURL.mainsnak.datavalue and formatterURL.mainsnak.datavalue.value then --nil check for ABA
Line 39: Line 67:
 
end
 
end
 
end
 
end
elseif dataType == "url" then
+
elseif dataType == 'url' then
 
local subjectItem = entityObject:getBestStatements('P1629')[1]
 
local subjectItem = entityObject:getBestStatements('P1629')[1]
 
if subjectItem then
 
if subjectItem then
Line 45: Line 73:
 
if officialWebsite then link = officialWebsite.mainsnak.datavalue.value end
 
if officialWebsite then link = officialWebsite.mainsnak.datavalue.value end
 
end
 
end
elseif dataType == "string" then
+
elseif dataType == 'string' then
 
local formatterURL = entityObject:getBestStatements('P1630')[1]
 
local formatterURL = entityObject:getBestStatements('P1630')[1]
 
if formatterURL then
 
if formatterURL then
Line 64: Line 92:
 
 
 
local valurl = val
 
local valurl = val
if mw.ustring.find( link, 'antweb.org' ) then valurl = mw.ustring.gsub(valurl, " ", "%%20") end
+
if mw.ustring.find( link, 'antweb.org' ) then valurl = mw.ustring.gsub(valurl, ' ', '%%20') end
valurl = mw.ustring.gsub(valurl,"%%","%%%%")
+
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)
 
link = mw.ustring.gsub(link, '$1', valurl)
 
end
 
end
Line 72: Line 106:
 
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"),'%[%]')..']'
+
returnVal.text = '['..link..' '..mw.text.encode(mw.uri.decode(val, 'PATH'),'%[%]')..']'
elseif link == "" then
+
elseif link == '' then
 
returnVal.text = val
 
returnVal.text = val
 
else
 
else
Line 99: Line 133:
  
 
local p = {}
 
local p = {}
 +
 +
--[[==========================================================================]]
 +
--[[                                  Main                                  ]]
 +
--[[==========================================================================]]
  
 
function p.authorityControlTaxon( frame )
 
function p.authorityControlTaxon( frame )
local resolve = require( "Module:ResolveEntityId" )
+
local resolveEntity = require( 'Module:ResolveEntityId' )
 
local parentArgs = copyTable(frame:getParent().args)
 
local parentArgs = copyTable(frame:getParent().args)
 
local currentTitle = mw.title.getCurrentTitle()
 
local currentTitle = mw.title.getCurrentTitle()
Line 108: Line 146:
 
local stringArgs = false
 
local stringArgs = false
 
local fromTitleCount, firstRow, rowCount = 1, 0, 0
 
local fromTitleCount, firstRow, rowCount = 1, 0, 0
local outString, errors = "", ""
+
local outString, errors = '', ''
local tfroms = {} --non-sequential table of unique froms
+
local tFroms = {} --non-sequential table of unique froms
local ifroms = 0 --integer size of tfroms, b/c Lua
+
local iFroms = 0 --integer size of tFroms, b/c Lua
 
local categories = {
 
local categories = {
 
'[[Category:Taxonbars without from parameter]]',
 
'[[Category:Taxonbars without from parameter]]',
Line 123: Line 161:
 
'', --[10] placeholder for [[Category:Taxonbars with manual taxon IDs identical to Wikidata]]
 
'', --[10] placeholder for [[Category:Taxonbars with manual taxon IDs identical to Wikidata]]
 
'', --[11] placeholder for [[Category:Taxonbars on possible non-taxon pages]]
 
'', --[11] placeholder for [[Category:Taxonbars on possible non-taxon pages]]
'', --[12] placeholder for [[Category:Taxonbars with 20+ taxon IDs]]
+
'', --[12] placeholder for [[Category:Taxonbars with 20–24 taxon IDs]]
'', --[13] placeholder for [[Category:Taxonbars with 25+ taxon IDs]]
+
'', --[13] placeholder for [[Category:Taxonbars with 25–29 taxon IDs]]
'', --[14] placeholder for [[Category:Taxonbars with automatically added basionyms]]
+
'', --[14] placeholder for [[Category:Taxonbars with 30–34 taxon IDs]]
'', --[15] placeholder for [[Category:Taxonbars with automatically added monotypic genera]]
+
'', --[15] placeholder for [[Category:Taxonbars with automatically added basionyms]]
'', --[16] placeholder for [[Category:Taxonbars of monotypic species missing genera]]
+
'', --[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]]
 
}
 
}
 
 
Line 133: Line 176:
 
local currentItem = nil
 
local currentItem = nil
 
if currentTitle.namespace == 10 then --i.e. Module:Taxonbar/sandbox, Template:Taxonbar/doc, etc.
 
if currentTitle.namespace == 10 then --i.e. Module:Taxonbar/sandbox, Template:Taxonbar/doc, etc.
if resolve._entityid(frame, parentArgs['from']) then
+
if resolveEntity._id(parentArgs['from']) then
 
currentItem = mw.wikibase.getEntity(parentArgs['from'])
 
currentItem = mw.wikibase.getEntity(parentArgs['from'])
 
end
 
end
 
if currentItem == nil then
 
if currentItem == nil then
if resolve._entityid(frame, parentArgs['from1']) then
+
if resolveEntity._id(parentArgs['from1']) then
 
currentItem = mw.wikibase.getEntity(parentArgs['from1'])
 
currentItem = mw.wikibase.getEntity(parentArgs['from1'])
 
end
 
end
 
end
 
end
elseif resolve._entityid(frame, currentEntityId) then
+
elseif resolveEntity._id(currentEntityId) then
 
currentItem = mw.wikibase.getEntity(currentEntityId)
 
currentItem = mw.wikibase.getEntity(currentEntityId)
else --currentEntityId == nil
+
else --currentEntityId == nil/unresolvable
 
categories[6] = '[[Category:Taxonbar pages requiring a Wikidata item]]'
 
categories[6] = '[[Category:Taxonbar pages requiring a Wikidata item]]'
 
end
 
end
 
if currentItem then
 
if currentItem then
 
local acceptable = {
 
local acceptable = {
  ['Q16521'] = 'taxon',
+
  ['Q16521'] = 'taxon',                     --strict
  ['Q310890'] = 'monotypic taxon',
+
  ['Q310890'] = 'monotypic taxon',           --strict
  ['Q2568288'] = 'ichnotaxon',
+
  ['Q2568288'] = 'ichnotaxon',               --strict
  ['Q23038290'] = 'fossil taxon',
+
  ['Q23038290'] = 'fossil taxon',           --strict
  ['Q47487597'] = 'monotypic fossil taxon',
+
  ['Q47487597'] = 'monotypic fossil taxon', --strict
  ['Q42621'] = 'hybrid',
+
  ['Q42621'] = 'hybrid',                     --lax
  ['Q235536'] = 'incertae sedis',
+
  ['Q235536'] = 'incertae sedis',           --lax
  ['Q713623'] = 'clade',
+
  ['Q713623'] = 'clade',                     --lax
  ['Q848328'] = 'serotype',
+
  ['Q848328'] = 'serotype',                 --lax
  ['Q17487588'] = 'unavailable combination',
+
  ['Q857968'] = 'candidatus',                --lax
 +
  ['Q17487588'] = 'unavailable combination', --lax
 
}
 
}
 
categories[11] = '[[Category:Taxonbars on possible non-taxon pages]]' --unset if acceptable found
 
categories[11] = '[[Category:Taxonbars on possible non-taxon pages]]' --unset if acceptable found
Line 174: Line 218:
 
--make args case insensitive
 
--make args case insensitive
 
local lowerk = mw.ustring.lower(k)
 
local lowerk = mw.ustring.lower(k)
if not parentArgs[lowerk] or parentArgs[lowerk] == '' then
+
if isNilOrEmpty( parentArgs[lowerk] ) then
 
parentArgs[k] = nil
 
parentArgs[k] = nil
 
parentArgs[lowerk] = v
 
parentArgs[lowerk] = v
 
end
 
end
 
--remap abc to abc1
 
--remap abc to abc1
if not mw.ustring.find(lowerk,"%d$") then --if no number at end of param
+
if mw.ustring.find(lowerk,'%d$') == nil then --if no number at end of param
if not parentArgs[lowerk..'1'] or parentArgs[lowerk..'1'] == '' then
+
if isNilOrEmpty( parentArgs[lowerk..'1'] ) then
 
parentArgs[lowerk] = nil
 
parentArgs[lowerk] = nil
 
lowerk = lowerk..'1'
 
lowerk = lowerk..'1'
Line 187: Line 231:
 
end
 
end
 
if v and v ~= '' then
 
if v and v ~= '' then
--remap "for" to "title"
+
--remap 'for' to 'title'
if mw.ustring.sub(lowerk,1,3) == "for" then
+
if mw.ustring.sub(lowerk,1,3) == 'for' then
local forTitle = mw.ustring.gsub(lowerk,"^for","title",1)
+
local forTitle = mw.ustring.gsub(lowerk,'^for','title',1)
if parentArgs[forTitle] == '' or not parentArgs[forTitle] then
+
if isNilOrEmpty( parentArgs[forTitle] ) then
 
parentArgs[lowerk] = nil
 
parentArgs[lowerk] = nil
 
lowerk = forTitle
 
lowerk = forTitle
Line 197: Line 241:
 
end
 
end
 
--find highest from or title param
 
--find highest from or title param
if mw.ustring.sub(lowerk,1,4) == "from" then
+
if mw.ustring.sub(lowerk,1,4) == 'from' then
 
local fromNumber = tonumber(mw.ustring.sub(lowerk,5,-1))
 
local fromNumber = tonumber(mw.ustring.sub(lowerk,5,-1))
 
if fromNumber and fromNumber >= fromTitleCount then fromTitleCount = fromNumber end
 
if fromNumber and fromNumber >= fromTitleCount then fromTitleCount = fromNumber end
 
--look for duplicate froms while we're here
 
--look for duplicate froms while we're here
if mw.ustring.find(v, "^Q%d") then
+
if mw.ustring.find(v, '^Q%d') then
if tfroms[v] then
+
if tFroms[v] then
 
categories[8] = '[[Category:Taxonbars with duplicate from parameters]]'
 
categories[8] = '[[Category:Taxonbars with duplicate from parameters]]'
tfroms[v] = tfroms[v] + 1
+
tFroms[v] = tFroms[v] + 1
 
else
 
else
tfroms[v] = 1
+
tFroms[v] = 1
ifroms = ifroms + 1
+
iFroms = iFroms + 1
 
end
 
end
if ifroms > 1 then
+
if iFroms == 2 then
 
categories[3] = '[[Category:Taxonbars using multiple manual Wikidata items]]'
 
categories[3] = '[[Category:Taxonbars using multiple manual Wikidata items]]'
 
end
 
end
 
end
 
end
elseif mw.ustring.sub(lowerk,1,5) == "title" then
+
elseif mw.ustring.sub(lowerk,1,5) == 'title' then
 
local titleNumber = tonumber(mw.ustring.sub(lowerk,4,-1))
 
local titleNumber = tonumber(mw.ustring.sub(lowerk,4,-1))
 
if titleNumber and titleNumber >= fromTitleCount then fromTitleCount = titleNumber end
 
if titleNumber and titleNumber >= fromTitleCount then fromTitleCount = titleNumber end
Line 221: Line 265:
 
end
 
end
 
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] = '[[Category:Taxonbars with unknown parameters|' .. k ..']]'
 +
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( '{{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
 
end
Line 229: Line 320:
 
if currentBasState then
 
if currentBasState then
 
local basionymId = currentBasState.mainsnak.datavalue.value.id
 
local basionymId = currentBasState.mainsnak.datavalue.value.id
if basionymId and resolve._entityid(frame, basionymId) and tfroms[basionymId] == nil then
+
if basionymId and resolveEntity._id(basionymId) and tFroms[basionymId] == nil then
 
--check that basionym is a strict instance of taxon
 
--check that basionym is a strict instance of taxon
 
local basionymItem = mw.wikibase.getEntity(basionymId)
 
local basionymItem = mw.wikibase.getEntity(basionymId)
 
if basionymItem then
 
if basionymItem then
 
local acceptable = {
 
local acceptable = {
  ['Q16521'] = 'taxon',
+
  ['Q16521'] = 'taxon',                     --strict
  ['Q310890'] = 'monotypic taxon',
+
  ['Q310890'] = 'monotypic taxon',         --strict
  ['Q2568288'] = 'ichnotaxon',
+
  ['Q2568288'] = 'ichnotaxon',             --strict
  ['Q23038290'] = 'fossil taxon',
+
  ['Q23038290'] = 'fossil taxon',           --strict
  ['Q47487597'] = 'monotypic fossil taxon',
+
  ['Q47487597'] = 'monotypic fossil taxon', --strict
 
}
 
}
 
for _, instanceOfState in pairs ( basionymItem:getBestStatements('P31') ) do --instance of
 
for _, instanceOfState in pairs ( basionymItem:getBestStatements('P31') ) do --instance of
Line 244: Line 335:
 
if acceptable[instanceOf] then
 
if acceptable[instanceOf] then
 
--housekeeping
 
--housekeeping
tfroms[basionymId] = 1
+
tFroms[basionymId] = 1
ifroms = ifroms + 1
+
iFroms = iFroms + 1
 
fromTitleCount = fromTitleCount + 1
 
fromTitleCount = fromTitleCount + 1
 
--append basionym & track
 
--append basionym & track
 
parentArgs['from'..fromTitleCount] = basionymId
 
parentArgs['from'..fromTitleCount] = basionymId
categories[14] = '[[Category:Taxonbars with automatically added basionyms]]'
+
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
 
break
 
end end end end end end
 
end end end end end end
Line 270: Line 390:
 
local parentTaxonState = currentItem:getBestStatements('P171')[1] --parent taxon
 
local parentTaxonState = currentItem:getBestStatements('P171')[1] --parent taxon
 
if parentTaxonState then parentTaxon = parentTaxonState.mainsnak.datavalue.value.id end
 
if parentTaxonState then parentTaxon = parentTaxonState.mainsnak.datavalue.value.id end
--confirm parent taxon rank == genus & monotypic (too careful/expensive? remove/mod this first if hitting any request limits)
+
--confirm parent taxon rank == genus & monotypic
if parentTaxon and resolve._entityid(frame, parentTaxon) then
+
if parentTaxon and resolveEntity._id(parentTaxon) then
 
parentItem = mw.wikibase.getEntity(parentTaxon)
 
parentItem = mw.wikibase.getEntity(parentTaxon)
 
if parentItem then
 
if parentItem then
Line 285: Line 405:
 
end
 
end
 
end
 
end
if parentMonoGenus and tfroms[parentMonoGenus] == nil then
+
if parentMonoGenus and tFroms[parentMonoGenus] == nil then
 
--housekeeping
 
--housekeeping
tfroms[parentMonoGenus] = 1
+
tFroms[parentMonoGenus] = 1
ifroms = ifroms + 1
+
iFroms = iFroms + 1
 
fromTitleCount = fromTitleCount + 1
 
fromTitleCount = fromTitleCount + 1
 
--append monotypic genus & track
 
--append monotypic genus & track
 
parentArgs['from'..fromTitleCount] = parentMonoGenus
 
parentArgs['from'..fromTitleCount] = parentMonoGenus
categories[15] = '[[Category:Taxonbars with automatically added monotypic genera]]'
+
categories[17] = '[[Category:Taxonbars with automatically added monotypic genera]]'
 
break
 
break
 
end
 
end
Line 298: Line 418:
 
end
 
end
 
end
 
end
if parentMonoGenus == nil or tfroms[parentMonoGenus] == nil then
+
if parentMonoGenus == nil or tFroms[parentMonoGenus] == nil then
categories[16] = '[[Category:Taxonbars of monotypic species missing genera]]'
+
categories[18] = '[[Category:Taxonbars of monotypic species missing genera]]'
 
break
 
break
 
end
 
end
Line 309: Line 429:
 
end
 
end
 
end
 
end
end
+
end --if currentItem
 
 
 
--Setup navbox
 
--Setup navbox
Line 319: Line 439:
 
}
 
}
 
 
for f = 1,fromTitleCount,1
+
for f = 1, fromTitleCount, 1
 
do
 
do
 
local elements, title = {}, nil
 
local elements, title = {}, nil
Line 328: Line 448:
 
for _, a in pairs( conf.aliases ) do
 
for _, a in pairs( conf.aliases ) do
 
local alias, name = mw.ustring.lower(a[1]), mw.ustring.lower(a[2])
 
local alias, name = mw.ustring.lower(a[1]), mw.ustring.lower(a[2])
if parentArgs[alias..f] and not parentArgs[name..f] then
+
if parentArgs[alias..f] and parentArgs[name..f] == nil then
 
parentArgs[name..f] = parentArgs[alias..f]
 
parentArgs[name..f] = parentArgs[alias..f]
 
parentArgs[alias..f] = nil
 
parentArgs[alias..f] = nil
Line 334: Line 454:
 
end
 
end
 
--Fetch Wikidata item
 
--Fetch Wikidata item
local from = resolve._entityid(frame, parentArgs['from'..f])
+
local from = resolveEntity._id(parentArgs['from'..f])
 
local item = mw.wikibase.getEntity(from)
 
local item = mw.wikibase.getEntity(from)
 
local label = nil
 
local label = nil
Line 357: Line 477:
 
title = mw.title.new(label)
 
title = mw.title.new(label)
 
end
 
end
if not title and parentArgs['title'..f] then
+
if title == nil and parentArgs['title'..f] then
 
title = mw.title.new(parentArgs['title'..f])
 
title = mw.title.new(parentArgs['title'..f])
 
end
 
end
if not title and f == 1 then
+
if title == nil and f == 1 then
 
title = currentTitle
 
title = currentTitle
 
end
 
end
 
 
 
if title then
 
if title then
if (not parentArgs['wikidata'..f] or parentArgs['wikidata'..f] == '') and  
+
if isNilOrEmpty( parentArgs['wikidata'..f] ) and  
 
  (title.namespace == 0) then
 
  (title.namespace == 0) then
 
if parentArgs['from'..f] then
 
if parentArgs['from'..f] then
Line 373: Line 493:
 
end
 
end
 
end
 
end
if title.namespace == 0 or stringArgs then --Only in the main namespace or if there are manual overrides
+
if title.namespace == 0 or stringArgs then --only in mainspace or if manual overrides exist
 
local sourceCount = 0
 
local sourceCount = 0
 
for _, params in pairs( conf.databases ) do
 
for _, params in pairs( conf.databases ) do
Line 379: Line 499:
 
local propId = params[3]
 
local propId = params[3]
 
--Wikidata fallback if requested
 
--Wikidata fallback if requested
if (item ~= nil and item.claims ~= nil) and
+
if (item and item.claims) and
 
  (type(propId) == 'string' or (type(propId) == 'number' and propId > 0)) then
 
  (type(propId) == 'string' or (type(propId) == 'number' and propId > 0)) then
local wikidataIds = getIdsFromWikidata( item, 'P' .. propId )
+
local wikidataId = getIdFromWikidata( item, 'P' .. propId )
 
local v = parentArgs[params[1]..f]
 
local v = parentArgs[params[1]..f]
if wikidataIds[1] then
+
if wikidataId then
if (not v or v == '') then
+
if isNilOrEmpty(v) then
parentArgs[params[1]..f] = wikidataIds[1]
+
parentArgs[params[1]..f] = wikidataId
 
else
 
else
if v and v ~= 'no' and v ~= wikidataIds[1] then
+
if v and v ~= 'no' and v ~= wikidataId then
 
categories[9] = '[[Category:Taxonbars with manual taxon IDs differing from Wikidata]]'
 
categories[9] = '[[Category:Taxonbars with manual taxon IDs differing from Wikidata]]'
elseif v and v == wikidataIds[1] then
+
elseif v and v == wikidataId then
 
categories[10] = '[[Category:Taxonbars with manual taxon IDs identical to Wikidata]]'
 
categories[10] = '[[Category:Taxonbars with manual taxon IDs identical to Wikidata]]'
 
end
 
end
Line 407: Line 527:
 
table.insert( elements, createRow( params[1], params[2]..':', val, getLink( propId, val ).text, true ) )
 
table.insert( elements, createRow( params[1], params[2]..':', val, getLink( propId, val ).text, true ) )
 
end
 
end
if params[1] ~= 'wikidata' then
+
if params[1] ~= 'wikidata' and params[1] ~= 'wikispecies' then
 
sourceCount = sourceCount + 1
 
sourceCount = sourceCount + 1
 
end
 
end
Line 413: Line 533:
 
end
 
end
 
 
if sourceCount >= 20 then categories[12] = '[[Category:Taxonbars with 20+ taxon IDs]]' end
+
if     sourceCount >= 40 then categories[21] = '[[Category:Taxonbars with 40+ taxon IDs]]'
if sourceCount >= 25 then categories[13] = '[[Category:Taxonbars with 25+ taxon IDs]]' end
+
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
 
--Generate navbox title
Line 421: Line 545:
 
if firstRow == 0 then firstRow = f end
 
if firstRow == 0 then firstRow = f end
 
--set title from wikidata if it doesn't exist
 
--set title from wikidata if it doesn't exist
if parentArgs['title'..f] == '' or not parentArgs['title'..f] then
+
if isNilOrEmpty( parentArgs['title'..f] ) then
 
parentArgs['noTitle'..f] = true
 
parentArgs['noTitle'..f] = true
 
parentArgs['title'..f] = title.text
 
parentArgs['title'..f] = title.text
 
end
 
end
 
--if it exists now, set row heading to title
 
--if it exists now, set row heading to title
if parentArgs['title'..f] and parentArgs['title'..f] ~= '' then
+
if not isNilOrEmpty( parentArgs['title'..f] ) then
 
navboxParams['group'..f] = TaxonItalics.italicizeTaxonName(parentArgs['title'..f], false)
 
navboxParams['group'..f] = TaxonItalics.italicizeTaxonName(parentArgs['title'..f], false)
 
else
 
else
navboxParams['group'..f] = ""
+
navboxParams['group'..f] = ''
 
end
 
end
 
navboxParams['list'..f] = table.concat( elements )
 
navboxParams['list'..f] = table.concat( elements )
Line 437: Line 561:
 
 
 
--Categorize
 
--Categorize
if parentArgs['from'..f] and parentArgs['from'..f] ~= '' then
+
if not isNilOrEmpty( parentArgs['from'..f] ) then
 
--blank "missing from" if 'from' exists
 
--blank "missing from" if 'from' exists
 
categories[1] = ''
 
categories[1] = ''
Line 447: Line 571:
 
end
 
end
 
end
 
end
end
+
end --for f = 1, fromTitleCount, 1
 
+
 
if rowCount > 0 then
 
if rowCount > 0 then
 
local Navbox = require('Module:Navbox')
 
local Navbox = require('Module:Navbox')
Line 456: Line 580:
 
for f = 1,fromTitleCount,1
 
for f = 1,fromTitleCount,1
 
do
 
do
if parentArgs['title'..f] and parentArgs['title'..f] ~= '' then
+
if not isNilOrEmpty( parentArgs['title'..f] ) then
 
if rowIDs[parentArgs['wikidata'..f]] then --remove duplicate
 
if rowIDs[parentArgs['wikidata'..f]] then --remove duplicate
 
navboxParams['group'..f] = nil
 
navboxParams['group'..f] = nil
Line 477: Line 601:
 
end
 
end
 
--adjust navbox for number of rows
 
--adjust navbox for number of rows
navboxParams['title'] = "[[Help:Taxon identifiers|Taxon identifiers]]"
+
navboxParams['title'] = '[[Help:Taxon identifiers|Taxon identifiers]]'
 
if rowCount > 2 then
 
if rowCount > 2 then
 
navboxParams['navbar'] = 'plain'
 
navboxParams['navbar'] = 'plain'
Line 492: Line 616:
 
--return navbox
 
--return navbox
 
outString = Navbox._navbox(navboxParams)
 
outString = Navbox._navbox(navboxParams)
end
+
end --if rowCount > 0
 
 
--add categories
+
--Add categories
 
if string.sub(currentTitle.subpageText,1,9) == 'testcases' then parentArgs['demo'] = true end
 
if string.sub(currentTitle.subpageText,1,9) == 'testcases' then parentArgs['demo'] = true end
if parentArgs['demo'] and parentArgs['demo'] ~= '' then
+
if not isNilOrEmpty( parentArgs['demo'] ) then
 
outString = outString .. mw.text.nowiki(table.concat(categories)) .. '<br />'
 
outString = outString .. mw.text.nowiki(table.concat(categories)) .. '<br />'
 
elseif currentTitle.namespace == 0 then
 
elseif currentTitle.namespace == 0 then

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.
'..

'This message is only shown in preview.

'

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