Module:Authority control
From Soyjak Wiki, The Free Soycyclopedia
Jump to navigationJump to search
This Lua module is used on approximately 2,000,000 pages, or roughly 13447% 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.
Lua error in Module:Lua_banner at line 113: attempt to index field 'edit' (a nil value). This module contains the code of the {{Authority control}} and {{Pages with authority control identifiers}} templates.
Parameters, Wikidata properties, and tracking categories
Lua error at line 400: attempt to index field 'wikibase' (a nil value).
Additional tracking categories
This module also implements the following hidden tracking categories:
- Category:Pages with red-linked authority control categories (0) – error category to identify missing categories
- Category:Articles with suppressed authority control 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
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,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 = '[[Category:Pages with red-linked authority control categories]]' 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 ids = {} if not mw.wikibase or not qid then return ids end local statements = mw.wikibase.getBestStatements(qid,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,qid) --validate values and create a link 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.link2 then -- use function to validate and generate link if conf.link2(val) then link = link .. conf.link2(val) valid_value = true end else 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 link = link .. '<span class="uid">' if not conf.label or nextid>1 then conf.label = tostring(nextid) end if conf.link then valid_value = valid_value:gsub('%%', '%%%%') link = link .. '[' .. mw.ustring.gsub(conf.link,'%$1',valid_value) .. ' ' .. conf.label .. ']' else link = link .. valid_value end link = link .. '</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..' 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 resolveEntity = require('Module:ResolveEntityId') local function resolveQID(qid) if qid then qid = 'Q'..mw.ustring.gsub(qid, '^[Qq]', '') qid = resolveEntity._id(qid) --nil if unresolvable end return qid end local config = require("Module:Authority control/config") local conf = config.config local parentArgs = frame:getParent().args local iParentArgs = 0 --count original/manual parent args local iMatches,suppressedIdCount = 0,0 local auxCats = '' local rct = 0 -- total number of links returned local qid if namespace == 0 then qid = mw.wikibase.getEntityIdForCurrentPage() end if not qid then qid = resolveQID(parentArgs['qid']) --use qid parameter if no wikidata item is connected 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 table.insert(qids,resolveQID(v)) end end local sections = {} for _ = 1,#config.sectionNames + #qids 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 addshowlist(list) if list and list ~= '' then for _,v in ipairs(mw.text.split(string.lower(list),"%s*,%s*")) do if config.whitelists[v] then for _,w in ipairs(config.whitelists[v]) do show[w] = true end end end showall = false end end addshowlist(frame.args.show) -- check show= parameter on wrapper template addshowlist(parentArgs.show) -- 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 if v:match("^[Pp]%d+$") then v = mw.ustring.gsub(v,'[Pp]','') --strip P from property number end if v:match("^%d+$") then v = tonumber(v) else v = string.upper(v) -- convert to uppercase end show[v] = false 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 addit then if not showb then tval[params.property] = false -- indicates the identifier is suppressed end else local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]] if not showb or val == '' then if tval[params.property][1] and (namespace == 0 or testcases) then suppressedIdCount = suppressedIdCount + 1 end tval[params.property] = false -- indicates the identifier is suppressed elseif val then -- add local parameter to list if not already in 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 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],val) else iMatches = iMatches+1 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 = rct + 1 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],#config.sectionNames+c) end if iMatches > 0 and iMatches == iParentArgs then auxCats = auxCats .. '[[Category:Pages using authority control with parameters all matching Wikidata]]' end if (parentArgs.show or frame.args.show) 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 = '' if rct > 0 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,#config.sectionNames+#qids do if #sections[c] ~= 0 then -- section is non-empty sect = sect + 1 lastsect = c local sectname if c <= #config.sectionNames then -- regular section sectname = config.sectionNames[c] else -- section from additional qid sectname = mw.wikibase.getLabel(qids[c-#config.sectionNames]) .. pencil(qids[c-#config.sectionNames]) 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 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 <= #config.sectionNames 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 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%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', 'suppress', 'additional', 'qid', 'state', 'country' }, 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 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>'.. '<th>[[:Category:Articles with authority control information|Articles]]</th>'.. '<th>[[:Category:Articles with faulty authority control information|Faulty IDs]]</th></tr>' local columns = 7 local lang = mw.getContentLanguage() local a, f, P = 0, 0, 0 --cumulative sums local config = require("Module:Authority control/config") 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 wpl = frame:expandTemplate{ title = 'Wikidata property link', args = { id = 'f', conf.property } } local faultyCat = conf.errorcat or '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) local name = mw.wikibase.getBestStatements('P'..conf.property,"P9073") if name then if name[1] then name = name[1].mainsnak.datavalue.value.id if name then name = getlink(name) end else name = false end end if conf.remark then wikiTable = wikiTable..'<tr><td rowspan=2>' else wikiTable = wikiTable..'<tr><td>' end wikiTable = wikiTable..'[['..(conf.idlink or conf[1]..' (identifier)')..'|'..conf[1]..']]</td>' wikiTable = wikiTable..'<td>'..(name or '')..'</td>'.. '<td data-sort-value='..conf.property..'>'..wpl..'</td>'.. '<td>'..config.sectionNames[conf.section]..'</td>'.. '<td>' .. mw.getCurrentFrame():expandTemplate{title = "Hlist", args = {'\n' .. makelink(conf,conf.example,1)}} .. '\n</td>'.. '<td style="text-align: right;">'..checkcat(articleCat,articleCount)..'</td>'.. '<td style="text-align: right;">'..checkcat(faultyCat,faultyCount)..'</td></tr>' if conf.remark then wikiTable = wikiTable.."<tr><td colspan=" .. columns-1 .. "6>'''Remarks:''' "..conf.remark.."</td></tr>" end end wikiTable = wikiTable..'<tr><th style="text-align: right;" colspan=' .. columns-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;">' .. '[[:Category:All articles with faulty authority control information|' .. lang:formatNum(f) .. ']]</th></tr></table>' return require('Module:Suppress categories').main(wikiTable) end -- Local Utility Functions local function whichTOC( frame ) -- standardize TOC behavior via {{CatAutoTOC}} return frame:expandTemplate{ title = 'CatAutoTOC', args = { align = 'center' } } end -- Main/External Call for Pages with authority control identifiers function p.autoDetect( frame ) 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 '[[Category:Pages with authority control identifiers unknown category]]' end end return '' end return p