require('strict') local config = require("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 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 .. '' 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 .. '' 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 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 iParentArgs = 0 --count original/manual parent args local iMatches = 0 local auxCats = '' local rct = 0 -- total number of links 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 = {} 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].properties) do show[w] = true end 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 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 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 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 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 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 --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 = ' [[File:Commons to Wikidata QuickStatements.svg|20px|link=https://quickstatements.toolforge.org/#/v1=' .. qslink .. '|Add values to Wikidata.]]' 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 <= #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 (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 table-responsive 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 = ''.. 'Code | '.. 'Identifier | '.. 'Wikidata property | '.. 'Section | '.. 'Appears as | ' if count then wikiTable = wikiTable .. '[[:Category:Articles with authority control information|Articles]] ([[:Category:Articles with faulty authority control information|Faults]]) | ' end wikiTable = wikiTable .. '
' 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..' [['..tostring(mw.uri.fullUrl('Category:'..category,'action=edit&preload=Template:Authority_control/preload'))..' create]]' 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,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..'' else wikiTable = wikiTable..'' end wikiTable = wikiTable .. '[[' .. (conf.idlink or conf[1] .. ' (identifier)') .. '|' .. conf[1] .. ']] | ' wikiTable = wikiTable..''.. name .. ' | ' .. '' .. frame:expandTemplate{title='Wikidata property link',args={id='f',conf.property}} .. ' | ' .. '' .. config.sectionNames[conf.section]..' | ' .. '' .. example .. ' | ' if count then wikiTable = wikiTable .. ''..checkcat(articleCat,lang:formatNum(articleCount))..' ('..checkcat(errorCat,errorCount)..') | ' end wikiTable = wikiTable .. ' ' if conf.remark then wikiTable = wikiTable .. ".. columns .. ">'''Remarks:''' "..conf.remark .. " | " end end if count then wikiTable = wikiTable .. 'Totals | ' .. '' .. P .. ' | ' .. '' .. lang:formatNum(a) .. ' ([[:Category:All articles with faulty authority control information|' .. f .. ']]) | ' end wikiTable = wikiTable .. ' |
' return require('Module:Suppress categories').main(wikiTable) end function p.errorTable(frame) local Table = ''.. 'Code | '.. 'Wikidata property | '.. 'Faulty IDs | '.. '[[:Category:Articles with faulty authority control information|Tracking category]] |
' 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..'[['..(conf.idlink or conf[1]..' (identifier)')..'|'..conf[1]..']] | '.. ''..frame:expandTemplate{ title = 'Wikidata property link', args = { id = 'f', conf.property } } .. ' | '.. ''..tostring(count)..' | '.. '[[:Category:'..category..']] |
' end end Table = Table..'Totals | '.. '' .. '[[:Category:All articles with faulty authority control information|' .. tostring(f) .. ']] | '.. ''..tostring(P)..' |
---|
' return Table end function p.whitelisttable(frame) local Table = ''.. 'Code | '.. 'Topic | '.. 'Identifiers |
' for code, wlist in pairs(config.whitelists) do Table = Table .. '' .. code .. ' | '.. '[[' .. mw.wikibase.getSitelink('Q' .. wlist.topic) .. ']] | ' local plist = {} for _, property in pairs(wlist.properties) do table.insert(plist,frame:expandTemplate{title='Wikidata property link', args={'P' .. property}}) end Table = Table .. '' .. table.concat(plist,', ') .. ' |
' end Table = Table .. '
' return Table end function p.sectiontable(frame) local Table = ''.. 'Section | '.. 'Description | '.. 'Identifiers |
' for number,section in ipairs(config.sectionNames) do Table = Table .. '' .. number .. ' | ' ..'' .. section .. ' | ' 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 .. '' .. table.concat(plist,', ') .. ' |
' end 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