Module:Authority control: Difference between revisions
From The Goon Show Depository
m (1 revision imported) |
en>MSGJ m (further code simplification, do not add suppressed ids from arts to tracking category) |
||
Line 27: | Line 27: | ||
local function getIdsFromWikidata(itemId,property) | local function getIdsFromWikidata(itemId,property) | ||
local ids = {} | local ids = {} | ||
if not mw.wikibase then | if not mw.wikibase or not itemId then | ||
return ids | return ids | ||
end | end | ||
Line 65: | Line 65: | ||
end | end | ||
if conf.link then | if conf.link then | ||
valid_value = valid_value:gsub('%%', '%%%%') | |||
link = '[' .. mw.ustring.gsub(conf.link,'%$1',valid_value) .. ' ' .. label .. ']' | link = '[' .. mw.ustring.gsub(conf.link,'%$1',valid_value) .. ' ' .. label .. ']' | ||
else | else | ||
Line 76: | Line 77: | ||
link = '<span class="uid">'..link..'</span>' | link = '<span class="uid">'..link..'</span>' | ||
else | else | ||
local faultyCat = 'Articles with faulty '..(conf.errorcat or conf. | local faultyCat = 'Articles with faulty '..(conf.errorcat or conf.category or conf[1])..' identifiers' | ||
link = '<span class="error">The '..conf[1]..' id '..val..' is not valid.</span>'..addCat(faultyCat) | link = '<span class="error">The '..conf[1]..' id '..val..' is not valid.</span>'..addCat(faultyCat) | ||
end | end | ||
Line 86: | Line 87: | ||
--[[==========================================================================]] | --[[==========================================================================]] | ||
function p.authorityControl( frame ) | function p.authorityControl(frame) | ||
local config = require("Module:Authority control/config") | local config = require("Module:Authority control/config") | ||
local conf = config.config | local conf = config.config | ||
local sectionOrder = config.sectionOrder | |||
local aliases = config.aliases | local aliases = config.aliases | ||
local deprecated = config.deprecated | local deprecated = config.deprecated | ||
Line 94: | Line 96: | ||
local parentArgs = frame:getParent().args --WD IDs added here later | local parentArgs = frame:getParent().args --WD IDs added here later | ||
local iParentArgs = 0 --count original/manual parent args only later | local iParentArgs = 0 --count original/manual parent args only later | ||
local | local suppressedIdCount = 0 | ||
local iMatches = 0 | |||
local auxCats = '' | |||
local rct = 0 | |||
local sections = {{},{},{},{},{},{},{},{}} | |||
local | |||
local | |||
local | |||
local | |||
--redirect aliases to proper parameter names | --redirect aliases to proper parameter names | ||
Line 118: | Line 116: | ||
parentArgs[param] = parentArgs[dep] | parentArgs[param] = parentArgs[dep] | ||
if namespace == 0 then | if namespace == 0 then | ||
auxCats = auxCats .. '[[Category:Articles with deprecated authority control identifiers|'..dep..']]' | |||
end | end | ||
end | end | ||
Line 124: | Line 122: | ||
--use QID= parameter for testing/example purposes only | --use QID= parameter for testing/example purposes only | ||
local itemId | local itemId | ||
local function resolveQID(qid) | |||
if qid then | if qid then | ||
itemId = 'Q'..mw.ustring.gsub(qid, '^[Qq]', '') | itemId = 'Q'..mw.ustring.gsub(qid, '^[Qq]', '') | ||
itemId = resolveEntity._id(itemId) --nil if unresolvable | itemId = resolveEntity._id(itemId) --nil if unresolvable | ||
end | end | ||
return qid | |||
end | |||
if namespace ~= 0 then | |||
local qid = parentArgs['qid'] or parentArgs['QID'] | |||
qid = resolveQID(qid) | |||
elseif mw.wikibase then | elseif mw.wikibase then | ||
itemId = mw.wikibase.getEntityIdForCurrentPage() | itemId = mw.wikibase.getEntityIdForCurrentPage() | ||
end | end | ||
local tval = {} | local tval = {} | ||
Line 193: | Line 149: | ||
end | end | ||
for _, params in ipairs(conf) do | for _, params in ipairs(conf) do | ||
tval[params.property] = getIdsFromWikidata(itemId, 'P' .. params.property) -- setup table for values with property number as key | |||
local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]] | local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]] | ||
if val == '' then | |||
if val then | if tval[params.property][1] and (namespace == 0 or testcases) then | ||
if | suppressedIdCount = suppressedIdCount + 1 | ||
if parentArgs['arts'] ~= 'arts' then | |||
auxCats = auxCats .. '[[Category:Articles with suppressed authority control identifiers|'..params[1]..']]' | |||
table.insert( | end | ||
end | |||
tval[params.property] = false -- indicates the identifier is suppressed | |||
elseif val then -- add local parameter to wikidata | |||
iParentArgs = iParentArgs + 1 | |||
local bnew = true | |||
for _, w in pairs(tval[params.property]) do | |||
if val == w then | |||
bnew = false | |||
end | |||
end | |||
if bnew then -- add new value to table | |||
if tval[params.property][1] then | |||
auxCats = auxCats .. '[[Category:Pages using authority control with parameters different on Wikidata|'..params[1]..']]' | |||
end | |||
table.insert(tval[params.property],val) | |||
else | |||
iMatches = iMatches+1 | |||
end | end | ||
end | end | ||
local suppress=false | |||
if params.suppressedbyproperty then | if params.suppressedbyproperty then | ||
for _,sc in ipairs(params.suppressedbyproperty) do | for _,sc in ipairs(params.suppressedbyproperty) do | ||
Line 213: | Line 184: | ||
end | end | ||
end | end | ||
if not | if not tval[params.property] == false and not suppress then | ||
local tlinks = {} -- setup table for links | local tlinks = {} -- setup table for links | ||
local nextIdVal = 1 | local nextIdVal = 1 | ||
for _, val in | for _,val in ipairs(tval[params.property]) do | ||
local link = makelink(params,val,nextIdVal) | |||
local cat = params.category or params[1] | |||
if link then -- add category unless link==false | |||
link = link .. getCatForId(cat) | |||
end | end | ||
table.insert(tlinks,link) | |||
nextIdVal = nextIdVal + 1 | |||
end | end | ||
if tval[params.property][1] then -- assemble | if tval[params.property][1] then -- assemble | ||
Line 252: | Line 213: | ||
rct = rct + 1 | rct = rct + 1 | ||
if tval[params.property][2] then | if tval[params.property][2] then | ||
auxCats = auxCats .. getCatForId('multiple') | |||
end | end | ||
end | end | ||
end | |||
end | |||
if iMatches > 0 and iMatches == iParentArgs then | |||
auxCats = auxCats .. '[[Category:Pages using authority control with parameters all matching Wikidata]]' | |||
end | |||
if parentArgs['arts'] == 'arts' and suppressedIdCount > 0 then | |||
if namespace == 0 or testcases then | |||
local s = 's' | |||
if suppressedIdCount == 1 then s = '' end | |||
auxCats = auxCats .. addCat('ACArt with '..suppressedIdCount..' suppressed element'..s) | |||
end | end | ||
end | end | ||
Line 312: | Line 283: | ||
if rct == 0 or rct >= 25 then | if rct == 0 or rct >= 25 then | ||
if namespace == 0 or testcases then | if namespace == 0 or testcases then | ||
auxCats = auxCats .. addCat('AC with '..rct..' elements') | |||
end | end | ||
end | end | ||
Line 324: | Line 294: | ||
else sCat = 'AC using state parameter: other' | else sCat = 'AC using state parameter: other' | ||
end | end | ||
auxCats = auxCats .. addCat(sCat) | |||
end | end | ||
end | end | ||
if testcases then | if testcases then | ||
auxCats = mw.ustring.gsub(auxCats, '(%[%[)(Category)', '%1:%2') --for easier checking | auxCats = mw.ustring.gsub(auxCats, '(%[%[)(Category)', '%1:%2') --for easier checking | ||
Line 368: | Line 336: | ||
local appearsAs = makelink(conf,conf.example,1) | local appearsAs = makelink(conf,conf.example,1) | ||
local link = conf.idlink or param..' (identifier)' | local link = conf.idlink or param..' (identifier)' | ||
local category = conf. | local category = conf.category or param | ||
local args = { id = 'f', pid } | local args = { id = 'f', pid } | ||
local wpl = frame:expandTemplate{ title = 'Wikidata property link', args = args } | local wpl = frame:expandTemplate{ title = 'Wikidata property link', args = args } |
Revision as of 08:33, 14 December 2022
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 title = mw.title.getCurrentTitle()
local namespace = title.namespace
local testcases = (string.sub(title.subpageText,1,9) == 'testcases')
local function addCat(cat)
if cat and cat ~= '' then
local redlinkcat = ''
if testcases == false and mw.title.new(cat, 14).exists == false then
redlinkcat = '[[Category:Pages with red-linked authority control categories]]'
end
return '[[Category:'..cat..']]'..redlinkcat
else
return ''
end
end
local function getCatForId(id)
local cat = ''
if namespace == 0 then
cat = 'Articles with '..id..' identifiers'
end
return addCat(cat)
end
local function getIdsFromWikidata(itemId,property)
local ids = {}
if not mw.wikibase or not itemId then
return ids
end
local statements = mw.wikibase.getBestStatements( itemId, property )
if statements then
for _, statement in ipairs( statements ) do
if statement.mainsnak.datavalue then
table.insert( ids, statement.mainsnak.datavalue.value )
end
end
end
return ids
end
local function makelink(conf,val,nextid) --validate values and create a link
local link
if conf.link2 then -- use function to validate and generate link
link = conf.link2(val)
else
local valid_value
if conf.pattern then -- use pattern to determine validity if defined
valid_value = val:match(conf.pattern)
elseif conf.patterns then
for i = 1,#conf.patterns do
valid_value = val:match(conf.patterns[i])
if valid_value then break end
end
elseif conf.valid then -- otherwise use function to determine validity
valid_value = conf.valid(val)
else -- no validation possible
valid_value = val
end
if valid_value then
local label = conf.label
if not label or nextid>1 then
label = tostring(nextid)
end
if conf.link then
valid_value = valid_value:gsub('%%', '%%%%')
link = '[' .. mw.ustring.gsub(conf.link,'%$1',valid_value) .. ' ' .. label .. ']'
else
link = valid_value
end
else
link = false
end
end
if link then
link = '<span class="uid">'..link..'</span>'
else
local faultyCat = 'Articles with faulty '..(conf.errorcat or conf.category or conf[1])..' identifiers'
link = '<span class="error">The '..conf[1]..' id '..val..' is not valid.</span>'..addCat(faultyCat)
end
return link
end
--[[==========================================================================]]
--[[ Main ]]
--[[==========================================================================]]
function p.authorityControl(frame)
local config = require("Module:Authority control/config")
local conf = config.config
local sectionOrder = config.sectionOrder
local aliases = config.aliases
local deprecated = config.deprecated
local resolveEntity = require( 'Module:ResolveEntityId' )
local parentArgs = frame:getParent().args --WD IDs added here later
local iParentArgs = 0 --count original/manual parent args only later
local suppressedIdCount = 0
local iMatches = 0
local auxCats = ''
local rct = 0
local sections = {{},{},{},{},{},{},{},{}}
--redirect aliases to proper parameter names
for _, a in pairs(aliases) do
local alias, param = a[1], a[2]
if (parentArgs[param] == nil or parentArgs[param] == '') and parentArgs[alias] then
parentArgs[param] = parentArgs[alias]
end
end
--redirect deprecated parameters to proper parameter names, and assign tracking cat
for _, d in pairs( deprecated ) do
local dep, param = d[1], d[2]
if (parentArgs[param] == nil or parentArgs[param] == '') and parentArgs[dep] then
parentArgs[param] = parentArgs[dep]
if namespace == 0 then
auxCats = auxCats .. '[[Category:Articles with deprecated authority control identifiers|'..dep..']]'
end
end
end
--use QID= parameter for testing/example purposes only
local itemId
local function resolveQID(qid)
if qid then
itemId = 'Q'..mw.ustring.gsub(qid, '^[Qq]', '')
itemId = resolveEntity._id(itemId) --nil if unresolvable
end
return qid
end
if namespace ~= 0 then
local qid = parentArgs['qid'] or parentArgs['QID']
qid = resolveQID(qid)
elseif mw.wikibase then
itemId = mw.wikibase.getEntityIdForCurrentPage()
end
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
end
end
return used
end
for _, params in ipairs(conf) do
tval[params.property] = getIdsFromWikidata(itemId, 'P' .. params.property) -- setup table for values with property number as key
local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]]
if val == '' then
if tval[params.property][1] and (namespace == 0 or testcases) then
suppressedIdCount = suppressedIdCount + 1
if parentArgs['arts'] ~= 'arts' then
auxCats = auxCats .. '[[Category:Articles with suppressed authority control identifiers|'..params[1]..']]'
end
end
tval[params.property] = false -- indicates the identifier is suppressed
elseif val then -- add local parameter to wikidata
iParentArgs = iParentArgs + 1
local bnew = true
for _, w in pairs(tval[params.property]) do
if val == w then
bnew = false
end
end
if bnew then -- add new value to table
if tval[params.property][1] then
auxCats = auxCats .. '[[Category:Pages using authority control with parameters different on Wikidata|'..params[1]..']]'
end
table.insert(tval[params.property],val)
else
iMatches = iMatches+1
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 not tval[params.property] == false and not suppress then
local tlinks = {} -- setup table for links
local nextIdVal = 1
for _,val in ipairs(tval[params.property]) do
local link = makelink(params,val,nextIdVal)
local cat = params.category or params[1]
if link then -- add category unless link==false
link = link .. getCatForId(cat)
end
table.insert(tlinks,link)
nextIdVal = nextIdVal + 1
end
if tval[params.property][1] then -- assemble
local row = ''
if params.prefix then
row = row..'*'..params.prefix
end
for i, l in ipairs(tlinks) do
if i==1 and not params.prefix then
row = row..'*'
else
row = row..'\n**'
end
row = row .. l
end
row = row..'\n'
table.insert(sections[params.section],row)
rct = rct + 1
if tval[params.property][2] then
auxCats = auxCats .. getCatForId('multiple')
end
end
end
end
if iMatches > 0 and iMatches == iParentArgs then
auxCats = auxCats .. '[[Category:Pages using authority control with parameters all matching Wikidata]]'
end
if parentArgs['arts'] == 'arts' and suppressedIdCount > 0 then
if namespace == 0 or testcases then
local s = 's'
if suppressedIdCount == 1 then s = '' end
auxCats = auxCats .. addCat('ACArt with '..suppressedIdCount..' suppressed element'..s)
end
end
--configure Navbox
local outString = ''
local extrap = true
local extra = parentArgs.extralist
if extra == nil or extra == '' then
extrap = false
end
if rct > 0 or extrap then
local Navbox = require('Module:Navbox')
local sectionID = 1
local args = { pid = 'identifiers' } -- #target the list of identifiers
if testcases and itemId then args.qid = itemId end --expensive
local pencil = require('Module:EditAtWikidata')._showMessage(args)
local navboxArgs = {
name = 'Authority control',
navboxclass = 'authority-control',
bodyclass = 'hlist',
state = parentArgs.state or 'autocollapse',
navbar = 'off'
}
for c, sectName in ipairs(sectionOrder) do
if #sections[c] ~= 0 then
navboxArgs['group'..sectionID] = sectName
navboxArgs['list'..sectionID] = table.concat(sections[c])
sectionID = sectionID + 1
end
end
if extrap then
if parentArgs.extragroup then
navboxArgs['group'..sectionID] = parentArgs.extragroup
else
navboxArgs['group'..sectionID] = 'Additional'
end
navboxArgs['list'..sectionID] = extra
sectionID = sectionID + 1
end
if navboxArgs.list2 then
navboxArgs.title = '[[Help:Authority control|Authority control]]'..pencil
else
local sect = navboxArgs.group1
if sect == 'General' or sect == 'Other' or sect == 'Additional' then
-- Just say "Authority control" with no label if only general or only other IDs are present
-- since "general" is redundant and "other" is silly when there's nothing to contrast it with
navboxArgs.group1 = '[[Help:Authority control|Authority control]]'..pencil
else
navboxArgs.group1 = '[[Help:Authority control|Authority control: '..sect..']] '..pencil
end
end
outString = Navbox._navbox(navboxArgs)
end
--auxCats
if rct == 0 or rct >= 25 then
if namespace == 0 or testcases then
auxCats = auxCats .. addCat('AC with '..rct..' elements')
end
end
if parentArgs.state then
if namespace == 0 or testcases then
local sCat
if parentArgs.state == 'collapsed' then sCat = 'AC using state parameter: collapsed'
elseif parentArgs.state == 'expanded' then sCat = 'AC using state parameter: expanded'
elseif parentArgs.state == 'autocollapse' then sCat = 'AC using state parameter: autocollapse'
else sCat = 'AC using state parameter: other'
end
auxCats = auxCats .. addCat(sCat)
end
end
if testcases then
auxCats = mw.ustring.gsub(auxCats, '(%[%[)(Category)', '%1:%2') --for easier checking
end
--out
outString = outString..auxCats
if namespace ~= 0 then
outString = mw.ustring.gsub(outString, '(%[%[)(Category:Articles)', '%1:%2') --by definition
end
return outString
end
-- Creates a human-readable standalone wikitable version of conf, and tracking categories with page counts, for use in the documentation
function p.docConfTable(frame)
local wikiTable = '<table class="wikitable sortable">'..
'<tr><th rowspan=2>Parameter</th>'..
'<th rowspan=2>Section</th>'..
'<th rowspan=2>Appears as</th>'..
'<th rowspan=2 data-sort-type=number>Wikidata property</th>'..
'<th colspan=2>Tracking categories and page counts</th></tr>'..
'<tr><th>[[:Category:Articles with authority control information|Articles]]</th>'..
'<th>[[:Category:Articles with faulty authority control information|Faulty IDs]]</th></tr>'
local lang = mw.getContentLanguage()
local a, f, P = 0, 0, 0 --cumulative sums
local config = require("Module:Authority control/config")
local conf = config.config
local sectionOrder = config.sectionOrder
local function checkcat(category,label)
local ret='[[:Category:'..category..'|'..label..']]'
if mw.title.new(category, 14).exists == false then
ret = ret..' <span class="plainlinks" style="font-size:85%;">[['..tostring(mw.uri.fullUrl('Category:'..category,'action=edit&preload=Template:Authority_control/preload'))..' create]]</span>'
end
return ret
end
for _, conf in pairs(conf) do
local param, pid, section = conf[1], conf.property, sectionOrder[conf.section]
local appearsAs = makelink(conf,conf.example,1)
local link = conf.idlink or param..' (identifier)'
local category = conf.category or param
local args = { id = 'f', pid }
local wpl = frame:expandTemplate{ title = 'Wikidata property link', args = args }
local articleCat = 'Articles with '..category..' identifiers'
local faultyCat = 'Articles with faulty '.. (conf.errorcat or category) ..' identifiers'
local articleCount = lang:formatNum( mw.site.stats.pagesInCategory(articleCat, 'pages') )
local faultyCount = lang:formatNum( mw.site.stats.pagesInCategory(faultyCat, 'pages') )
P = P + 1 --property count
a = a + lang:parseFormattedNumber(articleCount)
f = f + lang:parseFormattedNumber(faultyCount)
wikiTable = wikiTable..'<tr><td>[['..link..'|'..param..']]</td>'..
'<td>'..section..'</td>'..
'<td>'..appearsAs..'</td>'..
'<td data-sort-value='..pid..'>'..wpl..'</td>'..
'<td style="text-align: right;">'..checkcat(articleCat,articleCount)..'</td>'..
'<td style="text-align: right;">'..checkcat(faultyCat,faultyCount)..'</td></tr>'
end
wikiTable = wikiTable..'<tr><th style="text-align: right;" colspan=3>Totals</th>'..
'<th style="text-align: right;">'..lang:formatNum(P)..'</th>'..
'<th style="text-align: right;">'..lang:formatNum(a)..'</th>'..
'<th style="text-align: right;">'..lang:formatNum(f)..'</th></tr></table>'
return require('Module:Suppress categories').main(wikiTable)
end
return p