Αυτό το module υλοποιεί το πρότυπο {{Authority control}}. Αντλεί κωδικούς αναφοράς βιβλιογραφικών βάσεων δεδομένων από τα Wikidata και δημιουργεί πίνακα με καταλόγους καθιερωμένων όρων και συνδέσμους προς αυτούς. Ο παρακάτω πίνακας εμφανίζει τους κωδικούς αναφοράς που υποστηρίζει το module, την ιδιότητα Wikidata που αντιστοιχεί στον καθένα, τη σειρά και το όνομα (ετικέτα) με το οποίο εμφανίζονται στο πρότυπο {{Authority control}} και το τμήμα του module που τους αντλεί (function).

Σειρά Κωδικός αναφοράς Function Ετικέτα Ιδιότητα Wikidata
1 VIAF viafLink VIAF P214
2 NLG NLGIDLink ΕΒΕ P3348
3 BNed BNeditionLink BiblioNet P2187
4 BNper BNpersonLink BiblioNet P2188
5 BNpub BNpublisherLink BiblioNet P2189
6 LCCN lccnLink LCCN P244
7 ISNI isniLink ISNI P213
8 ORCID orcidLink ORCID P496
9 GND gndLink GND P227
10 SELIBR selibrLink SELIBR P906
11 SUDOC sudocLink SUDOC P269
12 BNF bnfLink BNF P268
13 BPN bpnLink BPN P651
14 RID ridLink ResearcherID P1053
15 BIBSYS bibsysLink BIBSYS P1015
16 ULAN ulanLink ULAN P245
17 HDS hlsLink HDS P209
18 LIR lirLink LIR P886
19 MBA mbLink MusicBrainz P434
20 MGP mgpLink MGP P549
21 NLA nlaLink NLA P409
22 NDL ndlLink NDL P349
23 NCL nclLink NCL P1048
23 NKC nkcLink NKC P691
24 Léonore leonoreLink Léonore P640
25 SBN sbnLink ICCU P396
26 RLS rslLink RLS P947
27 Gutenberg gutenbergauthorLink Project Gutenberg P1938
28 NARA-person narapersonLink NARA P1222
29 NARA-organization naraorganizationLink NARA P1223
30 USCongress uscongressLink US Congress P1157
31 BNE bneLink BNE P950
32 CINII ciniiLink CiNii P271
33 TLS tlsLink TLS P1362
34 SIKART sikartLink SIKART P781
35 KULTURNAV kulturnavLink KulturNav P1248
36 RKDartists rkdartistsLink RKD P650

require('Module:No globals')

local function getCatForId( id )
	local title = mw.title.getCurrentTitle()
	local namespace = title.namespace
	if namespace == 0 then
		return '[[Category:Περιεχόμενο Βικιθήκης με αναγνωριστικά ' .. id .. ']]'
	elseif namespace == 2 and not title.isSubpage then
		return '[[Category:Σελίδες χρηστών με αναγνωριστικά ' .. id .. ']]'
	else
		return '[[Category:Διάφορες σελίδες με αναγνωριστικά ' .. id .. ']]'
	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 NLGIDLink( id )
	return '[https://catalogue.nlg.gr/Authority/Record?id=au.' .. id .. ' ' .. id .. ']' .. getCatForId( 'EBE' )
end

local function BNeditionLink( id )
	return '[http://www.biblionet.gr/book/' .. id .. ' ' .. id .. ']' .. getCatForId( 'BiblioNet' )
end

local function BNpersonLink( id )
	return '[http://www.biblionet.gr/προσωπο/?personid=' .. id .. ' ' .. id .. ']' .. getCatForId( 'BiblioNet' )
end

local function BNpublisherLink( id )
	return '[http://www.biblionet.gr/com/' .. id .. ' ' .. id .. ']'.. getCatForId( 'BiblioNet' )
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 '[http://research.archives.gov/person/' .. id .. ' ' .. id .. ']' 
end

local function naraorganizationLink( id )
	return '[http://research.archives.gov/organization/' .. id .. ' ' .. id .. ']' 
end

local function gutenbergauthorLink( id )
	local id2 = mw.ustring.gsub(id, '%s', function(s) return mw.uri.encode(s, 'PATH') end)
	return '[http://www.gutenberg.org/ebooks/author/' .. id .. ' ' .. 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 )
	return '[https://www.leonore.archives-nationales.culture.gouv.fr/ui/notice/' .. id .. ' ' .. id .. ']' 
end

