Module:Authority control: Difference between revisions

Safer nicotine wiki Tobacco Harm Reduction
Jump to navigation Jump to search
m (1 revision imported)
m (1 revision imported: templates)
 
(5 intermediate revisions by 3 users not shown)
Line 1: Line 1:
--[[ 
require('strict')
  __  __          _      _          _        _  _                _ _                          _            _
local p = {}
|  \/  | ___  __| |_  _| | ___ _  / \  _  _| |_| |__  ___  _ __(_) |_ _  _    ___ ___  _ __ | |_ _ __ ___ | |
local configfile = 'Module:Authority control/config' -- default configuation module
| |\/| |/ _ \ / _` | | | | |/ _ (_) / _ \| | | | __| '_ \ / _ \| '__| | __| | | |  / __/ _ \| '_ \| __| '__/ _ \| |
local arg = mw.getCurrentFrame().args.config
| |  | | (_) | (_| | |_| | |  __/_ / ___ \ |_| | |_| | | | (_) | |  | | |_| |_| | | (_| (_) | | | | |_| | | (_) | |
if arg and arg~='' then
|_|  |_|\___/ \__,_|\__,_|_|\___(_)_/  \_\__,_|\__|_| |_|\___/|_|  |_|\__|\__, |  \___\___/|_| |_|\__|_|  \___/|_|
configfile = 'Module:Authority control/config/' .. arg
                                                                            |___/                                   
end
This module is intended to be the engine behind "Template:Authority control".
local config
if mw.title.new(configfile).exists then
config = mw.loadData(configfile)
else
return error('Invalid configuration file',0)
end
local title = mw.title.getCurrentTitle()
local namespace = title.namespace
local testcases = title.subpageText == config.i18n.testcases


Please do not modify this code without applying the changes first at "Module:Authority control/sandbox" and testing
local function needsAttention(sortkey)
at "Module:Authority control/testcases".
return '[[' .. config.i18n.category .. ':' .. config.i18n.attentioncat .. '|' .. sortkey .. title.text .. ']]'
end


Authors and maintainers:
local function addCat(cat,sortkey)
* User:Jarekt - original version
if cat and cat ~= '' and (namespace == 0 or namespace == 14 or testcases) then
 
local redlinkcat = ''
]]
if testcases == false and mw.title.new(cat, 14).exists == false then
 
redlinkcat = needsAttention('N')
local properties = require('Module:Authority control/conf')
end
local core      = require('Module:Core')
if sortkey then
 
cat = '[[' .. config.i18n.category .. ':'..cat..'|' .. sortkey .. title.text .. ']]'
-- ==================================================
else
-- === Internal functions ===========================
cat = '[[' .. config.i18n.category .. ':'..cat..']]'
-- ==================================================
 
local function getSitelink(item, lang)
    -- get item's siteling in specific language
local langList = mw.language.getFallbacksFor(lang)
table.insert(langList, 1, lang)
for _, language in ipairs(langList) do
local sitelink = mw.wikibase.sitelink( item, language .. 'wiki' )
if sitelink then
return 'w:'.. language ..':'.. sitelink
end
end
cat = cat .. redlinkcat
return cat
else
return ''
end
end
return nil
end
end


-- ==================================================
local function getCatForId(id,faulty)
local function getIdentifierNameLink( lang, item1, item2, label )
local cat = string.format(
-- Identifier names, like VIAF, LCCN, ISNI, need to be linked to the articles about them if possible
config.i18n.cat,
-- Alternativly they can be linked to the articles for institutions that issue them
(faulty and config.i18n.faulty..' ' or '') .. id
local id_name_URL = nil
)
-- 1) try wikipedia sitelink for the identifier in users language and in English
return addCat(cat)
if item1 and item1 ~='' then
end
id_name_URL = getSitelink(item1, lang)
 
local function getIdsFromWikidata(qid,property)
local function getquals(statement,qualid)
if statement.qualifiers and statement.qualifiers['P'..qualid] then
return mw.wikibase.renderSnak(statement.qualifiers['P'..qualid][1])
else
return false
end
end
end
-- 2) try wikipedia sitelink for the issuedBy property in users language and in English
local ids = {}
if id_name_URL==nil and item2 and item2 ~='' then -- if no link than
if qid then
id_name_URL = getSitelink(item2, lang)
for _, statement in ipairs(mw.wikibase.getBestStatements(qid,property)) do
end
if statement.mainsnak.datavalue then
-- 3) if still no links than link to wikidata
local val = statement.mainsnak.datavalue.value
if id_name_URL then
if val then
return string.format("[[%s|%s]]", id_name_URL, label) -- link to wikipedia
local namedas = getquals(statement,1810) or getquals(statement,742) or ''
else   
table.insert(ids,{id=val,name=namedas})
return string.format("[[d:%s|%s]]", item1, label) -- link to wikidata
end
end
end
end
end
return ids
end
end


-- ==================================================
local _makelink = function(conf,val,nextid,qid) --validate values and create a link
-- Create link to a single identifier
local function tooltip(text,label)
-- INPUTS:
if label and label~='' then
--  * val - value of the identifier
return mw.getCurrentFrame():expandTemplate{title = "Tooltip", args = {text,label}}
--  * URL_format - string used to create URL
else
--  * params - additional parameters related to this type of identifiers. Single item from "conf"
return text
--  * color - color of the link
end
local function getIdentifierValLink(val, URL_format, params, color)
if not val or val=='' then
return ''
end
end
-- check if identifier is in the right format
local link
local mismatchStr = ''
if nextid==1 then
local val_ = val:gsub( ' ', '' ) -- remove spaces
if conf.prefix then
if (params.regexp and not val:match( params.regexp )) then
link = '*' .. conf.prefix .. '\n**'
mismatchStr  = string.format("<span style=\"color:red\">[does not match %s pattern]</span>", params.regexp)
else
elseif (params.verify) then -- check if special "Verify" function is present
link = '*'
mismatchStr = params.verify(val_) -- add error message if any
end
else
link = '\n**'
end
end
-- identifier_value_URL
local valid_value = false
local val_URL = URL_format:gsub('$1', val_)-- URL part of the link for the identifier value
if conf.customlink then -- use function to validate and generate link
if color~="blue" then
local label = nextid>1 and nextid
val = string.format('<span style=\"color:%s\">%s</span>', color, val)
local newlink= require(config.auxiliary)[conf.customlink](val.id,label)
end
if newlink then
return string.format("<span class=\"plainlinks\">[%s %s]</span>%s", val_URL, val, mismatchStr) -- link to the identifier's external website
link = link .. newlink
end
valid_value = true
 
end
-- ==================================================
else
-- Convert between 2 formats of LCCN: "n/79/63767" -> "n79063767"
if conf.pattern then -- use pattern to determine validity if defined
-- "n/79/63767" format was used as input by {{Authority Control}} templates
valid_value = string.match(val.id,'^'..conf.pattern..'$')
-- "n79063767" format is used by wikidata
elseif conf.patterns then
local function fixLCCN(id)
for _,pattern in ipairs(conf.patterns) do
  if id then
valid_value = val.id:match('^'..pattern..'$')
local a, b, c = string.match(id, "([%a%d]*)/([%a%d]*)/([%a%d]*)")
if valid_value then break end
if c then
end
local pad = 6 - string.len(c)
elseif conf.valid then -- otherwise use function to determine validity
if pad > 0 then
valid_value = require(config.auxiliary)[conf.valid](val.id)
c = string.rep("0", pad)..c
else -- no validation possible
valid_value = val.id
end
if valid_value then
local newlink
local label = conf.label
if not label or nextid>1 then
label = tostring(nextid)
end
if conf.link then
valid_value = valid_value:gsub('%%', '%%%%')
newlink = '[' .. mw.ustring.gsub(conf.link,'%$1',valid_value) .. ' ' .. label .. ']'
else
newlink = valid_value
end
end
id = a..b..c
link = link .. '<span class="uid">'..tooltip(newlink,val.name)..'</span>'
end
end
end
end
return id
if valid_value then
end -- fixLCCN
link = link .. getCatForId(conf.category or conf[1])
 
-- ==================================================
-- Verify last "check" digit is correct. ISNI and several other
-- identifiers use last digit as a verification digit
local function verifyLastDigit( id )
    local total = 0
    for i = 1, #id-1 do
        local digit = id:byte( i ) - 48 --Get integer value
        total = (total + digit) * 2
    end
    --local remainder = total % 11
    local lastDigit = tostring((12 - total % 11) % 11)
    if lastDigit == '10' then
        lastDigit = "X"
    end
    if (lastDigit == string.sub( id, -1)) then
return ''
else
else
return "<span style=\"color:red\">[last digit should be " .. lastDigit .. "]</span>"
--local preview = require("Module:If preview")
local wdlink = qid and '[[:wikidata:' .. qid .. '#P' .. conf.property .. ']]' or ''
local tooltip = string.format(
config.i18n.idnotvalid,
conf[1],
val.id
)
link = link .. '[[File:' .. config.i18n.warningicon .. '|20px|frameless|link=' .. wdlink .. '|' .. tooltip .. '.]]'
if conf.errorcat then
link = link .. addCat(conf.errorcat)
else
link = link .. getCatForId(conf.category or conf[1],true)
end
link = link .. addCat(config.i18n.allfaultycat,conf[1])-- .. preview._warning({'The '..conf[1]..' id '..val..' is not valid.'})
end
end
return link
end
end


-- ==================================================
--[[==========================================================================]]
-- === Settings =====================================
--[[                                   Main                                  ]]
-- ==================================================
--[[==========================================================================]]
-- In order to add a new identifier associated with Wikidata property do the following
function p.authorityControl(frame)
-- 1) go to [[Template:Authority control/IdentifierList]] and verify that the property number is on the list, if not than edit the page to add it
local function resolveQID(qid)
-- 2) copy code generated at [[Template:Authority control/IdentifierList]] to protected [[Module:Authority control/conf]]
if qid then
-- 3) add the property to the "conf" list below
qid = 'Q'..mw.ustring.gsub(qid, '^[Qq]', '')
 
if mw.wikibase.isValidEntityId(qid) and mw.wikibase.entityExists(qid) then
-- load 'Module:Authority control/conf' which holds hardwired data derived from Wikidata's properties of
local sitelink = mw.wikibase.getSitelink(qid)
-- properties
if sitelink then
 
return mw.wikibase.getEntityIdForTitle(sitelink) or mw.wikibase.getEntity(qid).id
--conf  holds list of identifiers to be displayed
end
local conf = {
return mw.wikibase.getEntity(qid).id
    -- people
end
{label='VIAF'        , property='P214' , lang=''  , regexp='^%d+$' },
end
{label='ISNI'        , property='P213' , lang=''  , regexp='^%d%d%d%d %d%d%d%d %d%d%d%d %d%d%d[%dX]$', verify=verifyLastDigit },
{label='ORCID'      , property='P496' , lang=''  , regexp='^0000%-000[1-3]%-%d%d%d%d%-%d%d%d[%dX]$' },
{label='ULAN'        , property='P245' , lang=''  , regexp='^500%d%d%d%d%d%d$' }, -- 'Union List of Artist Names' by Getty Research Institute
{label='ResearcherID', property='P1053', lang=''  , regexp='^[A-Z]{1,3}-\d{4}-(19|20)\d\d$' },
{label='LCCN'        , property='P244' , lang='en', regexp='^[ns][broshj]?%d%d%d%d%d%d%d%d%d?%d?$' }, -- Library of Congress Authorities
{label='GND'        , property='P227' , lang='de', regexp='^[%dX%-]+$'},
{label='SELIBR'      , property='P906' , lang='se', regexp='^%d+$' }, -- National Library of Sweden
{label='SUDOC'      , property='P269' , lang='fr', regexp='^%d%d%d%d%d%d%d%d[%dxX]$' },   
{label='BNF'        , property='P268' , lang='fr', regexp='^%d+%w?$' }, -- Bibliothèque nationale de France
{label='BPN'        , property='P651' , lang='nl', regexp='^%d%d%d%d%d%d%d%d$' }, -- Biografisch Portaal number
{label='NAID'        , property='P1225', lang='en', regexp='^%d+$' }, -- NARA ID (redirect for US National Archives Identifier (P1225))
{label='Museofile'  , property='P539' , lang='fr', regexp='^M%d%d%d%d%-?%d?%d?$' }, --Ministry of Culture (France)
{label='NDL'        , property='P349' , lang='ja', regexp='^0?%d%d%d%d%d%d%d%d$' }, -- National Diet Library (of Japan)
{label='NLA'        , property='P409' , lang='en', regexp='^[1-9]%d*$' }, -- National Library of Australia
{label='BIBSYS'      , property='P1015', lang='no', regexp='^%d+$' }, -- Norwegian information system BIBSYS
{label='HDS'        , property='P902' , lang='de', regexp='^%d%d%d?%d?%d?%d?$' },  -- Historical Dictionary of Switzerland
{label='MusicBrainz' , property='P434' , lang='en', regexp='^[-%x]+$' },
{label='MGP'        , property='P549' , lang='en', regexp='^%d%d?%d?%d?%d?%d?$' },  -- Mathematics Genealogy Project
{label='NCL'        , property='P1048', lang='zh', regexp='^%d+$' },  --National Central Library (Taiwan)
{label='NKC'        , property='P691' , lang='cs', regexp='^%l%l%l?%l?%d%d%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?$' },  --National Library of the Czech Republic
{label='Léonore'    , property='P640' , lang='fr', regexp='^[LHC%/%d]+$' },
{label='SBN'        , property='P396' , lang='it'},  -- Istituto Centrale per il Catalogo Unico /  National Library Service (SBN) of Italy
{label='RSL'        , property='P947' , lang='ru', regexp='^%d%d%d%d%d%d%d%d%d$' },  --Russian State Library
{label='Botanist'    , property='P428' , lang='en' },
{label='US Congress' , property='P1157', lang='en', regexp='^%u00[01]%d%d%d' },
{label='BNE'         , property='P950' , lang='es', regexp='' }, --Biblioteca Nacional de España
{label='CALIS'      , property='P270' , lang='zh'}, --China Academic Library and Information
{label='CiNii'      , property='P271' , lang='jp', regexp='^DA%d%d%d%d%d%d%d[%dX]$' },
{label='TLS'        , property='P1362', lang='de', regexp='' }, -- Theaterlexikon der Schweiz
{label='SIKART'      , property='P781' , lang='de', regexp='^%d%d%d%d%d%d%d%d?%d?%d?$' }, -- Swiss
{label='NLP'        , property='P1695', lang='pl', regexp='' }, -- National Library of Poland
{label='WGA'        , property='P1882', lang='en', regexp='' }, -- Web Gallery of Art
{label='KulturNav'  , property='P1248', lang='no', regexp='' },
{label='RKD'        , property='P650' , lang='nl', regexp='^[1-9]%d%d?%d?%d?%d?$' }, --Netherlands Institute for Art History#Online artist pages
{label='autores.uy'  , property='P2558', lang='es', regexp='^[1-9]%d?%d?%d?%d?$' },  --autores.uy
{label='J9U'        , property='P8189', lang='he', regexp='' },  --National Library of Israel J9U ID
 
{label='FIDE'        , property='P1440', lang='en', regexp='' }, -- FIDE database for chess players
{label='Chess Games' , property='P1665', lang='en', regexp='' }, -- Chess Games
 
{label='ISSN'        , property='P236',  lang='', regexp='' }, -- P1629: International Standard Serial Number
{label='OSM'        , property='P402',  lang='', regexp='' },  -- P1629: OpenStreetMap
{label='Joconde'    , property='P347',  lang='fr', regexp='' }, -- Joconde ID
{label='Rijksmonument',property='P359',  lang='nl', regexp='' }, -- Rijksmonument ID
{label='IMO'        , property='P458',  lang='', regexp='' }, --IMO ship number
{label='BNCF'        , property='P508',  lang='it', regexp='' }, -- BNCF Thesaurus ID
{label='MMSI'        , property='P587',  lang='', regexp='' }, -- P1629: Maritime Mobile Service Identity
{label='Open Library', property='P648',  lang='', regexp='' }, -- P1629: Open Library
{label='NRHP'        , property='P649',  lang='en', regexp='' }, -- NRHP reference number
{label='DBNL'        , property='P723',  lang='', regexp='' }, -- DBNL author ID
{label='UNESCO'      , property='P757',  lang='', regexp='' }, -- World Heritage Site ID
{label='BIC'        , property='P808',  lang='', regexp='' }, -- Bien de Interés Cultural (BIC) code
{label='LIR'        , property='P886',  lang='', regexp='' }, -- LIR
{label='BNR'        , property='P1003', lang='ro', regexp='' }, -- NLR (Romania) ID
{label='Koninklijke' , property='P1006', lang='nl', regexp='' }, -- National Thesaurus for Author Names ID
{label='Louvre'      , property='P9394', lang='', regexp='' }, -- Louvre ID
{label='OCLC'        , property='P243',  lang='', regexp='' }, -- OCLC
{label='ISBN-13'    , property='P212',  lang='', regexp='' }, -- ISBN-13
{label='ISBN-10'    , property='P957',  lang='', regexp='' }, -- ISBN-10
{label='Historic England', property='P1216', lang='en', regexp='' }, -- National Heritage List for England number
 
{label='Oxford Dict.', property='P1415', lang='en', regexp='' }, -- Oxford Dictionary of National Biography ID
{label='kulturnoe-nasledie', property='P1483', lang='ru', regexp='' },  -- kulturnoe-nasledie.ru ID
{label='Catalunya'  , property='P1600', lang='ca', regexp='' }, -- Inventari del Patrimoni Arquitectònic de Catalunya code
{label='COAM'        , property='P2917', lang='es', regexp='' }, -- COAM structure ID
{label='SIMBAD'      , property='P3083', lang='fr', regexp='' }, -- SIMBAD ID
{label='JCyL'        , property='P3177', lang='es', regexp='' }, -- Patrimonio Web JCyL ID
{label='Zaragoza'    , property='P3178', lang='es', regexp='' },  -- Zaragoza monument ID
{label='BDI'        , property='P3318', lang='es', regexp='' }, -- Patrimonio Inmueble de Andalucía ID
{label='SIPCA'      , property='P3580', lang='es', regexp='' }, -- SIPCA code
{label='DOCOMOMO'    , property='P3758', lang='', regexp='' }, -- DOCOMOMO Ibérico ID
{label='Czech Monument', property='P4075', lang='cz', regexp='' }, -- Czech Monument Catalogue Number
{label='MEG'        , property='P4157', lang='ch', regexp='' }, -- P1629: Musée d'ethnographie de Genève
{label='Enciclopédia Itaú Cultural' , property='P4399', lang='pt_br', regexp='' }, -- Enciclopédia Itaú Cultural ID
{label='Monumentos de São Paulo'    , property='P4360', lang='pt_br', regexp='' }, -- Monumentos de São Paulo ID
{label='Infopatrimônio'            , property='P4372', lang='pt_br', regexp='' }, -- Infopatrimônio ID
{label="Musée d'Orsay"              , property='P4659', lang='fr'  , regexp='' }, -- Musée d'Orsay artwork ID
{label='MuBE'                      , property='P4721', lang='pt_br', regexp='' }, -- MuBE Virtual ID
{label='Hispania Nostra'            , property='P4868', lang='es'  , regexp='' }, -- Hispania Nostra Red List ID
{label='NLK'            , property='P5034', lang='ko'  , regexp='' }, -- National Library of Korea ID
}
 
-- ==================================================
-- === External functions ===========================
-- ==================================================
local p = {}
 
function p.getAuthorityControlTag( lang )
-- get a localized interwiki link to article "Authority Control"
local field_name = "[[w:en:Help:Authority control|Authority control]]" -- hardwire the default
if lang~='en' then
field_name = core.getLabel("Q36524", lang)
end
end
return field_name
local conf = config.config
end
local parentArgs = frame:getParent().args
 
local auxCats = ''
-- ==================================================
local rct = false -- boolean to track if there are any links to be returned
function p._authorityControl(entity, args, lang, length)
local qid,topic
-- INPUTS:
local wikilink = function(qid,hideifequal)
--  * entity - wikidata entity if already created or nil. If provided than you should still provide args.Wikidata
local label,sitelink = mw.wikibase.getLabel(qid),mw.wikibase.getSitelink(qid)
--  * args  - structure with identifier fields: args.VIAF, args.LCCN, args.Wikidata, etc.
if label then
-- * lang  - language code
if sitelink then
-- * length - maximum length of the identifier array, or number of identifiers to display
local target = mw.title.new(sitelink)
-- OUTPUTS:
if target==title or (target.isRedirect and target.redirectTarget==title) then -- do not link
--  * results - wikicode string equivalent to {{Authority control|...|bare=1 }} call
return label
--  * cats    - wikicode with maintenance categories
else -- make wikilink to article
 
return '[[' .. sitelink .. '|' .. label .. ']]'
  -- count custom parameters (not pulled from Wikidata)
end
local nCustomParam = 0
else
for _,params in ipairs( conf ) do
return label
if (args[params.label]~=nil) then
end
nCustomParam = nCustomParam + 1
else
auxCats = auxCats .. needsAttention('L')
return qid
end
end
end
end
if namespace == 0 then
-- Get entity - record of wikidata related to a single item
qid = mw.wikibase.getEntityIdForCurrentPage()
local q = args.wikidata
if not entity and q then
entity = mw.wikibase.getEntity(q)
end
end
if qid then -- article is connected to Wikidata item
-- Check if this is category item
if parentArgs.qid and (resolveQID(parentArgs.qid) ~= qid) then -- non-matching qid parameter
local cats = '' -- categories (mismatching and missing)
auxCats = auxCats .. needsAttention('D')
if entity and entity.claims and entity.claims.P31 then  
end
for _, statement in pairs( entity.claims.P31) do
else -- page is not connected to any Wikidata item
if (statement.mainsnak.snaktype == "value") and (statement.mainsnak.datavalue.value.id == 'Q4167836') then -- P31 == Wikimedia category
qid = resolveQID(parentArgs.qid) -- check qid parameter if no wikidata item is connected
cats = '[[Category:Wrong Wikidata ID in authority control data: category item]]'
if qid then -- qid parameter is valid, set topic to display
topic = mw.wikibase.getLabel(qid)
if topic then
if mw.ustring.lower(title.subpageText) == mw.ustring.lower(topic) then -- suppress topic display if subpagename equals topic up to case change
topic = nil
end
if topic and mw.wikibase.getSitelink(qid) then -- make wikilink to article
topic = '[[' .. mw.wikibase.getSitelink(qid) .. '|' .. topic .. ']]'
end
else
auxCats = auxCats .. needsAttention('L')
end
end
if (statement.mainsnak.snaktype == "value") and (statement.mainsnak.datavalue.value.id == 'Q4167410') then -- P31 == Wikimedia disambiguation page
elseif parentArgs.qid and parentArgs.qid~='' then -- invalid qid has been supplied, add to tracking cat
cats = '[[Category:Wrong Wikidata ID in authority control data: disambiguation item]]'
auxCats = auxCats .. needsAttention('Q')
end
end
local qids = {} -- setup any additional QIDs
if parentArgs.additional=='auto' and qid then  -- check P527 for parts to add additional qids
local checkparts = function(property)
local parts = mw.wikibase.getBestStatements(qid,property)
if parts then
for _,part in ipairs(parts) do
if part.mainsnak.datavalue and part.mainsnak.datavalue.value.id then
local resolvedqid = resolveQID(part.mainsnak.datavalue.value.id)
if resolvedqid then
table.insert(qids,resolvedqid)
end end end end end
for _,part in ipairs(config.auto_additional) do
checkparts('P'..tostring(part))
end
elseif parentArgs.additional and parentArgs.additional ~= '' then
for _,v in ipairs(mw.text.split(parentArgs.additional,"%s*,%s*")) do
v = resolveQID(v)
if v then
if v == qid then -- duplicate of qid parameter
auxCats = auxCats .. needsAttention('R')
end
table.insert(qids,v)
else -- invalid QID specified
auxCats = auxCats .. needsAttention('A')
end
end
end
end
end
end


--compare provided arguments with Wikidata identifiers
local sections = {}
local data = {} -- structure similar to "args" but filled with wikidata data
local localparams = false
for _,params in ipairs( conf ) do
local numsections = 0
local label = string.lower(params.label)
for _,_ in ipairs(config.sections) do numsections = numsections + 1 end
data[label] = nil
for _ = 1,#qids+numsections do table.insert(sections,{}) end
if entity and entity.claims and params.property and entity.claims[params.property] then -- if we have wikidata item and item has the property
local qslink = '' -- setup link to add using QuickStatements
-- capture all Wikidata values for the identifier
 
--for _, statement in pairs( entity.claims[params.property]) do
-- check which identifiers to show/suppress in template
for _, statement in pairs( entity:getBestStatements( params.property )) do
local show = {} -- setup list
if (statement.mainsnak.snaktype == "value") then -- or if statement.mainsnak.datavalue then
local showall = true
local v = statement.mainsnak.datavalue.value
local function stripP(pid)
if data[label]==nil then
if pid:match("^[Pp]%d+$") then
data[label] = v       -- save the first value
pid = mw.ustring.gsub(pid,'[Pp]','') --strip P from property number
end
end
if args[label] == v then  -- match between template and wikidata identifiers
if pid:match("^%d+$") then
data[label] = ''      -- ignore identifier from wikidata
return tonumber(pid)
break 
end
end
local function addshowlist(list)
if list and list ~= '' then
for _,v in ipairs(mw.text.split(string.lower(list),"%s*,%s*")) do
local vprop = stripP(v)
if vprop then -- e.g. show=P214 to show one particular property
show[vprop] = true
else -- e.g. show=arts to use whitelist
if config.whitelists[v] then
for _,w in ipairs(config.whitelists[v].properties) do
show[w] = true
end
end
end
end
end
end
end
showall = false
end
end
end
end
 
addshowlist(frame.args.show) -- check show= parameter on wrapper template
--Create string with all the identifiers listed
addshowlist(parentArgs.show or parentArgs.country) -- check show parameter on article template
local results1 = {} -- high priority list
if parentArgs.suppress then
local results2 = {} -- low  priority list
local suppresslist = mw.text.split(parentArgs.suppress,"%s*,%s*") -- split parameter by comma
properties.P214.item = 'Q54919';  -- hardwire link to VIAF
for _,v in ipairs(suppresslist) do
local today = '+' .. os.date('!%F') .. 'T00:00:00Z/11'
v = stripP(string.upper(v))
local TransStr = 'https://quickstatements.toolforge.org/#/v1=%s|%s|%%22%s%%22|S143|Q565|S813|'.. today -- QuickStatementts URL
if v then
TransStr = '<span class=\"plainlinks\" title=\"Click (+) to copy to wikidata\">['.. TransStr .. ' (+)]</span>'
show[v] = false
for _,params in ipairs( conf ) do
auxCats = auxCats .. '[[' .. config.i18n.category .. ':' .. config.i18n.suppressedcat .. ']]'
local label = string.lower(params.label)
local val1 = args[label] -- identifier value provided to the template
local val2 = data[label] -- identifier value pulled from wikidata
if val1 or val2 then
local P = properties[params.property] -- properties of wikidata identifier propertyc
-- name_link - link for the identifier name
local name_link = getIdentifierNameLink( lang, P.item, P.issuedBy, params.label )
-- val_link - identifier value or values
local transfer = ''
local val3 = string.gsub(val1 or '', ' ', '' ) -- remove spaces
local val_link
if not val1 then
val_link = getIdentifierValLink(val2, P.URL_format, params, 'blue') -- wikidata only no local identifier
elseif val2=='' then
val_link = getIdentifierValLink(val1, P.URL_format, params, 'magenta') -- match was found
elseif val2 then
val_link = getIdentifierValLink(val1, P.URL_format, params, 'darkgreen') .. "/"..getIdentifierValLink(val2, P.URL_format, params, 'blue')
cats  = string.format("%s[[Category:Pages using authority control with identifiers mismatching Wikidata]]\n", cats)
transfer  = string.format(TransStr, q, params.property, val3)
elseif not val2 and entity then
val_link = getIdentifierValLink(val1, P.URL_format, params, 'darkgreen')
cats  = string.format("%s[[Category:Pages using authority control with identifiers missing from Wikidata]]\n", cats)
transfer  = string.format(TransStr, q, params.property, val3)
else
else
val_link = getIdentifierValLink(val1, P.URL_format, params, 'blue') -- local identifier and no wikidata q-code
auxCats = auxCats .. needsAttention('P')
end
 
-- combine them all
local lineStr = string.format("\n*%s:&thinsp;<span class=\"uid\">%s</span>%s", name_link, val_link, transfer)
if (params.lang==lang) or (params.lang=='') then
table.insert(results1, lineStr) -- add to high priority list
else
table.insert(results2, lineStr) -- add to low priority list
end
end
end
end
end -- for all sources
-- merge high and low priority lists, trim them if needed and convert to string
--table.insert(results1, "\n*End list 1") -- for debuging
--table.insert(results2, "\n*End list 2")
for _,v in pairs(results2) do table.insert(results1, v) end
local results = table.concat(results1, "", 1, math.min(#results1, length or #results1))
-- Add Link to wikidata
if q then
results = string.format("\n*[[File:Wikidata-logo.svg|20px|wikidata:%s|link=wikidata:%s]]: [[d:%s|%s]]%s",q,q,q,q,results)
end
end
-- Add link to Worldcat
local function makeSections(qid,addit)
if (args.worldcatid==nil and (args.lccn or data.lccn)) then
local tval = {}
args.worldcatid = 'lccn-' .. (args.lccn or data.lccn)
local function parameter_is_used(property)
local used = false
if property then
if tval[property] then
if tval[property][1] then
used = true
end
elseif tval[property] == false then -- property has been manually suppressed
used = true
end
end
return used
end
for _, params in ipairs(conf) do
tval[params.property] = getIdsFromWikidata(qid, 'P' .. params.property) -- setup table for values with property number as key
local showb = true
if (show[params.property] == nil) and (show[string.upper(params[1])] == nil ) then
showb = showall -- if not specified then depends on showall
elseif (show[params.property] == false) or (show[string.upper(params[1])] == false) then -- if either are false then id will be suppressed
showb = false
end
if not showb then
tval[params.property] = false -- indicates the identifier is suppressed
elseif not addit then
local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]]
if val and val~='' then -- add local parameter to list if not already in
localparams = true
local bnew = true
for _, w in pairs(tval[params.property]) do
if val == w.id then
bnew = false
end
end
if bnew then -- add new value to table
if qid then
qslink = qslink .. '%7C%7C' .. qid .. '%7CP' .. params.property .. '%7C%22' .. mw.uri.encode(val,"PATH") .. '%22%7CS143%7CQ328'
end
table.insert(tval[params.property],{id=val,name=''})
end
end
end
local suppress = false
if params.suppressedbyproperty then
for _,sc in ipairs(params.suppressedbyproperty) do
if parameter_is_used(sc) then
suppress = true
end
end
end
if tval[params.property] ~= false and not suppress then
local tlinks = {} -- setup table for links
local nextIdVal = 1
local row = ''
for _,val in ipairs(tval[params.property]) do
local link = _makelink(params,val,nextIdVal,qid)
row = row .. link
table.insert(tlinks,link)
nextIdVal = nextIdVal + 1
end
if nextIdVal>=2 then
row = row .. '\n'
table.insert(sections[addit or params.section],row)
rct = true
end
end
end
end
end
if args.worldcatid  then
local function pencil(qid)
results = string.format("%s\n*<span class=\"uid\">[//www.worldcat.org/identities/%s WorldCat]</span>", results, args.worldcatid)
if not qid then
return ''
end
local args = { pid = 'identifiers' } -- #target the list of identifiers
args.qid = qid
return require('Module:EditAtWikidata')._showMessage(args)
end
end
 
-- Add maintenance categories
makeSections(qid,false)
if q == nil then
for c = 1,#qids do
cats = string.format("%s[[Category:Pages using authority control without Wikidata link]]\n", cats)
makeSections(qids[c],numsections+c)
end
end
if nCustomParam>0 then
 
if cats=='' and entity ~= nil then
--configure Navbox
cats = string.format("%s[[Category:Pages using authority control with all identifiers matching Wikidata]]\n", cats)
local outString = ''
if rct or localparams then -- there is at least one link to display
local Navbox = require('Module:Navbox')
local sect,lastsect = 0,0
local navboxArgs = {
name  = 'Authority control',
navboxclass = 'authority-control',
bodyclass = 'hlist',
state = parentArgs.state or config.i18n.autocollapse,
navbar = 'off'
}
for c=1,numsections+#qids do
if #sections[c] ~= 0 then -- section is non-empty
sect = sect + 1
lastsect = c
local sectname
if c <= numsections then -- regular section
sectname = config.sections[c].name
else -- section from additional qid
local qid = qids[c-numsections]
sectname = wikilink(qid) .. pencil(qid)
end
navboxArgs['group' .. c] = sectname
navboxArgs['list' .. c] = table.concat(sections[c])
end
end
end
if string.find(results, "<span style=\"color:red\">") then  
if localparams then
cats = string.format("%s[[Category:Pages using authority control with badly formated identifier]]\n", cats)
lastsect = lastsect + 1
sect = sect + 1
navboxArgs['group' .. lastsect] = config.i18n.warning
local warning = frame:expandTemplate{title = config.i18n.errortemplate, args = {config.i18n.localparams}}
if qslink ~= '' then
warning = warning .. ' ' .. config.i18n.movetowd .. '<span class="qs autoconfirmed-show">&#32;[[File:Commons to Wikidata QuickStatements.svg|20px|link=https://quickstatements.toolforge.org/#/v1=' .. qslink .. '|' .. config.i18n.addtowd .. ']]</span>'
elseif not qid then
if namespace == 0 then
warning = warning .. ' ' .. config.i18n.connecttowd
elseif namespace==14 or namespace==2 or namespace==118 then
warning = warning .. ' ' .. config.i18n.qidcode
end
end
navboxArgs['list' .. lastsect] = warning
end
end
if topic then -- display in expanded form with topic
navboxArgs.title = config.i18n.aclink .. ' &ndash; ' .. topic .. pencil(qid)
elseif sect == 1 then -- special display when only one section
if lastsect <= numsections then
if config.sections[lastsect].hidelabelwhenalone then -- no special label when only general or other IDs are present
navboxArgs['group' .. lastsect] = config.i18n.aclink .. pencil(qid)
else -- other regular section
navboxArgs['group' .. lastsect] = config.i18n.aclink .. ': ' .. navboxArgs['group' .. lastsect] .. pencil(qid)
end
else -- section from additional qid
navboxArgs['group' .. lastsect] = config.i18n.aclink .. ': ' .. navboxArgs['group' .. lastsect]
end
else -- add title to navbox
navboxArgs.title = config.i18n.aclink .. pencil(qid)
end
outString = Navbox._navbox(navboxArgs)
end
end


-- return results
if parentArgs.state
if results~='' then -- if there are any results than wrap them in <div> tag
and parentArgs.state~=''
results  = string.format('<div class="hlist">%s\n</div>', results)
and parentArgs.state~=config.i18n.collapsed
and parentArgs.state~=config.i18n.expanded
and parentArgs.state~=config.i18n.autocollapse then --invalid state parameter
auxCats = auxCats .. needsAttention('S')
end
if testcases then
auxCats = mw.ustring.gsub(auxCats, '(%[%[)(' .. config.i18n.category .. ')', '%1:%2') --for easier checking
end
end
return results, cats
end


-- ===========================================================================
--out
-- === Version of the function to be called from template namespace
outString = outString..auxCats
-- ===========================================================================
if namespace ~= 0 then
function p.authorityControl(frame)
outString = mw.ustring.gsub(outString,'(%[%[)(' .. config.i18n.category .. ':' .. config.i18n.Articles .. ')([^%|%]]+)%|?[^%|%]]*(%]%])','%1:%2%3%4')
-- prepare arguments
outString = mw.ustring.gsub(outString,'(%[%[)(' .. config.i18n.category .. ':' .. config.i18n.All_articles .. ')([^%|%]]+)%|?[^%|%]]*(%]%])','%1:%2%3%4')
local args = core.getArgs(frame)
local bare = core.yesno(args.bare,false)        
-- Convert template arguments to the same format as used on wikidata
if args.bnf then
args.bnf = string.sub(args.bnf, 3) -- trim first 2 characters
end
end
if args.isni then -- group in sets of 4
local check = require('Module:Check for unknown parameters')._check
args.isni = string.sub(args.isni, 1, 4).." "..string.sub(args.isni, 5, 8)
local sortkey
    .." "..string.sub(args.isni, 9,12).." "..string.sub(args.isni,13,16)
if namespace == 0 then
sortkey = '*' .. title.text
else
sortkey = title.fullText
end
end
if args.isbn then
outString = outString .. check({
local isbn = isbn.gsub( ' ', '' )
['unknown'] = '[[' .. config.i18n.category .. ':' .. config.i18n.pageswithparams .. '|' .. sortkey .. ']]',
if #isbn==10 then
['preview'] = config.i18n.previewwarning, 'show', 'country', 'suppress', 'additional', 'qid', 'state'
args['isbn-10'] = args.isbn
}, parentArgs)
elseif #isbn==13 then
return outString
args['isbn-13'] = args.isbn
end
end
args.isbn = nil
end
args.gnd  = args.gnd or args.pnd --redirect PND to GND
args.lccn = fixLCCN(args.lccn)
args.wikidata = args.wikidata or args.q or nil
-- call the inner "core" function
local results, cats = p._authorityControl(nil, args, args.lang, args.length)
local namespace = mw.title.getCurrentTitle().namespace
local LUT = {[2]='user', [6]='file', [10]='template', [828]='module'}
if (LUT[namespace] or math.fmod(namespace,2)==1) then
-- lets not add categories to some namespaces, or talk pages and concentrate
-- on templates and categories instead
cats = ''  
end
--package results as a infobox if not "bare"
if not bare then
-- Get field name for authority control
local field_name = p.getAuthorityControlTag(args.lang)


-- build table
p.makelink = function(conf,val,nextid,qid)
results = string.format('<tr><td class="type fileinfo-paramfield">%s</td><td>\n%s\n</td></tr>', field_name, results)
return _makelink(conf,val,nextid,qid)
local dir  = mw.language.new( args.lang ):getDir()    -- get text direction
local style = 'class="toccolours mw-content-%s layouttemplate commons-file-information-table" style="width: 100%%;" dir="%s" lang="%s"'
style = string.format(style, dir, dir, args.lang)
results = string.format('<table %s>\n%s\n</table>\n', style, results)
else
results = string.format('\n%s\n', results)
end
return results..cats
end
end


return p
return p

Latest revision as of 10:01, 8 August 2023

This module contains the code of the {{Authority control}} template. See its documentation.

Parameters, Wikidata properties, and tracking categories

Script error: The function "docConfTable" does not exist.

Additional tracking categories

This module also implements the following hidden tracking categories:

Number of identifiers

State parameter

See also


require('strict')
local p = {}
local configfile = 'Module:Authority control/config' -- default configuation module
local arg = mw.getCurrentFrame().args.config
if arg and arg~='' then
	configfile = 'Module:Authority control/config/' .. arg
end
local config
if mw.title.new(configfile).exists then
	config = mw.loadData(configfile)
else
	return error('Invalid configuration file',0)
end
local title = mw.title.getCurrentTitle()
local namespace = title.namespace
local testcases = title.subpageText == config.i18n.testcases

local function needsAttention(sortkey)
	return '[[' .. config.i18n.category .. ':' .. config.i18n.attentioncat .. '|' .. sortkey .. title.text .. ']]'
end

local function addCat(cat,sortkey)
	if cat and cat ~= '' and (namespace == 0 or namespace == 14 or testcases) then
		local redlinkcat = ''
		if testcases == false and mw.title.new(cat, 14).exists == false then
			redlinkcat = needsAttention('N')
		end
		if sortkey then
			cat = '[[' .. config.i18n.category .. ':'..cat..'|' .. sortkey .. title.text .. ']]'
		else
			cat = '[[' .. config.i18n.category .. ':'..cat..']]'
		end
		cat = cat .. redlinkcat
		return cat
	else
		return ''
	end
end

local function getCatForId(id,faulty)
	local cat = string.format(
		config.i18n.cat,
		(faulty and config.i18n.faulty..' ' or '') .. id
	)
	return addCat(cat)
end

local function getIdsFromWikidata(qid,property)
	local function getquals(statement,qualid)
		if statement.qualifiers and statement.qualifiers['P'..qualid] then
			return mw.wikibase.renderSnak(statement.qualifiers['P'..qualid][1])
		else
			return false
		end
	end
	local ids = {}
	if qid then
		for _, statement in ipairs(mw.wikibase.getBestStatements(qid,property)) do
			if statement.mainsnak.datavalue then
				local val = statement.mainsnak.datavalue.value
				if val then
					local namedas = getquals(statement,1810) or getquals(statement,742) or ''
					table.insert(ids,{id=val,name=namedas})
				end
			end
		end
	end
	return ids
end

local _makelink = function(conf,val,nextid,qid) --validate values and create a link
	local function tooltip(text,label)
		if label and label~='' then
			return mw.getCurrentFrame():expandTemplate{title = "Tooltip", args = {text,label}}
		else
			return text
		end
	end
	local link
	if nextid==1 then
		if conf.prefix then
			link = '*' .. conf.prefix .. '\n**'
		else
			link = '*'
		end
	else
		link = '\n**'
	end
	local valid_value = false
	if conf.customlink then -- use function to validate and generate link
		local label = nextid>1 and nextid
		local newlink= require(config.auxiliary)[conf.customlink](val.id,label)
		if newlink then
			link = link .. newlink
			valid_value = true
		end
	else
		if conf.pattern then -- use pattern to determine validity if defined
			valid_value = string.match(val.id,'^'..conf.pattern..'$')
		elseif conf.patterns then
			for _,pattern in ipairs(conf.patterns) do
				valid_value = val.id:match('^'..pattern..'$')
				if valid_value then break end
			end
		elseif conf.valid then -- otherwise use function to determine validity
			valid_value = require(config.auxiliary)[conf.valid](val.id)
		else -- no validation possible
			valid_value = val.id
		end
		if valid_value then
			local newlink
			local label = conf.label
			if not label or nextid>1 then
				label = tostring(nextid)
			end
			if conf.link then
				valid_value = valid_value:gsub('%%', '%%%%')
				newlink = '[' .. mw.ustring.gsub(conf.link,'%$1',valid_value) .. ' ' .. label .. ']'
			else
				newlink = valid_value
			end
			link = link .. '<span class="uid">'..tooltip(newlink,val.name)..'</span>'
		end
	end
	if valid_value then
		link = link .. getCatForId(conf.category or conf[1])
	else
		--local preview = require("Module:If preview")
		local wdlink = qid and '[[:wikidata:' .. qid .. '#P' .. conf.property .. ']]' or ''
		local tooltip = string.format(
			config.i18n.idnotvalid,
			conf[1],
			val.id
		)
		link = link .. '[[File:' .. config.i18n.warningicon .. '|20px|frameless|link=' .. wdlink .. '|' .. tooltip .. '.]]'
		if conf.errorcat then
			link = link .. addCat(conf.errorcat)
		else
			link = link .. getCatForId(conf.category or conf[1],true)
		end
		link = link .. addCat(config.i18n.allfaultycat,conf[1])-- .. preview._warning({'The '..conf[1]..' id '..val..' is not valid.'})
	end
	return link
end

--[[==========================================================================]]
--[[                                   Main                                   ]]
--[[==========================================================================]]
function p.authorityControl(frame)
	local function resolveQID(qid)
		if qid then
			qid = 'Q'..mw.ustring.gsub(qid, '^[Qq]', '')
			if mw.wikibase.isValidEntityId(qid) and mw.wikibase.entityExists(qid) then
				local sitelink = mw.wikibase.getSitelink(qid)
				if sitelink then
					return mw.wikibase.getEntityIdForTitle(sitelink) or mw.wikibase.getEntity(qid).id
				end
				return mw.wikibase.getEntity(qid).id
			end
		end
	end
	local conf = config.config
	local parentArgs = frame:getParent().args
	local auxCats = ''
	local rct = false -- boolean to track if there are any links to be returned
	local qid,topic
	local wikilink = function(qid,hideifequal)
		local label,sitelink = mw.wikibase.getLabel(qid),mw.wikibase.getSitelink(qid)
		if label then
			if sitelink then
				local target = mw.title.new(sitelink)
				if target==title or (target.isRedirect and target.redirectTarget==title) then -- do not link
					return label
				else -- make wikilink to article
					return '[[' .. sitelink .. '|' .. label .. ']]'
				end
			else
				return label
			end
		else
			auxCats = auxCats .. needsAttention('L')
			return qid
		end
	end
	if namespace == 0 then
		qid = mw.wikibase.getEntityIdForCurrentPage()
	end
	if qid then -- article is connected to Wikidata item
		if parentArgs.qid and (resolveQID(parentArgs.qid) ~= qid) then -- non-matching qid parameter
			auxCats = auxCats .. needsAttention('D')
		end
	else -- page is not connected to any Wikidata item
		qid = resolveQID(parentArgs.qid) -- check qid parameter if no wikidata item is connected
		if qid then -- qid parameter is valid, set topic to display
			topic = mw.wikibase.getLabel(qid)
			if topic then
				if mw.ustring.lower(title.subpageText) == mw.ustring.lower(topic) then -- suppress topic display if subpagename equals topic up to case change
					topic = nil
				end
				if topic and mw.wikibase.getSitelink(qid) then -- make wikilink to article
					topic = '[[' .. mw.wikibase.getSitelink(qid) .. '|' .. topic .. ']]'
				end
			else
				auxCats = auxCats .. needsAttention('L')
			end
		elseif parentArgs.qid and parentArgs.qid~='' then -- invalid qid has been supplied, add to tracking cat
			auxCats = auxCats .. needsAttention('Q')
		end
	end
	local qids = {} -- setup any additional QIDs
	if parentArgs.additional=='auto' and qid then  -- check P527 for parts to add additional qids
		local checkparts = function(property)
			local parts = mw.wikibase.getBestStatements(qid,property)
			if parts then
				for _,part in ipairs(parts) do
					if part.mainsnak.datavalue and part.mainsnak.datavalue.value.id then
						local resolvedqid = resolveQID(part.mainsnak.datavalue.value.id)
						if resolvedqid then
							table.insert(qids,resolvedqid)
		end end end end end
		for _,part in ipairs(config.auto_additional) do
			checkparts('P'..tostring(part))
		end
	elseif parentArgs.additional and parentArgs.additional ~= '' then
		for _,v in ipairs(mw.text.split(parentArgs.additional,"%s*,%s*")) do
			v = resolveQID(v)
			if v then
				if v == qid then -- duplicate of qid parameter
					auxCats = auxCats .. needsAttention('R')
				end
				table.insert(qids,v)
			else -- invalid QID specified
				auxCats = auxCats .. needsAttention('A')
			end
		end
	end

	local sections = {}
	local localparams = false
	local numsections = 0
	for _,_ in ipairs(config.sections) do numsections = numsections + 1 end
	for _ = 1,#qids+numsections do table.insert(sections,{}) end
	local qslink = '' -- setup link to add using QuickStatements

	-- check which identifiers to show/suppress in template
	local show = {} -- setup list
	local showall = true
	local function stripP(pid)
		if pid:match("^[Pp]%d+$") then
			pid = mw.ustring.gsub(pid,'[Pp]','') --strip P from property number
		end
		if pid:match("^%d+$") then
			return tonumber(pid)
		end
	end
	local function addshowlist(list)
		if list and list ~= '' then
			for _,v in ipairs(mw.text.split(string.lower(list),"%s*,%s*")) do
				local vprop = stripP(v)
				if vprop then -- e.g. show=P214 to show one particular property
					show[vprop] = true
				else -- e.g. show=arts to use whitelist
					if config.whitelists[v] then
						for _,w in ipairs(config.whitelists[v].properties) do
							show[w] = true
						end
					end
				end
			end
			showall = false
		end
	end
	addshowlist(frame.args.show) -- check show= parameter on wrapper template
	addshowlist(parentArgs.show or parentArgs.country) -- check show parameter on article template
	if parentArgs.suppress then
		local suppresslist = mw.text.split(parentArgs.suppress,"%s*,%s*") -- split parameter by comma
		for _,v in ipairs(suppresslist) do
			v = stripP(string.upper(v))
			if v then
				show[v] = false
				auxCats = auxCats .. '[[' .. config.i18n.category .. ':' .. config.i18n.suppressedcat .. ']]'
			else
				auxCats = auxCats .. needsAttention('P')
			end
		end
	end
	
	local function makeSections(qid,addit)
		local tval = {}
		local function parameter_is_used(property)
			local used = false
			if property then
				if tval[property] then
					if tval[property][1] then
						used = true
					end
				elseif tval[property] == false then -- property has been manually suppressed
					used = true
				end
			end
			return used
		end
		for _, params in ipairs(conf) do
			tval[params.property] = getIdsFromWikidata(qid, 'P' .. params.property) -- setup table for values with property number as key
			local showb = true
			if (show[params.property] == nil) and (show[string.upper(params[1])] == nil ) then
				showb = showall -- if not specified then depends on showall
			elseif (show[params.property] == false) or (show[string.upper(params[1])] == false) then -- if either are false then id will be suppressed
				showb = false
			end
			if not showb then
				tval[params.property] = false -- indicates the identifier is suppressed
			elseif not addit then
				local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]]
				if val and val~='' then -- add local parameter to list if not already in
					localparams = true
					local bnew = true
					for _, w in pairs(tval[params.property]) do
						if val == w.id then
							bnew = false
						end
					end
					if bnew then -- add new value to table
						if qid then
							qslink = qslink .. '%7C%7C' .. qid .. '%7CP' .. params.property .. '%7C%22' .. mw.uri.encode(val,"PATH") .. '%22%7CS143%7CQ328'
						end
						table.insert(tval[params.property],{id=val,name=''})
					end
				end
			end
			local suppress = false
			if params.suppressedbyproperty then
				for _,sc in ipairs(params.suppressedbyproperty) do
					if parameter_is_used(sc) then
						suppress = true
					end
				end
			end
			if tval[params.property] ~= false and not suppress then
				local tlinks = {} -- setup table for links
				local nextIdVal = 1
				local row = ''
				for _,val in ipairs(tval[params.property]) do
					local link = _makelink(params,val,nextIdVal,qid)
					row = row .. link
					table.insert(tlinks,link)
					nextIdVal = nextIdVal + 1
				end
				if nextIdVal>=2 then
					row = row .. '\n'
					table.insert(sections[addit or params.section],row)
					rct = true
				end
			end
		end
	end
	local function pencil(qid)
		if not qid then
			return ''
		end
		local args = { pid = 'identifiers' } -- #target the list of identifiers
		args.qid = qid
		return require('Module:EditAtWikidata')._showMessage(args)
	end

	makeSections(qid,false)
	for c = 1,#qids do
		makeSections(qids[c],numsections+c)
	end

	--configure Navbox
	local outString = ''
	if rct or localparams then -- there is at least one link to display
		local Navbox = require('Module:Navbox')
		local sect,lastsect = 0,0
		local navboxArgs = {
			name  = 'Authority control',
			navboxclass = 'authority-control',
			bodyclass = 'hlist',
			state = parentArgs.state or config.i18n.autocollapse,
			navbar = 'off'
		}
		for c=1,numsections+#qids do
			if #sections[c] ~= 0 then -- section is non-empty
				sect = sect + 1
				lastsect = c
				local sectname
				if c <= numsections then -- regular section
					sectname = config.sections[c].name
				else -- section from additional qid
					local qid = qids[c-numsections]
					sectname = wikilink(qid) .. pencil(qid)
				end
				navboxArgs['group' .. c] = sectname
				navboxArgs['list' .. c] = table.concat(sections[c])
			end
		end
		if localparams then
			lastsect = lastsect + 1
			sect = sect + 1
			navboxArgs['group' .. lastsect] = config.i18n.warning
			local warning = frame:expandTemplate{title = config.i18n.errortemplate, args = {config.i18n.localparams}}
			if qslink ~= '' then
				warning = warning .. ' ' .. config.i18n.movetowd .. '<span class="qs autoconfirmed-show">&#32;[[File:Commons to Wikidata QuickStatements.svg|20px|link=https://quickstatements.toolforge.org/#/v1=' .. qslink .. '|' .. config.i18n.addtowd .. ']]</span>'
			elseif not qid then
				if namespace == 0 then
					warning = warning .. ' ' .. config.i18n.connecttowd
				elseif namespace==14 or namespace==2 or namespace==118 then
					warning = warning .. ' ' .. config.i18n.qidcode
				end
			end
			navboxArgs['list' .. lastsect] = warning
		end
		if topic then -- display in expanded form with topic
			navboxArgs.title = config.i18n.aclink .. ' &ndash; ' .. topic .. pencil(qid)
		elseif sect == 1 then -- special display when only one section
			if lastsect <= numsections then
				if config.sections[lastsect].hidelabelwhenalone then -- no special label when only general or other IDs are present
					navboxArgs['group' .. lastsect] = config.i18n.aclink .. pencil(qid)
				else -- other regular section
					navboxArgs['group' .. lastsect] = config.i18n.aclink .. ': ' .. navboxArgs['group' .. lastsect] .. pencil(qid)
				end
			else -- section from additional qid
				navboxArgs['group' .. lastsect] = config.i18n.aclink .. ': ' .. navboxArgs['group' .. lastsect]
			end
		else -- add title to navbox
			navboxArgs.title = config.i18n.aclink .. pencil(qid)
		end
		outString = Navbox._navbox(navboxArgs)
	end

	if parentArgs.state
		and parentArgs.state~=''
		and parentArgs.state~=config.i18n.collapsed
		and parentArgs.state~=config.i18n.expanded
		and parentArgs.state~=config.i18n.autocollapse then --invalid state parameter
		auxCats = auxCats .. needsAttention('S')
	end
	if testcases then
		auxCats = mw.ustring.gsub(auxCats, '(%[%[)(' .. config.i18n.category .. ')', '%1:%2') --for easier checking
	end

	--out
	outString = outString..auxCats
	if namespace ~= 0 then
		outString = mw.ustring.gsub(outString,'(%[%[)(' .. config.i18n.category .. ':' .. config.i18n.Articles .. ')([^%|%]]+)%|?[^%|%]]*(%]%])','%1:%2%3%4')
		outString = mw.ustring.gsub(outString,'(%[%[)(' .. config.i18n.category .. ':' .. config.i18n.All_articles .. ')([^%|%]]+)%|?[^%|%]]*(%]%])','%1:%2%3%4')
	end
	local check = require('Module:Check for unknown parameters')._check
	local sortkey
	if namespace == 0 then
		sortkey = '*' .. title.text
	else
		sortkey = title.fullText
	end
	outString = outString .. check({
		['unknown'] = '[[' .. config.i18n.category .. ':' .. config.i18n.pageswithparams .. '|' .. sortkey .. ']]',
		['preview'] = config.i18n.previewwarning, 'show', 'country', 'suppress', 'additional', 'qid', 'state'
		}, parentArgs)
	return outString
end

p.makelink = function(conf,val,nextid,qid)
	return _makelink(conf,val,nextid,qid)
end

return p