Module:Authority control
Jump to navigation
Jump to search
This Lua module is used on 475,000+ pages, or roughly 28770% 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. |
This module uses the Wikidata properties:
Lua error in Module:Uses_Wikidata at line 13: attempt to index field 'wikibase' (a nil value).
This module contains the code of the {{Authority control}} template. See its documentation.
Tracking categories
This module currently implements the following hidden tracking categories:
- Category:Wikipedia articles with VIAF identifiers (0)
- Category:User pages with VIAF identifiers (0)
- Category:Miscellaneous pages with VIAF identifiers (0)
- Category:Wikipedia articles with SBN identifiers (0)
- Category:User pages with SBN identifiers (0)
- Category:Miscellaneous pages with SBN identifiers (0)
- Category:Wikipedia articles with LCCN identifiers (0)
- Category:User pages with LCCN identifiers (0)
- Category:Miscellaneous pages with LCCN identifiers (0)
- Category:Wikipedia articles with MusicBrainz identifiers (0)
- Category:User pages with MusicBrainz identifiers (0)
- Category:Miscellaneous pages with MusicBrainz identifiers (0)
- Category:Wikipedia articles with ISNI identifiers (0)
- Category:User pages with ISNI identifiers (0)
- Category:Miscellaneous pages with ISNI identifiers (0)
- Category:Wikipedia articles with ORCID identifiers (0)
- Category:User pages with ORCID identifiers (0)
- Category:Miscellaneous pages with ORCID identifiers (0)
- Category:Wikipedia articles with GND identifiers (0)
- Category:User pages with GND identifiers (0)
- Category:Miscellaneous pages with GND identifiers (0)
- Category:Wikipedia articles with SELIBR identifiers (0)
- Category:User pages with SELIBR identifiers (0)
- Category:Miscellaneous pages with SELIBR identifiers (0)
- Category:Wikipedia articles with BPN identifiers (0)
- Category:User pages with BPN identifiers (0)
- Category:Miscellaneous pages with BPN identifiers (0)
- Category:Wikipedia articles with BNF identifiers (0)
- Category:User pages with BNF identifiers (0)
- Category:Miscellaneous pages with BNF identifiers (0)
- Category:Wikipedia articles with RID identifiers (0)
- Category:User pages with RID identifiers (0)
- Category:Miscellaneous pages with RID identifiers (0)
- Category:Wikipedia articles with BIBSYS identifiers (0)
- Category:User pages with BIBSYS identifiers (0)
- Category:Miscellaneous pages with BIBSYS identifiers (0)
- Category:Wikipedia articles with ULAN identifiers (0)
- Category:User pages with ULAN identifiers (0)
- Category:Miscellaneous pages with ULAN identifiers (0)
- Category:Wikipedia articles with NLA identifiers (0)
- Category:User pages with NLA identifiers (0)
- Category:Miscellaneous pages with NLA identifiers (0)
- Category:Wikipedia articles with RKDartists identifiers (0)
- Category:User pages with RKDartists identifiers (0)
- Category:Miscellaneous pages with RKDartists identifiers (0)
Existing categories not currently implemented in module:
- Category:Wikipedia articles with BNE identifiers (0)
- Category:Wikipedia articles with LNB identifiers (0)
- Category:Wikipedia articles with NDL identifiers (0)
- Category:Wikipedia articles with NSK identifiers (0)
require('Module:No globals') local function getCatForId( id ) local title = mw.title.getCurrentTitle() local namespace = title.namespace if namespace == 0 then return '[[Category:Wikipedia articles with ' .. id .. ' identifiers]]' elseif namespace == 2 and not title.isSubpage then return '[[Category:User pages with ' .. id .. ' identifiers]]' else return '[[Category:Miscellaneous pages with ' .. id .. ' identifiers]]' end end local function viafLink( id ) if not string.match( id, '^%d+$' ) then return false end return '[https://viaf.org/viaf/' .. id .. ' ' .. id .. ']' .. getCatForId( 'VIAF' ) end local function kulturnavLink( id ) return '[http://kulturnav.org/language/en/' .. id .. ' id]' end local function sikartLink( id ) return '[http://www.sikart.ch/KuenstlerInnen.aspx?id=' .. id .. '&lng=en ' .. id .. ']' end local function tlsLink( id ) local id2 = mw.ustring.gsub(id, '%s', function(s) return mw.uri.encode(s, 'WIKI') end) return '[http://tls.theaterwissenschaft.ch/wiki/' .. id2 .. ' ' .. id .. ']' end local function ciniiLink( id ) return '[http://ci.nii.ac.jp/author/' .. id .. '?l=en ' .. id .. ']' end local function bneLink( id ) return '[http://catalogo.bne.es/uhtbin/authoritybrowse.cgi?action=display&authority_id=' .. id .. ' ' .. id .. ']' end local function uscongressLink( id ) return '[http://bioguide.congress.gov/scripts/biodisplay.pl?index=' .. id .. ' ' .. id .. ']' end local function narapersonLink( id ) return '[https://research.archives.gov/person/' .. id .. ' ' .. id .. ']' end local function naraorganizationLink( id ) return '[https://research.archives.gov/organization/' .. id .. ' ' .. id .. ']' end local function botanistLink( id ) local id2 = mw.ustring.gsub(id, '%s', function(s) return mw.uri.encode(s, 'PATH') end) return '[http://www.ipni.org/ipni/advAuthorSearch.do?find_abbreviation=' .. id2 .. ' ' .. id .. ']' end local function mgpLink( id ) -- TODO Implement some sanity checking regex return '[http://www.genealogy.ams.org/id.php?id=' .. id .. ' ' .. id .. ']' end local function rslLink( id ) -- TODO Implement some sanity checking regex return '[http://aleph.rsl.ru/F?func=find-b&find_code=SYS&adjacent=Y&local_base=RSL11&request=' .. id .. '&CON_LNG=ENG ' .. id .. ']' end local function leonoreLink( id ) -- Identifiants allant de LH/1/1 à LH/2794/54 (légionnaires) -- Identifiants allant de C/0/1 à C/0/84 (84 légionnaires célèbres) -- Identifiants allant de 19800035/1/1 à 19800035/385/51670 (légionnaires décédés entre 1954 et 1977, et quelques dossiers de légionnaires décédés avant 1954) if not string.match( id, '^LH/%d%d?%d?%d?/%d%d?%d?$' ) and not string.match( id, '^C/0/%d%d?$' ) and not string.match( id, '^19800035/%d%d?%d?%d?/%d%d?%d?%d?%d?$' ) then return false end return '[http://www.culture.gouv.fr/public/mistral/leonore_fr?ACTION=CHERCHER&FIELD_1=COTE&VALUE_1=' .. id .. ' ' .. id .. ']' end local function sbnLink( id ) if not string.match( id, '^IT\\ICCU\\%d%d%d%d%d%d%d%d%d%d$' ) and not string.match( id, '^IT\\ICCU\\%u%u[%d%u]%u\\%d%d%d%d%d%d$' ) then return false end return '[http://opac.sbn.it/opacsbn/opac/iccu/scheda_authority.jsp?bid=' .. id .. ' ' .. id .. ']' .. getCatForId( 'SBN' ) end local function nkcLink( id ) return '[http://aleph.nkp.cz/F/?func=find-c&local_base=aut&ccl_term=ica=' .. id .. '&CON_LNG=ENG ' .. id .. ']' end local function nclLink( id ) if not string.match( id, '^%d+$' ) then return false end return '[http://aleweb.ncl.edu.tw/F/?func=accref&acc_sequence=' .. id .. '&CON_LNG=ENG ' .. id .. ']' end local function ndlLink( id ) return '[https://id.ndl.go.jp/auth/ndlna/' .. id .. ' ' .. id .. ']' end local function sudocLink( id ) if not string.match( id, '^%d%d%d%d%d%d%d%d[%dxX]$' ) then return false end return '[https://www.idref.fr/' .. id .. ' ' .. id .. ']' end local function hlsLink( id ) if not string.match( id, '^%d+$' ) then return false end return '[http://www.hls-dhs-dss.ch/textes/f/F' .. id .. '.php ' .. id .. ']' end local function lirLink( id ) if not string.match( id, '^%d+$' ) then return false end return '[http://www.e-lir.ch/e-LIR___Lexicon.' .. id .. '.450.0.html ' .. id .. ']' end local function splitLccn( id ) if id:match( '^%l%l?%l?%d%d%d%d%d%d%d%d%d?%d?$' ) then id = id:gsub( '^(%l+)(%d+)(%d%d%d%d%d%d)$', '%1/%2/%3' ) end if id:match( '^%l%l?%l?/%d%d%d?%d?/%d+$' ) then return mw.text.split( id, '/' ) end return false end local function append(str, c, length) while str:len() < length do str = c .. str end return str end local function lccnLink( id ) local parts = splitLccn( id ) if not parts then return false end local lccnType = parts[1] ~= 'sh' and 'names' or 'subjects' id = parts[1] .. parts[2] .. append( parts[3], '0', 6 ) return '[http://id.loc.gov/authorities/' .. lccnType .. '/' .. id .. ' ' .. id .. ']' .. getCatForId( 'LCCN' ) end local function mbLink( id ) -- TODO Implement some sanity checking regex return '[//musicbrainz.org/artist/' .. id .. ' ' .. id .. ']' .. getCatForId( 'MusicBrainz' ) end --Returns the ISNI check digit isni must be a string where the 15 first elements are digits local function getIsniCheckDigit( isni ) local total = 0 for i = 1, 15 do local digit = isni:byte( i ) - 48 --Get integer value total = (total + digit) * 2 end local remainder = total % 11 local result = (12 - remainder) % 11 if result == 10 then return "X" end return tostring( result ) end --Validate ISNI (and ORCID) and retuns it as a 16 characters string or returns false if it's invalid --See http://support.orcid.org/knowledgebase/articles/116780-structure-of-the-orcid-identifier local function validateIsni( id ) id = id:gsub( '[ %-]', '' ):upper() if not id:match( '^%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d[%dX]$' ) then return false end if getIsniCheckDigit( id ) ~= string.char( id:byte( 16 ) ) then return false end return id end local function isniLink( id ) id = validateIsni( id ) if not id then return false end return '[http://isni.org/isni/' .. id .. ' ' .. id:sub( 1, 4 ) .. ' ' .. id:sub( 5, 8 ) .. ' ' .. id:sub( 9, 12 ) .. ' ' .. id:sub( 13, 16 ) .. ']' .. getCatForId( 'ISNI' ) end local function orcidLink( id ) id = validateIsni( id ) if not id then return false end id = id:sub( 1, 4 ) .. '-' .. id:sub( 5, 8 ) .. '-' .. id:sub( 9, 12 ) .. '-' .. id:sub( 13, 16 ) return '[https://orcid.org/' .. id .. ' ' .. id .. ']' .. getCatForId( 'ORCID' ) end local function gndLink( id ) return '[http://d-nb.info/gnd/' .. id .. ' ' .. id .. ']' .. getCatForId( 'GND' ) end local function selibrLink( id ) if not string.match( id, '^%d+$' ) then return false end return '[//libris.kb.se/auth/' .. id .. ' ' .. id .. ']' .. getCatForId( 'SELIBR' ) end local function bnfLink( id ) --Add cb prefix if it has been removed if not string.match( id, '^cb.+$' ) then id = 'cb' .. id end return '[http://catalogue.bnf.fr/ark:/12148/' .. id .. ' ' .. id .. '] [http://data.bnf.fr/ark:/12148/' .. id .. ' (data)]' .. getCatForId( 'BNF' ) end local function bpnLink( id ) if not string.match( id, '^%d+$' ) then return false end return '[http://www.biografischportaal.nl/en/persoon/' .. id .. ' ' .. id .. ']' .. getCatForId( 'BPN' ) end local function ridLink( id ) return '[https://www.researcherid.com/rid/' .. id .. ' ' .. id .. ']' .. getCatForId( 'RID' ) end local function bibsysLink( id ) return '[https://authority.bibsys.no/authority/rest/authorities/html/' .. id .. ' ' .. id .. ']' .. getCatForId( 'BIBSYS' ) end local function ulanLink( id ) return '[//www.getty.edu/vow/ULANFullDisplay?find=&role=&nation=&subjectid=' .. id .. ' ' .. id .. ']' .. getCatForId( 'ULAN' ) end local function nlaLink( id ) return '[//nla.gov.au/anbd.aut-an' .. id .. ' ' .. id .. ']' .. getCatForId( 'NLA' ) end local function rkdartistsLink( id ) return '[https://rkd.nl/en/explore/artists/' .. id .. ' ' .. id .. ']' .. getCatForId( 'RKDartists' ) end local function getIdsFromWikidata( item, property ) local ids = {} if not item.claims[property] then return ids end for _, statement in pairs( item:getBestStatements( property )) do if statement.mainsnak.datavalue then table.insert( ids, statement.mainsnak.datavalue.value ) end end return ids end local function matchesWikidataRequirements( item, reqs ) for _, group in pairs( reqs ) do local property = 'p' .. group[1] local qid = group[2] if item.claims[property] ~= nil then for _, statement in pairs ( item.claims[property] ) do if statement.mainsnak.datavalue ~= nil then if statement.mainsnak.datavalue.value['numeric-id'] == qid then return true end end end end end return false end local function createRow( id, label, rawValue, link, withUid ) if link then if withUid then return '*<span style="white-space:nowrap;">' .. label .. ' <span class="uid">' .. link .. '</span></span>\n' else return '*<span style="white-space:nowrap;">' .. label .. ' ' .. link .. '</span>\n' end else return '* <span class="error">The ' .. id .. ' id ' .. rawValue .. ' is not valid.</span>[[Category:Wikipedia articles with faulty authority control identifiers (' .. id .. ')]]\n' end end --In this order: name of the parameter, label, propertyId in Wikidata, formatting function local conf = { { 'VIAF', '[[Virtual International Authority File|VIAF]]', 214, viafLink }, { 'LCCN', '[[Library of Congress Control Number|LCCN]]', 244, lccnLink }, { 'ISNI', '[[International Standard Name Identifier|ISNI]]', 213, isniLink }, { 'ORCID', '[[ORCID]]', 496, orcidLink }, { 'GND', '[[Integrated Authority File|GND]]', 227, gndLink }, { 'SELIBR', '[[LIBRIS|SELIBR]]', 906, selibrLink }, { 'SUDOC', '[[Système universitaire de documentation|SUDOC]]', 269, sudocLink }, { 'BNF', '[[Bibliothèque nationale de France|BNF]]', 268, bnfLink }, { 'BPN', '[[Biografisch Portaal|BPN]]', 651, bpnLink }, { 'RID', '[[ResearcherID]]', 1053, ridLink }, { 'BIBSYS', '[[BIBSYS]]', 1015, bibsysLink }, { 'ULAN', '[[Union List of Artist Names|ULAN]]', 245, ulanLink }, { 'HDS', '[[Historical Dictionary of Switzerland|HDS]]', 902, hlsLink }, { 'LIR', '[[Historical Dictionary of Switzerland#Lexicon_Istoric_Retic|LIR]]', 886, lirLink }, { 'MBA', '[[MusicBrainz]]', 434, mbLink }, { 'MGP', '[[Mathematics Genealogy Project|MGP]]', 549, mgpLink }, { 'NLA', '[[National Library of Australia|NLA]]', 409, nlaLink }, { 'NDL', '[[National Diet Library|NDL]]', 349, ndlLink }, { 'NCL', '[[National Central Library|NCL]]', 1048, nclLink }, { 'NKC', '[[National Library of the Czech Republic|NKC]]', 691, nkcLink }, { 'Léonore', '[[Base Léonore|Léonore]]', 640, leonoreLink }, { 'SBN', '[[Istituto Centrale per il Catalogo Unico|ICCU]]', 396, sbnLink }, { 'RLS', '[[Russian State Library|RLS]]', 947, rslLink }, { 'Botanist', '[[Author citation (botany)|Botanist]]', 428, botanistLink }, { 'NARA-person', '[[National Archives and Records Administration|NARA]]', 1222, narapersonLink }, { 'NARA-organization', '[[National Archives and Records Administration|NARA]]', 1223, naraorganizationLink }, { 'USCongress', '[[Biographical Directory of the United States Congress|US Congress]]', 1157, uscongressLink }, { 'BNE', '[[Biblioteca Nacional de España|BNE]]', 950, bneLink }, { 'CINII', '[[CiNii]]', 271, ciniiLink }, { 'TLS', '[[Theaterlexikon der Schweiz|TLS]]', 1362, tlsLink }, { 'SIKART', '[[SIKART]]', 781, sikartLink }, { 'KULTURNAV', '[[KulturNav]]', 1248, kulturnavLink }, { 'RKDartists', '[[Netherlands Institute for Art History#Online artist pages|RKD]]', 650, rkdartistsLink }, } -- Check that the Wikidata item has this property-->value before adding it local reqs = {} local p = {} function p.authorityControl( frame ) local parentArgs = frame:getParent().args --Create rows local elements = {} --redirect PND to GND if (parentArgs.GND == nil or parentArgs.GND == '') and parentArgs.PND ~= nil and parentArgs.PND ~= '' then parentArgs.GND = parentArgs.PND end --Wikidata fallback if requested local item = mw.wikibase.getEntityObject() if item ~= nil and item.claims ~= nil then for _, params in pairs( conf ) do if params[3] ~= 0 then local val = parentArgs[params[1]] if not val or val == '' then local canUseWikidata = nil if reqs[params[1]] ~= nil then canUseWikidata = matchesWikidataRequirements( item, reqs[params[1]] ) else canUseWikidata = true end if canUseWikidata then local wikidataIds = getIdsFromWikidata( item, 'P' .. params[3] ) if wikidataIds[1] then parentArgs[params[1]] = wikidataIds[1] end end end end end end --Worldcat if parentArgs['WORLDCATID'] and parentArgs['WORLDCATID'] ~= '' then table.insert( elements, createRow( 'WORLDCATID', '', parentArgs['WORLDCATID'], '[//www.worldcat.org/identities/' .. parentArgs['WORLDCATID'] .. ' WorldCat Identities]', false ) ) --Validation? elseif parentArgs['VIAF'] and string.match( parentArgs['VIAF'], '^%d+$' ) then -- Hackishly copy the validation code; this should go away when we move to using P1793 and P1630 table.insert( elements, createRow( 'VIAF', '', parentArgs['VIAF'], '[//www.worldcat.org/identities/containsVIAFID/' .. parentArgs['VIAF'] .. ' WorldCat Identities]', false ) ) elseif parentArgs['LCCN'] and parentArgs['LCCN'] ~= '' then local lccnParts = splitLccn( parentArgs['LCCN'] ) if lccnParts and lccnParts[1] ~= 'sh' then table.insert( elements, createRow( 'LCCN', '', parentArgs['LCCN'], '[//www.worldcat.org/identities/lccn-' .. lccnParts[1] .. lccnParts[2] .. '-' .. lccnParts[3] .. ' WorldCat Identities]', false ) ) end end --Configured rows local rct = 0 for k, params in pairs( conf ) do local val = parentArgs[params[1]] if val and val ~= '' then table.insert( elements, createRow( params[1], params[2] .. ':', val, params[4]( val ), true ) ) rct = rct + 1 end end local Navbox = require('Module:Navbox') local elementscats = '' if rct > 13 then elementscats = '[[Category:AC with ' .. rct .. ' elements]]' end if #elements ~= 0 then return Navbox._navbox( { name = 'Authority control', bodyclass = 'hlist', group1 = '[[Help:Authority control|Authority control]]' .. elementscats, list1 = table.concat( elements ) } ) else return "" end end return p