local function sbnLink( id )
	return '[https://opac.sbn.it/opacsbn/opac/iccu/scheda_authority.jsp?bid=' .. id .. ' ' .. id .. ']'
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 '[http://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 '[http://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/' .. 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 '[http://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 '[http://www.researcherid.com/rid/' .. id .. ' ' .. id .. ']' .. getCatForId( 'RID' )
end

local function bibsysLink( id )
	return '[http://ask.bibsys.no/ask/action/result?cmd=&kilde=biblio&cql=bs.autid+%3D+' .. id .. '&feltselect=bs.autid ' .. 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.claims[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 '* ' .. label .. '&#160;<span class="uid plainlinks">' .. link .. '</span>\n'
		else
			return '* ' .. label .. '&#160;<span class="plainlinks">' .. link .. '</span>\n'
		end
		else
		return '* <span class="error">The ' .. id .. ' id ' .. rawValue .. ' is not valid.</span>[[Category:Σελίδες Βικιθήκης με εσφαλμένο αναγνωριστικό καταλόγου καθιερωμένων όρων]]\n'
	end
end

--In this order: name of the parameter, label, propertyId in Wikidata, formatting function
local conf = {
	{ 'VIAF', '[[w:Virtual International Authority File|VIAF]]', 214, viafLink },
	{ 'NLG', '[[w:Εθνική Βιβλιοθήκη της Ελλάδος|ΕΒΕ]]', 3348, NLGIDLink },
	{ 'BNed', '[[w:BiblioNet|BiblioNet]]', 2187, BNeditionLink },
	{ 'BNper', '[[w:BiblioNet|BiblioNet]]', 2188, BNpersonLink },
	{ 'BNpub', '[[w:BiblioNet|BiblioNet]]', 2189, BNpublisherLink },
	{ 'LCCN', '[[w:Αριθμός Ελέγχου της Βιβλιοθήκης του Κογκρέσου|LCCN]]', 244, lccnLink },
	{ 'ISNI', '[[w:International Standard Name Identifier|ISNI]]', 213, isniLink },
	{ 'ORCID', '[[w:en:ORCID|ORCID]]', 496, orcidLink },
	{ 'GND', '[[w:Gemeinsame Normdatei|GND]]', 227, gndLink },
	{ 'SELIBR', '[[w:LIBRIS|SELIBR]]', 906, selibrLink },
	{ 'SUDOC', '[[w:Système universitaire de documentation|SUDOC]]', 269, sudocLink },    
	{ 'BNF', '[[w:Εθνική Βιβλιοθήκη της Γαλλίας|BNF]]', 268, bnfLink },
	{ 'BPN', '[[w:el:Biografisch Portaal|BPN]]', 651, bpnLink },
	{ 'RID', '[[w:en:ResearcherID]]', 1053, ridLink },
	{ 'BIBSYS', '[[w:BIBSYS|BIBSYS]]', 1015, bibsysLink },
	{ 'ULAN', '[[w:Union List of Artist Names|ULAN]]', 245, ulanLink },
	{ 'HDS', '[[w:Ιστορικό λεξικό της Ελβετίας|HDS]]', 902, hlsLink },
	{ 'LIR', '[[w:en:Historical Dictionary of Switzerland#Lexicon_Istoric_Retic|LIR]]', 886, lirLink },
	{ 'MBA', '[[w:MusicBrainz|MusicBrainz]]', 434, mbLink },
	{ 'MGP', '[[w:Mathematics Genealogy Project|MGP]]', 549, mgpLink },    
	{ 'NLA', '[[w:Εθνική Βιβλιοθήκη της Αυστραλίας|NLA]]', 409, nlaLink },
	{ 'NDL', '[[w:en:National Diet Library|NDL]]', 349, ndlLink },
	{ 'NCL', '[[w:en:National Central Library|NCL]]', 1048, nclLink },
	{ 'NKC', '[[w:Εθνική βιβλιοθήκη της Τσεχίας|NKC]]', 691, nkcLink },
	{ 'Léonore', '[[w:fr:Base Léonore|Léonore]]', 11152, leonoreLink }, 
	{ 'SBN', '[[w:Istituto Centrale per il Catalogo Unico|ICCU]]', 396, sbnLink },     
	{ 'RLS', '[[w:ru:Российская_государственная_библиотека|RLS]]', 947, rslLink },
	{ 'Gutenberg', '[[w:Project Gutenberg|Project Gutenberg]]', 1938, gutenbergauthorLink },
	{ 'NARA-person', '[[w:en:National Archives and Records Administration|NARA]]', 1222, narapersonLink },
	{ 'NARA-organization', '[[w:en:National Archives and Records Administration|NARA]]', 1223, naraorganizationLink },
	{ 'USCongress', '[[w:en:Biographical Directory of the United States Congress|US Congress]]', 1157, uscongressLink },
	{ 'BNE', '[[w:Εθνική Βιβλιοθήκη της Ισπανίας|BNE]]', 950, bneLink },
	{ 'CINII', '[[w:CiNii]]', 271, ciniiLink },
	{ 'TLS', '[[w:de:Theaterlexikon der Schweiz|TLS]]', 1362, tlsLink },
	{ 'SIKART', '[[w:de:SIKART]]', 781, sikartLink },
	{ 'KULTURNAV', '[[w:KulturNav]]', 1248, kulturnavLink },
	{ 'RKDartists', '[[w:Ολλανδικό Ίδρυμα Ιστορίας της Τέχνης|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 = {}
	--Create rows
	local elements = {}

	--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]', false ) ) --Validation?
	elseif parentArgs['LCCN'] and parentArgs['LCCN'] ~= '' then
		local lccnParts = splitLccn( parentArgs['LCCN'] )
		if lccnParts then
			table.insert( elements, createRow( 'LCCN', '', parentArgs['LCCN'], '[//www.worldcat.org/identities/lccn-' .. lccnParts[1] .. lccnParts[2] .. '-' .. lccnParts[3] .. ' WorldCat]', 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 με ' .. rct .. ' στοιχεία]]'
	end
	
	if #elements ~= 0 then
		return Navbox._navbox( {
			name  = 'Authority control',
			bodystyle = 'margin-top:3em',
			bodyclass = 'hlist',
			group1 = 'Σύνδεσμοι σε [[w:Κατάλογος καθιερωμένων όρων|καταλόγους καθιερωμένων όρων]]' .. elementscats,
			list1 = table.concat( elements )
			} )
	else
		return ""
	end
end

return p