require('strict')  
local conf = require( 'Module:Taxonbar/conf' ) --configuration module
local TaxonItalics = require( 'Module:TaxonItalics' ) --use a function to conditionally italicize taxon names  
--==========================================================================
-- 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
--[[ this code picks up deprecated values on wikidata; better to use getBestStatements
for _, statement in pairs( item.claims[property] ) do
if statement.mainsnak.datavalue then
id = statement.mainsnak.datavalue.value
break
end
end
local statements = item:getBestStatements(property)[1]
if statements and
statements.mainsnak and
statements.mainsnak.datavalue and
statements.mainsnak.datavalue.value
then
id = statements.mainsnak.datavalue.value
end  
return id
end  
local function getLink( property, db, 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
if db == 'bow' then -- for birds of world which uses eBird identifier
link = 'https://birdsoftheworld.org/bow/species/$1'
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
local valurl = mw.uri.encode( val, 'PATH' )
valurl = string.gsub (valurl, '%%2F', '/') --escape '/' (e.g. issue with P5354); see wikidata T128078 and https://gerrit.wikimedia.org/r/c/mediawiki/extensions/Wikibase/+/664820/3/lib/includes/PropertyInfoSnakUrlExpander.php  
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 binomials, e.g. "Elaeagnus x ebbingei"
if property == 4301 then valurl = mw.ustring.gsub(valurl, '%%20', '+') 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]?)&#58;//', '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 = '<span>'..val..'</span>'
end
return returnVal
end  
local function createRow( id, label, rawValue, link, withUid )
if link then
local outStr = '*<span>'..label..' <span'
if withUid then outStr = outStr..'' end
return outStr..'>'..link..'</span></span>\n'
else
return '* '..mw.text.tag('span', {}, '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
local resolveEntity = require( 'Module:ResolveEntityId' )
local parentArgs = copyTable(: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 iFroms = 0 --integer size of tFroms, b/c Lua
local tFroms = {} --non-sequential table of unique froms
local tCats = {
'',
'',
'', -- [3] placeholder for
'', -- [4] placeholder for
'', -- [5] placeholder for
'', -- [6] placeholder for
'', -- [7] placeholder for
'', -- [8] placeholder for
'', -- [9] placeholder for --renamed 'using' -> 'with'
'', --[10] placeholder for
'', --[11] placeholder for
'', --[12] placeholder for
'', --[13] placeholder for
'', --[14] placeholder for --renamed 'using' -> 'with'
'', --[15] placeholder for
'', --[16] placeholder for
'', --[17] placeholder for
'', --[18] placeholder for
'', --[19] placeholder for
'', --[20] placeholder for
'', --[21] placeholder for
'', --[22] placeholder for
'', --[23] placeholder for
'', --[24] placeholder for
'', --[25] placeholder for --renamed '40+' -> '40–44'
'', --[26] placeholder for --new
}
local acceptableInstanceOf_Strict = {
['Q16521'] = 'taxon', --strict
['Q310890'] = 'monotypic taxon', --strict
['Q98961713'] = 'extinct taxon', --strict
['Q2568288'] = 'ichnotaxon', --strict
['Q23038290'] = 'fossil taxon', --strict
['Q47487597'] = 'monotypic fossil taxon', --strict
}
local acceptableInstanceOf_All = {
['Q16521'] = 'taxon', --strict
['Q310890'] = 'monotypic taxon', --strict
['Q98961713'] = 'extinct 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
}  
--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
tCats[3] = ''
end
if currentItem then
tCats[4] = '' --unset if acceptable found
for _, instanceOfState in pairs ( currentItem:getBestStatements('P31') ) do --instance of
local instanceOf = instanceOfState.mainsnak.datavalue.value.id
if acceptableInstanceOf_All[instanceOf] then
tCats[4] = ''
break
end
end
end  
--Cleanup args
for k, v in pairs( :getParent.args ) do