Module:Authority control
Jump to navigation
Jump to search
![]() | This Lua module is used on approximately 2,010,000 pages, or roughly 17747% 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 depends on the following other modules: |
This module contains the code of the {{Authority control}} and {{Pages with authority control identifiers}} templates.
Please see Template:Authority control/doc.
require('strict') local config = mw.loadData('Module:Authority control/config') local p = {} local title = mw.title.getCurrentTitle() local namespace = title.namespace local testcases = (string.sub(title.subpageText,1,9) == 'testcases') local function needsAttention(sortkey) return '[[Category:Pages with authority control identifiers needing attention|' .. 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 = '[[Category:'..cat..'|' .. sortkey .. title.text .. ']]' else cat = '[[Category:'..cat..']]' end cat = cat .. redlinkcat return cat else return '' end end local function getCatForId(id,faulty) local cat = 'Articles with ' if faulty then cat = cat .. 'faulty ' end cat = cat .. id .. ' identifiers' 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 function makelink(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 newlink = require('Module:Authority control/auxiliary')[conf.customlink](val.id) 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('Module:Authority control/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 '' link = link .. '[[File:345-409 Ambox warning centered.svg|20px|frameless|link=' .. wdlink .. '|The ' .. conf[1] .. ' id ' .. val.id .. ' is not valid.]]' if conf.errorcat then link = link .. addCat(conf.errorcat) else link = link .. getCatForId(conf.category or conf[1],true) end link = link .. addCat('All articles with faulty authority control information',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 return qid 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 Wikidata item if parentArgs.qid and (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 and (mw.ustring.lower(title.subpageText) == mw.ustring.lower(topic)) then -- suppress topic display if subpagename equals topic up to case change topic = nil end elseif 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 and parentArgs.additional ~= '' then for _,v in ipairs(mw.text.split(parentArgs.additional,"%s*,%s*")) do v = resolveQID(v) if v == qid then -- duplicate of qid parameter auxCats = auxCats .. needsAttention('R') end table.insert(qids,v) end end local sections = {} local numsections = 0 for _,_ in ipairs(config.sectionNames) 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 pid = tonumber(pid) end return pid end local function addshowlist(list) if list and list ~= '' then for _,v in ipairs(mw.text.split(string.lower(list),"%s*,%s*")) do v = stripP(v) if type(v) == 'string' then -- 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 else -- e.g. show=214 to show one particular property show[v] = true 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)) show[v] = false auxCats = auxCats .. '[[Category:Articles with suppressed authority control identifiers]]' 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 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 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 '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.sectionNames[c] else -- section from additional qid sectname = mw.wikibase.getLabel(qids[c-numsections]) .. pencil(qids[c-numsections]) end navboxArgs['group' .. c] = sectname navboxArgs['list' .. c] = table.concat(sections[c]) end end local aclink = '[[Help:Authority control|Authority control]]' if qslink ~= '' then qslink = '<span class="qs autoconfirmed-show"> [[File:Commons to Wikidata QuickStatements.svg|20px|link=https://quickstatements.toolforge.org/#/v1=' .. qslink .. '|Add values to Wikidata.]]</span>' end if topic then -- display in expanded form with topic navboxArgs.title = aclink .. ' – ' .. topic .. pencil(qid) .. qslink elseif sect == 1 then -- special display when only one section if lastsect == 1 or lastsect == 8 then -- no special label when only general or other IDs are present navboxArgs['group' .. lastsect] = aclink .. pencil(qid) .. qslink elseif lastsect <= numsections then -- other regular section navboxArgs['group' .. lastsect] = aclink .. ': ' .. config.sectionNames[lastsect] .. pencil(qid) .. qslink else -- section from additional qid navboxArgs['group' .. lastsect] = aclink .. ': ' .. navboxArgs['group' .. lastsect] .. qslink end else -- add title to navbox navboxArgs.title = aclink .. pencil(qid) .. qslink end outString = Navbox._navbox(navboxArgs) end if parentArgs.state then if (parentArgs.state ~= 'collapsed') and (parentArgs.state ~= 'expanded') and (parentArgs.state ~= 'autocollapse') then --invalid state parameter auxCats = auxCats .. needsAttention('S') 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%3%4') outString = mw.ustring.gsub(outString,'(%[%[)(Category: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 local tracking = check({ ['unknown']='[[Category:Pages using authority control with parameters|' .. sortkey .. ']]', ['preview']='Page using [[Template:Authority control]] with "_VALUE_", please move this to Wikidata.', 'show', 'country', 'suppress', 'additional', 'qid', 'state' }, parentArgs) if namespace == 0 -- mainspace or namespace == 14 -- category or namespace == 2 -- user or namespace == 118 then -- draft outString = outString .. tracking 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 count = frame.args.count or false local wikiTable = '<table class="wikitable sortable">'.. '<tr><th>Code</th>'.. '<th>Identifier</th>'.. '<th data-sort-type=number>Wikidata property</th>'.. '<th>Section</th>'.. '<th>Appears as</th>' if count then wikiTable = wikiTable .. '<th>[[:Category:Articles with authority control information|Articles]] ([[:Category:Articles with faulty authority control information|Faults]])</th>' end wikiTable = wikiTable .. '</tr>' local columns = 4 + (count and 1 or 0) local lang = mw.getContentLanguage() local a, P, f = 0, 0, 0 --cumulative sums local getlink = require("Module:Wikidata table")._getLink 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(config.config) do local category = conf.category or conf[1] local articleCat = 'Articles with '..category..' identifiers' local articleCount = mw.site.stats.pagesInCategory(articleCat,'pages') local errorCat = conf.errorcat or 'Articles with faulty '..(conf.category or conf[1])..' identifiers' local errorCount = mw.site.stats.pagesInCategory(errorCat,'pages') P = P + 1 --property count a = a + articleCount f = f + errorCount local example = mw.wikibase.getBestStatements('P'..conf.property,'P1855') or '' if example then example = example[1].qualifiers['P'..conf.property][1].datavalue.value example = mw.getCurrentFrame():expandTemplate{title = "Hlist", args = {'\n' .. makelink(conf,{id=example},1)}} .. '\n' end local name = mw.wikibase.getBestStatements('P'..conf.property,"P1629") if name and name[1] and name[1].mainsnak.datavalue.value.id then name = getlink(name[1].mainsnak.datavalue.value.id) else name = '' end if conf.remark then wikiTable = wikiTable..'<tr><td rowspan=2>' else wikiTable = wikiTable..'<tr><td>' end wikiTable = wikiTable .. '[[' .. conf[1] .. ' (identifier)' .. '|' .. conf[1] .. ']]</td>' wikiTable = wikiTable..'<td>'.. name .. '</td>' .. '<td data-sort-value=' .. conf.property .. '>' .. frame:expandTemplate{title='Wikidata property link',args={id='f',conf.property}} .. '</td>' .. '<td>' .. config.sectionNames[conf.section]..'</td>' .. '<td>' .. example .. '</td>' if count then wikiTable = wikiTable .. '<td style="text-align: right;">'..checkcat(articleCat,lang:formatNum(articleCount))..' ('..checkcat(errorCat,errorCount)..')</td>' end wikiTable = wikiTable .. '</tr>' if conf.remark then wikiTable = wikiTable .. "<tr><td colspan=" .. columns .. ">'''Remarks:''' "..conf.remark .. "</td></tr>" end end if count then wikiTable = wikiTable .. '<tr><th style="text-align: right;" colspan=' .. columns-1 .. '>Totals</th>' .. '<th style="text-align: right;">' .. P .. '</th>' .. '<th style="text-align: right;">' .. lang:formatNum(a) .. ' ([[:Category:All articles with faulty authority control information|' .. f .. ']])</th></tr>' end wikiTable = wikiTable .. '</table>' return require('Module:Suppress categories').main(wikiTable) end function p.errorTable(frame) local Table = '<table class="wikitable sortable">'.. '<tr><th>Code</th>'.. '<th>Wikidata property</th>'.. '<th>Faulty IDs</th>'.. '<th>[[:Category:Articles with faulty authority control information|Tracking category]]</th></tr>' local f, P = 0, 0, 0 --cumulative sums for _, conf in pairs(config.config) do local category = conf.errorcat or 'Articles with faulty '..(conf.category or conf[1])..' identifiers' local count = mw.site.stats.pagesInCategory(category,'pages') if count > 0 then P = P + 1 f = f + count Table = Table..'<tr><th>[['..(conf.idlink or conf[1]..' (identifier)')..'|'..conf[1]..']]</th>'.. '<td>'..frame:expandTemplate{ title = 'Wikidata property link', args = { id = 'f', conf.property } } .. '</td>'.. '<td style="text-align:center;">'..tostring(count)..'</td>'.. '<td>[[:Category:'..category..']]</td></tr>' end end Table = Table..'<tr><th colspan=2 style="text-align: right;">Totals</th>'.. '<th style="text-align:center;">' .. '[[:Category:All articles with faulty authority control information|' .. tostring(f) .. ']]</th>'.. '<th style="text-align:center;">'..tostring(P)..'</th></tr></table>' return Table end function p.whitelisttable(frame) local Table = '<table class="wikitable sortable">'.. '<tr><th>Code</th>'.. '<th>Topic</th>'.. '<th>Identifiers</th></tr>' for code, wlist in pairs(config.whitelists) do Table = Table .. '<tr><th>' .. code .. '</th>'.. '<td>[[' .. mw.wikibase.getSitelink('Q' .. wlist.topic) .. ']]</td>' local plist = {} for _, property in pairs(wlist.properties) do table.insert(plist,frame:expandTemplate{title='Wikidata property link', args={'P' .. property}}) end Table = Table .. '<td>' .. table.concat(plist,', ') .. '</td></tr>' end Table = Table .. '</table>' return Table end function p.sectiontable(frame) local Table = '<table class="wikitable sortable">'.. '<tr><th>Section</th>'.. '<th>Description</th>'.. '<th>Identifiers</th></tr>' for number,section in ipairs(config.sectionNames) do Table = Table .. '<tr><th>' .. number .. '</th>' .. '<td>' .. section .. '</td>' local plist = {} for _,id in pairs(config.config) do if id.section == number then table.insert(plist,frame:expandTemplate{title='Wikidata property link', args={'P' .. id.property}}) end end Table = Table .. '<td>' .. table.concat(plist,', ') .. '</td></tr>' end Table = Table .. '</table>' return Table end -- Main/External Call for Pages with authority control identifiers function p.autoDetect( frame ) local function whichTOC( frame ) -- standardize TOC behavior via {{CatAutoTOC}} return frame:expandTemplate{ title = 'CatAutoTOC', args = { align = 'center' } } end local ac_conf = require('Module:Authority control/config').config local rmCats = require('Module:Suppress categories').main --For use in [[Category:Articles with faulty authority control information]], i.e. on [[Category:Articles with faulty VIAF identifiers]] local function wpfaulty( frame, id ) for _, conf in pairs(ac_conf) do if conf.category == id or conf[1] == id then local outString = frame:expandTemplate{ title = 'Cat more', args = {'Wikipedia:Authority control', conf.idlink or conf[1]..' (identifier)', ':d:Property:P'..conf.property} } .. frame:expandTemplate{ title = 'Possibly empty category' } .. frame:expandTemplate{ title = 'Wikipedia category', args = { hidden = 'yes', tracking = 'yes' } } .. frame:expandTemplate{ title = 'Polluted category' } .. whichTOC( frame ) .. '\nPages in this category should only be added by [[Module:Authority control]].' .. addCat('Articles with '..id..' identifiers') .. addCat('Articles with faulty authority control information',id) return outString end end return '' end --For use in [[Category:Articles with authority control information]], i.e. on [[Category:Articles with VIAF identifiers]] local function wp(frame,id ) for _, conf in pairs( ac_conf ) do if conf.category == id or conf[1] == id then local link = '[[' .. (conf.idlink or conf[1] .. ' (identifier)') .. '|' .. conf[1] .. ']]' local outString = frame:expandTemplate{ title = 'Category explanation', args = {'articles with '..link..' identifiers.'..' Please do not add [[Wikipedia:Categorization#Subcategorization|subcategories]].'} } .. frame:expandTemplate{ title = 'Cat more', args = {'Wikipedia:Authority control', ':d:Property:P'..conf.property} } .. frame:expandTemplate{ title = 'Possibly empty category' } .. frame:expandTemplate{ title = 'Wikipedia category', args = { hidden = 'yes', tracking = 'yes' } } .. whichTOC( frame ) .. '\nPages in this category should only be added by [[Module:Authority control]].' .. addCat('Articles with authority control information',id) return outString end end return '' end if namespace == 14 then --cat space local wpfaultyID = mw.ustring.match(title.text, 'Articles with faulty ([%w%.%- ]+) identifiers') local wpID = mw.ustring.match(title.text, 'Articles with ([%w%.%- ]+) identifiers') if wpfaultyID then return wpfaulty(frame,wpfaultyID)-- must be before wpID check, in case they both match elseif wpID then return wp(frame, wpID)-- to keep the regex simple else return needsAttention('U') end end return '' end return p