Module:Authority control
From The Goon Show Depository
Revision as of 23:58, 30 August 2024 by en>MSGJ (do not add categories for each identifier unless specified in config)
This Lua module is used on approximately 1,990,000 pages, or roughly 8120% of all pages. To avoid major disruption and server load, any changes should be tested in the module's /sandbox or /testcases subpages, or in your own module sandbox. The tested changes can be added to this page in a single edit. Consider discussing changes on the talk page before implementing them. |
This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
Related pages |
---|
This module uses one or more Wikidata properties; see § Parameters for details.
This module depends on the following other modules: |
This module contains the code of the {{Authority control}} template. See its documentation.
Parameters, Wikidata properties, and tracking categories
Lua error in package.lua at line 80: module 'strict' not found.
Additional tracking categories
This module also implements the following hidden tracking categories:
- Category:Pages with red-linked authority control categories (1) – error category to identify missing categories
- Category:Articles with deprecated authority control identifiers (0) – fix/migrate/remove deprecated IDs
- Category:Articles with suppressed authority control identifiers (0) – tracking only (no error)
- Category:Articles with multiple identifiers (0) – tracking only (no error)
- Category:Pages using authority control with parameters (0) – migrate IDs to Wikidata, if possible (no error)
- Category:Pages using authority control with parameters different on Wikidata (0) – determine/remove incorrect IDs & migrate to Wikidata
- Category:Pages using authority control with parameters all matching Wikidata (0) – template parameters may safely be removed
Number of identifiers
- Category:AC with 0 elements (1)
- Category:AC with 25 elements (0)
- Category:AC with 26 elements (0)
- Category:AC with 27 elements (0)
- Category:AC with 28 elements (0)
- Category:AC with 29 elements (0)
- Category:AC with 30 elements (0)
- Category:AC with 31 elements (0)
- Category:AC with 32 elements (0)
- Category:AC with 33 elements (0)
- Category:AC with 34 elements (0)
- Category:AC with 35 elements (0)
- Category:AC with 36 elements (0)
- Category:AC with 37 elements (0)
- Category:AC with 38 elements (0)
- Category:AC with 39 elements (0)
- Category:AC with 40 elements (0)
- Category:AC with 41 elements (0)
- Category:AC with 42 elements (0)
- Category:AC with 43 elements (0)
- Category:AC with 44 elements (0)
- Category:AC with 45 elements (0)
State parameter
- Category:AC using state parameter: collapsed (0)
- Category:AC using state parameter: expanded (0)
- Category:AC using state parameter: autocollapse (0)
- Category:AC using state parameter: other (0)
See also
- m:Interwiki map – definition of global custom interwiki prefixes
require('strict')
local p = {}
local frame = mw.getCurrentFrame()
local config_file = frame.args.config and frame.args.config~='' and ('/' .. frame.args.config) or ''
local config = mw.loadData('Module:Authority control/config' .. config_file)
local title = mw.title.getCurrentTitle()
local namespace = title.namespace
local testcases = title.subpageText == config.i18n.testcases
local wikilink = function(target, label)
return label and '[[' .. target .. '|' .. label .. ']]' or '[[' .. target .. ']]'
end
local needsAttention = function(sortkey)
return wikilink(config.i18n.category .. ':' .. config.i18n.attentioncat, sortkey .. title.text)
end
local addCat = function(cat, sortkey)
if cat and cat~='' and (namespace==0 or namespace==14 or testcases) then
local redlinkcat = ''
if testcases==false then
local success, exists = pcall(function() return mw.title.new(cat, 14).exists end)
if success and not exists then
redlinkcat = needsAttention('N')
end
end
return wikilink(config.i18n.category..':'..cat, sortkey and sortkey..title.text) .. redlinkcat
else
return ''
end
end
local tooltip = function(text, label)
if label and label~='' then
return frame:expandTemplate{
title = 'Tooltip',
args = {text, label}
}
else
return text
end
end
local getstatement = function(id, propid)
local statement = mw.wikibase.getBestStatements('P' .. id, 'P' .. propid)
local value
if statement and statement[1] and statement[1].mainsnak.datavalue.value.id then
value = statement[1].mainsnak.datavalue.value.id
return value
end
end
p.getname = function(property) -- function to lookup the name of a property and provide a link if one exists
local item
for _, propnameqid in ipairs(config.property_items) do
item = getstatement(property, propnameqid)
if item then break end
end
if item then
local link = frame:expandTemplate{
title = 'Wikidata fallback link',
args = {item}
}
local raw = mw.wikibase.getLabel(item)
return link, raw
else
return ''
end
end
local _makelink = function(id, val, n, qid) --validate values and create a link
local link = mw.html.create('span'):addClass('uid')
if n==1 and id.prefix then --show prefix on primary value
link:wikitext(id.prefix .. ': ')
end
local valid_value = false
if id.customlink then -- use function to validate and generate link
local label = n>1 and n
local newlink = require(config.auxiliary)[id.customlink](val.id, label)
if newlink then
link:wikitext(newlink)
valid_value = true
end
else
if id.pattern then -- check pattern to determine validity
valid_value = string.match(val.id, '^' .. id.pattern .. '$')
elseif id.patterns then -- check multiple patterns to determine validity
for _, pattern in ipairs(id.patterns) do
valid_value = val.id:match('^' .. pattern .. '$')
if valid_value then break end
end
elseif id.valid then -- use function to determine validity
valid_value = require(config.auxiliary)[id.valid](val.id)
else -- no validation possible
valid_value = val.id
end
if valid_value then
local label = id.label
if not label or n>1 then
label = tostring(n)
end
local newlink
if id.link then
valid_value = valid_value:gsub('%%', '%%%%')
newlink = '[' .. mw.ustring.gsub(id.link, '%$1', valid_value) .. ' ' .. label .. ']'
else
newlink = valid_value
end
link:wikitext(tooltip(newlink, val.name))
end
end
if valid_value then
local cat = id.category and string.format(config.i18n.cat, id.category)
link:wikitext(addCat(cat))
else
local wdlink = qid and wikilink(':wikidata:' .. qid .. '#P' .. id.property) or ''
local _, name = p.getname(id.property)
local tooltip = string.format(
config.i18n.idnotvalid,
name,
val.id
)
local cat = id.category and string.format(
config.i18n.cat,
config.i18n.faulty .. ' ' .. id.category
)
link:wikitext(wikilink('File:' .. config.i18n.warningicon .. '|20px|frameless|link=' .. wdlink, tooltip .. '.'))
:wikitext(addCat(cat))
:wikitext(addCat(config.i18n.allfaultycat, name))
end
return link
end
local _makelinks = function(id, qid)
local getquals = function(statement, qualid)
if statement.qualifiers and statement.qualifiers['P'..qualid] then
return mw.wikibase.renderSnak(statement.qualifiers['P'..qualid][1])
end
end
local ids = {}
if qid then
for _, statement in ipairs(mw.wikibase.getBestStatements(qid, 'P'..id.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
local links
if ids[1] then
links = mw.html.create('li'):node(_makelink(id, ids[1], 1, qid))
if ids[2] then
local sublinks = mw.html.create('ul')
for n = 2, #ids do
sublinks:tag('li'):node(_makelink(id, ids[n], n, qid)):done()
end
links:node(sublinks)
end
end
return links
end
--[[==================================]]
--[[ Main ]]
--[[==================================]]
p.authorityControl = function(frame)
local resolveQID = function(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
if namespace==0 then
qid = mw.wikibase.getEntityIdForCurrentPage()
end
if qid then -- article is connected to a 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 = wikilink(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' .. 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 numsections = 0
for _, _ in ipairs(config.sections) do -- count number of regular sections
numsections = numsections + 1
end
local sections = {}
for _ = 1, #qids+numsections do
table.insert(sections, {})
end
-- check which identifiers to show/suppress in template
local show, show_all_unsuppressed = {}, true
local stripP = function(pid) --strip P from property number
if pid:match('^[Pp]%d+$') then
pid = mw.ustring.gsub(pid, '[Pp]', '')
end
if pid:match('^%d+$') then
return tonumber(pid)
end
end
local addshowlist = function(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
show_all_unsuppressed = false
end end
addshowlist(frame.args.show) -- check show= parameter on wrapper template
addshowlist(parentArgs.show) -- check show parameter on article
addshowlist(parentArgs.country) -- check country parameter on article
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(v)
if v then
show[v] = false
auxCats = auxCats .. wikilink(config.i18n.category .. ':' .. config.i18n.suppressedcat)
else
auxCats = auxCats .. needsAttention('P')
end
end
end
local makeSections = function(qid, addit)
for _, id in ipairs(conf) do
if id.suppressedbyproperty then
for _, property in ipairs(id.suppressedbyproperty) do
if show[property]=='used' then -- property is in use
show[id.property] = false -- suppressed by another property
end
end
end
if show[id.property]==nil then
show[id.property] = show_all_unsuppressed
end
if show[id.property] then
local links = _makelinks(id, qid)
if links then
table.insert(
sections[addit or id.section],
links
)
show[id.property] = 'used'
rct = true
end end end end
local pencil = function(qid)
if qid then
return require('Module:EditAtWikidata')._showMessage{
pid = 'identifiers',
qid = qid
}
else
return ''
end
end
makeSections(qid, false)
for c = 1, #qids do
makeSections(qids[c], numsections+c)
end
--configure Navbox
local outString = ''
if rct 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]
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
sectname = label
else -- make wikilink to article
sectname = wikilink(sitelink, label)
end
else
sectname = label
end
else
auxCats = auxCats .. needsAttention('L')
sectname = qid
end
sectname = sectname .. pencil(qid)
end
navboxArgs['group' .. c] = sectname
local list = mw.html.create('ul')
for _, link in ipairs(sections[c]) do
list:node(link)
end
navboxArgs['list' .. c] = tostring(list)
end
end
if topic then -- display in expanded form with topic
navboxArgs.title = config.i18n.aclink .. ' – ' .. 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'] = wikilink(config.i18n.category .. ':' .. config.i18n.pageswithparams, sortkey),
['preview'] = config.i18n.previewwarning, 'show', 'country', 'suppress', 'additional', 'qid', 'state'
}, parentArgs)
return outString
end
p.makelink = function(id, qid)
return _makelinks(id, qid)
end
return p