モジュール:Authority control

    提供:ManyoWiki

    このモジュールについての説明文ページを モジュール:Authority control/doc に作成できます

    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:赤リンクの典拠情報カテゴリがあるページ]]'
    		end
    		return '[[Category:'..cat..']]'..redlinkcat
    	else
    		return ''
    	end
    end
    
    local function getCatForId(id)
    	local cat = ''
    	if namespace == 0 then
    		cat = id..'識別子が指定されている記事'
    	end
    	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) --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 = '誤った'..(conf.errorcat or conf.category or conf[1])..'識別子が指定されている記事'
    		link = '<span class="error">'..conf[1]..'識別子の値'..val..'は正しくありません。</span>'..addCat(faultyCat)
    	end
    	return link
    end
    
    --[[==========================================================================]]
    --[[                                   Main                                   ]]
    --[[==========================================================================]]
    function p.authorityControl(frame)
    	local config = require("Module:Authority control/config")
    	local conf = config.config
    	local sectionNames = config.sectionNames
    	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 iMatches,suppressedIdCount = 0,0
    	local auxCats = ''
    	local rct = 0 -- total number of links returned
    	local numqids = 4 -- support for 4 additional qids
    	local totsect = #sectionNames + numqids
    	local sections = {}
    	for _ = 1,totsect do table.insert(sections,{}) end
    	
    	-- check for suppressed identifiers
    	local suppress = {}
    	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("^%d+$") then
    				v = "P"..tostring(v)
    			else
    				v = string.upper(v)
    			end
    			suppress[v] = true -- index table by identifier name
    		end
    	end
    	
    	--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:非推奨の典拠管理識別子が指定されている記事|'..dep..']]'
    			end
    		end
    	end
    
    	local function makeSections(qid,additional)
    		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(qid, 'P' .. params.property) -- setup table for values with property number as key
    			if additional then
    				if suppress["P"..tostring(params.property)] or suppress[string.upper(params[1])] 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 suppress["P"..tostring(params.property)] or suppress[string.upper(params[1])] or val == '' then
    					if tval[params.property][1] and (namespace == 0 or testcases) then
    						suppressedIdCount = suppressedIdCount + 1
    						if parentArgs['arts'] ~= 'arts' then
    							auxCats = auxCats .. '[[Category:抑制された典拠管理識別子がある記事|'..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:ウィキデータと異なる典拠管理識別子をパラメータで指定しているページ|'..params[1]..']]'
    						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 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'
    					local sec = additional or params.section -- uses section 9 for qid2, section 10 for qid3, etc.
    					table.insert(sections[sec],row)
    					rct = rct + 1
    					if tval[params.property][2] then
    						-- auxCats = auxCats .. getCatForId('multiple')
    					end
    				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
    
    	--use QID= parameter for testing/example purposes only
    	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 qids = {}
    	if namespace ~= 0 then
    		local qid = parentArgs['qid'] or parentArgs['QID']
    		qids[1] = resolveQID(qid)
    	elseif mw.wikibase then
    		qids[1] = mw.wikibase.getEntityIdForCurrentPage()
    	end
    	makeSections(qids[1],false)
    	for c = 2,5 do
    		qids[c] = resolveQID(parentArgs['qid' .. c])
    		if qids[c] then makeSections(qids[c],totsect-numqids+c-1) end
    	end
    	if iMatches > 0 and iMatches == iParentArgs then
    		auxCats = auxCats .. '[[Category:ウィキデータと同じ典拠管理識別子をパラメータで指定しているページ]]'
    	end
    	if parentArgs['arts'] == 'arts' and suppressedIdCount > 0 then
    		if namespace == 0 or testcases then
    			auxCats = auxCats .. addCat('ACArtで'..suppressedIdCount..'種類の典拠管理識別子が抑制された記事')
    		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,totsect do
    			if #sections[c] ~= 0 then -- section is non-empty
    				sect = sect + 1
    				lastsect = c
    				local sectname
    				if c <= totsect - numqids then -- regular section
    					sectname = sectionNames[c]
    				else -- section from additional qid
    					sectname = mw.wikibase.getLabel(qids[c-totsect+numqids+1]) .. pencil(qids[c-totsect+numqids +1])
    				end
    				navboxArgs['group' .. c] = sectname
    				navboxArgs['list' .. c] = table.concat(sections[c])
    			end
    		end
    		local aclink = '[[Help:典拠管理|典拠管理]]'
    		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(qids[1])
    			elseif lastsect <= totsect - numqids  then -- other regular section
    				navboxArgs['group' .. lastsect] = aclink .. ': ' .. sectionNames[lastsect] .. pencil(qids[1])
    			else -- section from additional qid
    				navboxArgs['group' .. lastsect] = aclink .. ': ' .. navboxArgs['group' .. lastsect]
    			end
    		else -- add title to navbox
    			navboxArgs.title = aclink .. pencil(qids[1])
    		end
    		outString = Navbox._navbox(navboxArgs)
    	end
    
    	--auxCats
    	if rct == 0 then
    		if namespace == 0 or testcases then
    			auxCats = auxCats .. addCat('典拠管理識別子が1つもない記事')
    		end
    	elseif rct >= 25 then
    		if namespace == 0 or testcases then
    			local eCat = rct..'種類の典拠管理識別子がある記事'
    			-- auxCats = auxCats .. addCat(eCat)	--25種類以上の識別子が指定された場合、追跡カテゴリをつけるという機能は日本語版では導入されていない
    		end
    	end
    	if parentArgs.state then
    		if namespace == 0 or testcases then
    			local sCat
    			if parentArgs.state == 'collapsed' then sCat = 'Normdatenでstateにcollapsedを指定している記事'
    			elseif parentArgs.state == 'expanded' then sCat = 'Normdatenでstateにexpandedを指定している記事'
    			elseif parentArgs.state == 'autocollapse' then sCat = 'Normdatenでstateにautocollapseを指定している記事'
    			else sCat = 'Normdatenでstateに不明な値を指定している記事'
    			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:[^%]]*記事)', '%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>引数名</th>'..
    	  '<th rowspan=2>グループ</th>'..
    	  '<th rowspan=2>表示名</th>'..
    	  '<th rowspan=2 data-sort-type=number>ウィキデータのプロパティ</th>'..
    	  '<th colspan=2>追跡カテゴリおよび該当ページ数</th></tr>'..
    	  '<tr><th>[[:Category:典拠管理情報がある記事|記事]]</th>'..
    	  '<th>[[:Category:誤った典拠管理情報が指定されている記事|誤った識別子]]</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 sectionNames = config.sectionNames
    	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%;">&#91;['..tostring(mw.uri.fullUrl('Category:'..category,'action=edit&preload=Template:Authority_control/preload'))..' 作成]&#93;</span>'
    		end
    		return ret
    	end
    	for _, conf in pairs(conf) do
    		local param, pid, section = conf[1], conf.property, sectionNames[conf.section]
    		local appearsAs = makelink(conf,conf.example,1)
    		local link = conf.idlink or param..' (識別子)'
    		local category = conf.category or param
    		local args = { id = 'f', pid }
    		local wpl = frame:expandTemplate{ title = 'Wikidata property link', args = args }
    		local articleCat = category..'識別子が指定されている記事'
    		local faultyCat =  '誤った'.. (conf.errorcat or category) ..'識別子が指定されている記事'
    		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>合計</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