Module:Authority control: Difference between revisions
From The Goon Show Depository
en>Pppery (Avoid Lua error when out of expensive parser function calls) |
No edit summary |
||
(8 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
require('strict') | -- require('strict') | ||
local p = {} | local p = {} | ||
local | local frame = mw.getCurrentFrame() | ||
local config_file = frame.args.config and frame.args.config~='' and ('/' .. frame.args.config) or '' | |||
local config = mw.loadData( | local config = mw.loadData('Module:Authority control/config' .. config_file) | ||
local title = mw.title.getCurrentTitle() | local title = mw.title.getCurrentTitle() | ||
local namespace = title.namespace | local namespace = title.namespace | ||
local testcases = title.subpageText == config.i18n.testcases | local testcases = title.subpageText == config.i18n.testcases | ||
local function | local wikilink = function(target, label) | ||
return '[[' .. | return label and '[[' .. target .. '|' .. label .. ']]' or '[[' .. target .. ']]' | ||
end | end | ||
local function addCat(cat,sortkey) | local needsAttention = function(sortkey) | ||
if cat and cat ~= '' and (namespace == 0 or namespace == 14 or testcases) then | 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 = '' | local redlinkcat = '' | ||
if testcases == false then | if testcases==false then | ||
local success, exists = pcall(function() return mw.title.new(cat, 14).exists end) | local success, exists = pcall(function() return mw.title.new(cat, 14).exists end) | ||
if success and not exists then | if success and not exists then | ||
Line 21: | Line 25: | ||
end | end | ||
end | end | ||
return wikilink(config.i18n.category..':'..cat, sortkey and sortkey..title.text) .. redlinkcat | |||
else | else | ||
return '' | return '' | ||
Line 33: | Line 31: | ||
end | end | ||
local function | local tooltip = function(text, label) | ||
if label and label~='' then | |||
return frame:expandTemplate{ | |||
title = 'Tooltip', | |||
args = {text, label} | |||
} | |||
else | |||
return text | |||
end | |||
end | end | ||
local function | local getstatement = function(id, propid) | ||
local | 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 | ||
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 | end | ||
local | 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 | ||
end | end | ||
local _makelink = function( | local _makelink = function(id, val, n, qid) --validate values and create a link | ||
local | local link = mw.html.create('span'):addClass('uid') | ||
if n==1 and id.prefix then --show prefix on primary value | |||
link:wikitext(id.prefix .. ': ') | |||
if | |||
end | end | ||
local valid_value = false | local valid_value = false | ||
if | if id.customlink then -- use function to validate and generate link | ||
local label = | local label = n>1 and n | ||
local newlink= require(config.auxiliary)[ | local newlink = require(config.auxiliary)[id.customlink](val.id, label) | ||
if newlink then | if newlink then | ||
link | link:wikitext(newlink) | ||
valid_value = true | valid_value = true | ||
end | end | ||
else | else | ||
if | if id.pattern then -- check pattern to determine validity | ||
valid_value = string.match(val.id,'^'.. | valid_value = string.match(val.id, '^' .. id.pattern .. '$') | ||
elseif | elseif id.patterns then -- check multiple patterns to determine validity | ||
for _,pattern in ipairs( | for _, pattern in ipairs(id.patterns) do | ||
valid_value = val.id:match('^'..pattern..'$') | valid_value = val.id:match('^' .. pattern .. '$') | ||
if valid_value then break end | if valid_value then break end | ||
end | end | ||
elseif | elseif id.valid then -- use function to determine validity | ||
valid_value = require(config.auxiliary)[ | valid_value = require(config.auxiliary)[id.valid](val.id) | ||
else -- no validation possible | else -- no validation possible | ||
valid_value = val.id | valid_value = val.id | ||
end | end | ||
if valid_value then | if valid_value then | ||
local label = id.label | |||
if not label or n>1 then | |||
label = tostring(n) | |||
end | |||
local newlink | local newlink | ||
if id.link then | |||
if | |||
valid_value = valid_value:gsub('%%', '%%%%') | valid_value = valid_value:gsub('%%', '%%%%') | ||
newlink = '[' .. mw.ustring.gsub( | newlink = '[' .. mw.ustring.gsub(id.link, '%$1', valid_value) .. ' ' .. label .. ']' | ||
else | else | ||
newlink = valid_value | newlink = valid_value | ||
end | end | ||
link | link:wikitext(tooltip(newlink, val.name)) | ||
end | end | ||
end | end | ||
if valid_value then | if valid_value then | ||
local cat = id.category and string.format(config.i18n.cat, id.category) | |||
link:wikitext(addCat(cat)) | |||
else | else | ||
local wdlink = qid and wikilink(':wikidata:' .. qid .. '#P' .. id.property) or '' | |||
local wdlink = qid and ' | local _, name = p.getname(id.property) | ||
local tooltip = string.format( | local tooltip = string.format( | ||
config.i18n.idnotvalid, | config.i18n.idnotvalid, | ||
name, | |||
val.id | 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 | ||
end | end | ||
return | return links | ||
end | end | ||
--[[ | --[[==================================]] | ||
--[[ | --[[ Main ]] | ||
--[[ | --[[==================================]] | ||
p.authorityControl = function(frame) | |||
local function | local resolveQID = function(qid) | ||
if qid then | if qid then | ||
qid = 'Q'..mw.ustring.gsub(qid, '^[Qq]', '') | qid = 'Q' .. mw.ustring.gsub(qid, '^[Qq]', '') | ||
if mw.wikibase.isValidEntityId(qid) and mw.wikibase.entityExists(qid) then | if mw.wikibase.isValidEntityId(qid) and mw.wikibase.entityExists(qid) then | ||
local sitelink = mw.wikibase.getSitelink(qid) | local sitelink = mw.wikibase.getSitelink(qid) | ||
Line 152: | Line 173: | ||
end | end | ||
return mw.wikibase.getEntity(qid).id | return mw.wikibase.getEntity(qid).id | ||
end end end | |||
local conf = config.config | local conf = config.config | ||
local parentArgs = frame:getParent().args | local parentArgs = frame:getParent().args | ||
local auxCats = '' | local auxCats = '' | ||
local rct = false -- boolean to track if there are any links to be returned | local rct = false -- boolean to track if there are any links to be returned | ||
local qid,topic | local qid, topic | ||
if namespace==0 then | |||
if namespace == 0 then | |||
qid = mw.wikibase.getEntityIdForCurrentPage() | qid = mw.wikibase.getEntityIdForCurrentPage() | ||
end | end | ||
if qid then -- article is connected to Wikidata item | if qid then -- article is connected to a Wikidata item | ||
if parentArgs.qid and (resolveQID(parentArgs.qid) ~= qid) then -- non-matching qid parameter | if parentArgs.qid and (resolveQID(parentArgs.qid) ~= qid) then -- non-matching qid parameter | ||
auxCats = auxCats .. needsAttention('D') | auxCats = auxCats .. needsAttention('D') | ||
Line 190: | Line 191: | ||
topic = mw.wikibase.getLabel(qid) | topic = mw.wikibase.getLabel(qid) | ||
if topic then | 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 | if mw.ustring.lower(title.subpageText)==mw.ustring.lower(topic) then -- suppress topic display if subpagename equals topic up to case change | ||
topic = nil | topic = nil | ||
end | end | ||
if topic and mw.wikibase.getSitelink(qid) then -- make wikilink to article | if topic and mw.wikibase.getSitelink(qid) then -- make wikilink to article | ||
topic = | topic = wikilink(mw.wikibase.getSitelink(qid), topic) | ||
end | end | ||
else | else | ||
Line 206: | Line 207: | ||
if parentArgs.additional=='auto' and qid then -- check P527 for parts to add additional qids | if parentArgs.additional=='auto' and qid then -- check P527 for parts to add additional qids | ||
local checkparts = function(property) | local checkparts = function(property) | ||
local parts = mw.wikibase.getBestStatements(qid,property) | local parts = mw.wikibase.getBestStatements(qid, property) | ||
if parts then | if parts then | ||
for _,part in ipairs(parts) do | for _, part in ipairs(parts) do | ||
if part.mainsnak.datavalue and part.mainsnak.datavalue.value.id then | if part.mainsnak.datavalue and part.mainsnak.datavalue.value.id then | ||
local resolvedqid = resolveQID(part.mainsnak.datavalue.value.id) | local resolvedqid = resolveQID(part.mainsnak.datavalue.value.id) | ||
Line 214: | Line 215: | ||
table.insert(qids,resolvedqid) | table.insert(qids,resolvedqid) | ||
end end end end end | end end end end end | ||
for _,part in ipairs(config.auto_additional) do | for _, part in ipairs(config.auto_additional) do | ||
checkparts('P'.. | checkparts('P' .. part) | ||
end | end | ||
elseif parentArgs.additional and parentArgs.additional ~= '' then | elseif parentArgs.additional and parentArgs.additional~='' then | ||
for _,v in ipairs(mw.text.split(parentArgs.additional, | for _, v in ipairs(mw.text.split(parentArgs.additional, '%s*,%s*')) do | ||
v = resolveQID(v) | v = resolveQID(v) | ||
if v then | if v then | ||
if v == qid then -- duplicate of qid parameter | if v==qid then -- duplicate of qid parameter | ||
auxCats = auxCats .. needsAttention('R') | auxCats = auxCats .. needsAttention('R') | ||
end | end | ||
table.insert(qids,v) | table.insert(qids, v) | ||
else -- invalid QID specified | else -- invalid QID specified | ||
auxCats = auxCats .. needsAttention('A') | auxCats = auxCats .. needsAttention('A') | ||
Line 231: | Line 232: | ||
end | end | ||
local numsections = 0 | |||
for _, _ in ipairs(config.sections) do -- count number of regular sections | |||
numsections = numsections + 1 | |||
end | |||
local sections = {} | local sections = {} | ||
for _ = 1, #qids+numsections do | |||
table.insert(sections, {}) | |||
end | |||
for _ = 1,#qids+numsections do table.insert(sections,{}) | |||
-- check which identifiers to show/suppress in template | -- check which identifiers to show/suppress in template | ||
local show = {} | local show, show_all_unsuppressed = {}, true | ||
local | local stripP = function(pid) --strip P from property number | ||
if pid:match('^[Pp]%d+$') then | |||
if pid:match( | pid = mw.ustring.gsub(pid, '[Pp]', '') | ||
pid = mw.ustring.gsub(pid,'[Pp]','') | |||
end | end | ||
if pid:match( | if pid:match('^%d+$') then | ||
return tonumber(pid) | return tonumber(pid) | ||
end | end | ||
end | end | ||
local function | local addshowlist = function(list) | ||
if list and list ~= '' then | if list and list~='' then | ||
for _,v in ipairs(mw.text.split(string.lower(list), | for _, v in ipairs(mw.text.split(string.lower(list), '%s*,%s*')) do | ||
local vprop = stripP(v) | local vprop = stripP(v) | ||
if vprop then -- e.g. show=P214 to show one particular property | if vprop then -- e.g. show=P214 to show one particular property | ||
Line 257: | Line 259: | ||
else -- e.g. show=arts to use whitelist | else -- e.g. show=arts to use whitelist | ||
if config.whitelists[v] then | if config.whitelists[v] then | ||
for _,w in ipairs(config.whitelists[v].properties) do | for _, w in ipairs(config.whitelists[v].properties) do | ||
show[w] = true | show[w] = true | ||
end end end end | |||
show_all_unsuppressed = false | |||
end end | |||
addshowlist(frame.args.show) -- check show= parameter on wrapper template | addshowlist(frame.args.show) -- check show= parameter on wrapper template | ||
addshowlist(parentArgs.show | addshowlist(parentArgs.show) -- check show parameter on article | ||
addshowlist(parentArgs.country) -- check country parameter on article | |||
if parentArgs.suppress then | if parentArgs.suppress then | ||
local suppresslist = mw.text.split(parentArgs.suppress, | local suppresslist = mw.text.split(parentArgs.suppress, '%s*,%s*') -- split parameter by comma | ||
for _,v in ipairs(suppresslist) do | for _, v in ipairs(suppresslist) do | ||
v = stripP | v = stripP(v) | ||
if v then | if v then | ||
show[v] = false | show[v] = false | ||
auxCats = auxCats .. | auxCats = auxCats .. wikilink(config.i18n.category .. ':' .. config.i18n.suppressedcat) | ||
else | else | ||
auxCats = auxCats .. needsAttention('P') | auxCats = auxCats .. needsAttention('P') | ||
Line 281: | Line 280: | ||
end | end | ||
local function | local makeSections = function(qid, addit) | ||
for _, id in ipairs(conf) do | |||
if id.suppressedbyproperty then | |||
for _, property in ipairs(id.suppressedbyproperty) do | |||
if | if show[property]=='used' then -- property is in use | ||
show[id.property] = false -- suppressed by another property | |||
if | |||
end | end | ||
end | end | ||
end | end | ||
if show[id.property]==nil then | |||
show[id.property] = show_all_unsuppressed | |||
if | |||
end | end | ||
if | if show[id.property] then | ||
local | local links = _makelinks(id, qid) | ||
if links then | |||
table.insert( | |||
sections[addit or id.section], | |||
links | |||
) | |||
show[id.property] = 'used' | |||
if | |||
table.insert(sections[addit or | |||
rct = true | rct = true | ||
end end end end | |||
local pencil = function(qid) | |||
if qid then | |||
return require('Module:EditAtWikidata')._showMessage{ | |||
local function | pid = 'identifiers', | ||
if | qid = qid | ||
} | |||
else | |||
return '' | return '' | ||
end | end | ||
end | end | ||
makeSections(qid,false) | makeSections(qid, false) | ||
for c = 1,#qids do | for c = 1, #qids do | ||
makeSections(qids[c],numsections+c) | makeSections(qids[c], numsections+c) | ||
end | end | ||
--configure Navbox | --configure Navbox | ||
local outString = '' | local outString = '' | ||
if rct | if rct then -- there is at least one link to display | ||
local Navbox = require('Module:Navbox') | local Navbox = require('Module:Navbox') | ||
local sect,lastsect = 0,0 | local sect, lastsect = 0, 0 | ||
local navboxArgs = { | local navboxArgs = { | ||
name = 'Authority control', | name = 'Authority control', | ||
Line 376: | Line 330: | ||
navbar = 'off' | navbar = 'off' | ||
} | } | ||
for c=1,numsections+#qids do | for c = 1, numsections+#qids do | ||
if #sections[c] | if #sections[c]>0 then -- section is non-empty | ||
sect = sect + 1 | sect = sect + 1 | ||
lastsect = c | lastsect = c | ||
local sectname | local sectname | ||
if c <= numsections then -- regular section | if c<=numsections then -- regular section | ||
sectname = config.sections[c].name | sectname = config.sections[c].name | ||
else -- section from additional qid | else -- section from additional qid | ||
local qid = qids[c-numsections] | local qid = qids[c-numsections] | ||
sectname = wikilink(qid | 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 | end | ||
navboxArgs['group' .. c] = sectname | navboxArgs['group' .. c] = sectname | ||
local list = mw.html.create('ul') | |||
for _, link in ipairs(sections[c]) do | |||
list:node(link) | |||
end | end | ||
navboxArgs['list' .. c] = tostring(list) | |||
end | end | ||
end | end | ||
if topic then -- display in expanded form with topic | if topic then -- display in expanded form with topic | ||
navboxArgs.title = config.i18n.aclink .. ' – ' .. topic .. pencil(qid) | navboxArgs.title = config.i18n.aclink .. ' – ' .. topic .. pencil(qid) | ||
elseif sect == 1 then -- special display when only one section | elseif sect==1 then -- special display when only one section | ||
if lastsect <= numsections then | if lastsect<=numsections then | ||
if config.sections[lastsect].hidelabelwhenalone then -- no special label when only general or other IDs are present | 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) | navboxArgs['group' .. lastsect] = config.i18n.aclink .. pencil(qid) | ||
Line 437: | Line 395: | ||
--out | --out | ||
outString = outString..auxCats | outString = outString .. auxCats | ||
if namespace ~= 0 then | 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.Articles .. ')([^%|%]]+)%|?[^%|%]]*(%]%])','%1:%2%3%4') | ||
outString = mw.ustring.gsub(outString,'(%[%[)(' .. config.i18n.category .. ':' .. config.i18n.All_articles .. ')([^%|%]]+)%|?[^%|%]]*(%]%])','%1:%2%3%4') | outString = mw.ustring.gsub(outString, '(%[%[)(' .. config.i18n.category .. ':' .. config.i18n.All_articles .. ')([^%|%]]+)%|?[^%|%]]*(%]%])','%1:%2%3%4') | ||
end | end | ||
local check = require('Module:Check for unknown parameters')._check | local check = require('Module:Check for unknown parameters')._check | ||
local sortkey | local sortkey | ||
if namespace == 0 then | if namespace==0 then | ||
sortkey = '*' .. title.text | sortkey = '*' .. title.text | ||
else | else | ||
Line 450: | Line 408: | ||
end | end | ||
outString = outString .. check({ | outString = outString .. check({ | ||
['unknown'] = | ['unknown'] = wikilink(config.i18n.category .. ':' .. config.i18n.pageswithparams, sortkey), | ||
['preview'] = config.i18n.previewwarning, 'show', 'country', 'suppress', 'additional', 'qid', 'state' | ['preview'] = config.i18n.previewwarning, 'show', 'country', 'suppress', 'additional', 'qid', 'state' | ||
}, parentArgs) | }, parentArgs) | ||
Line 456: | Line 414: | ||
end | end | ||
p.makelink = function( | p.makelink = function(id, qid) | ||
return | return _makelinks(id, qid) | ||
end | end | ||
return p | return p |
Latest revision as of 11:42, 2 September 2024
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
Script error: The function "docConfTable" does not exist.
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