From Afropedia.world
![]() simplewiki>MathXplore (Protected "Module:Commons link": Highly visible page: per Special:Diff/9530218 ([Edit=Allow only autoconfirmed users] (indefinite) [Move=Allow only administrators] (indefinite))) m |
m |
||
Line 1: | Line 1: | ||
require('strict') | |||
-- Module to find commons galleries and categories based on wikidata entries | -- Module to find commons galleries and categories based on wikidata entries | ||
local getArgs = require('Module:Arguments').getArgs | local getArgs = require('Module:Arguments').getArgs | ||
local yesNo = require('Module:Yesno') | |||
local p = {} | local p = {} | ||
Line 17: | Line 20: | ||
end | end | ||
function _lcfirst( | local function _lcfirst(s) | ||
return mw.ustring.lower(mw.ustring.sub(s,1,1))..mw.ustring.sub(s,2) | |||
end | end | ||
local function | -- Format displayed linktext | ||
-- Arguments: | |||
-- s = string to display | |||
-- formatting = formatting table: | |||
-- formatting.linktext = if defined, override s | |||
-- formatting.lcfirst = lower case the first letter in display | |||
-- formatting.bold = whether to bold the display | |||
-- formatting.italic = whether to italicize the display | |||
-- formatting.nowrap = set nowrapping | |||
-- Returns: | |||
-- formatted string | |||
local function _formatResult(s, formatting) | |||
local resultVal = formatting.linktext or s | |||
if formatting.lcfirst then | |||
resultVal = _lcfirst(resultVal) | |||
end | |||
local style = "" | |||
if formatting.italic then style = "font-style:italic; " end | |||
if formatting.bold then style = style.."font-weight:bold; " end | |||
if formatting.nowrap then style = style.."white-space:nowrap; " end | |||
if style ~= "" then | |||
resultVal = '<span style="'..mw.text.trim(style)..'">'..resultVal..'</span>' | |||
end | |||
return resultVal | |||
end | end | ||
Line 147: | Line 163: | ||
if commonsSitelink and mw.ustring.sub(commonsSitelink,1,9) == "Category:" then | if commonsSitelink and mw.ustring.sub(commonsSitelink,1,9) == "Category:" then | ||
categoryLink = mw.ustring.sub(commonsSitelink,10) | categoryLink = mw.ustring.sub(commonsSitelink,10) | ||
end | end | ||
-- P910 is the "topic's main category". Look for commons sitelink there | -- P910 is the "topic's main category". Look for commons sitelink there | ||
Line 174: | Line 179: | ||
if categoryLink and categoryLink ~= fallback then | if categoryLink and categoryLink ~= fallback then | ||
consistent = false | consistent = false | ||
qid = nil | |||
else | else | ||
categoryLink = fallback | categoryLink = fallback | ||
end | |||
end | |||
-- P373 is the "commons category" property for this article. This is | |||
-- a low-quality field, so should only be used as a last resort. | |||
if categoryLink == nil and _validQID(qid) then | |||
local P373 = mw.wikibase.getBestStatements(qid, "P373")[1] | |||
if P373 and P373.mainsnak.datavalue then | |||
categoryLink = P373.mainsnak.datavalue.value | |||
consistent = true -- P373 is never used if anything else is available | |||
end | end | ||
end | end | ||
return categoryLink, consistent, commonsSitelink | return categoryLink, consistent, commonsSitelink | ||
end | |||
-- Does the article have a Commons gallery, and is it consistent? | |||
-- Arguments: | |||
-- qid = QID to lookup in wikidata (for testing only) | |||
-- Returns: | |||
-- filename at Commons, bool: is wikidata consistent for this article? | |||
function p._hasGalleryConsistent(qid) | |||
local wp_title, wp_ns | |||
wp_title, wp_ns, qid = _getTitleQID(qid) | |||
return _lookupGallery(qid,true) | |||
end | end | ||
Line 185: | Line 211: | ||
-- qid = QID to lookup in wikidata (for testing only) | -- qid = QID to lookup in wikidata (for testing only) | ||
-- Returns: | -- Returns: | ||
-- filename at Commons if so, | -- filename at Commons if so, false if not | ||
function p._hasGallery(qid) | function p._hasGallery(qid) | ||
local galleryLink, consistent = p._hasGalleryConsistent(qid) | |||
return consistent and galleryLink | |||
local galleryLink, consistent = | |||
end | end | ||
-- Does the article have a | -- Does the article have a Commons category? Is wikidata consistent for that? | ||
-- Arguments: | -- Arguments: | ||
-- qid = QID to lookup in wikidata (for testing only) | -- qid = QID to lookup in wikidata (for testing only) | ||
-- prefix = whether to add "Category:" to return string (default true) | -- prefix = whether to add "Category:" to return string (default true) | ||
-- Returns: | -- Returns: | ||
-- filename at Commons | -- filename at Commons, bool: consistent | ||
function p. | function p._hasCategoryConsistent(qid,prefix) | ||
if prefix == nil then | if prefix == nil then | ||
prefix = true | prefix = true | ||
Line 209: | Line 230: | ||
wp_title, wp_ns, qid = _getTitleQID(qid) | wp_title, wp_ns, qid = _getTitleQID(qid) | ||
local categoryLink, consistent = _lookupCategory(qid,true) | local categoryLink, consistent = _lookupCategory(qid,true) | ||
if categoryLink and | if categoryLink and prefix then | ||
categoryLink = "Category:"..categoryLink | |||
end | end | ||
return | return categoryLink, consistent | ||
end | |||
-- Does the article have a corresponding Commons category? | |||
-- Arguments: | |||
-- qid = QID to lookup in wikidata (for testing only) | |||
-- prefix = whether to add "Category:" to return string (default true) | |||
-- Returns: | |||
-- filename at Commons if so, blank if not | |||
function p._hasCategory(qid,prefix) | |||
local categoryLink, consistent = p._hasCategoryConsistent(qid,prefix) | |||
return consistent and categoryLink | |||
end | end | ||
Line 222: | Line 251: | ||
-- namespace = namespace in Commons ("" for galleries) | -- namespace = namespace in Commons ("" for galleries) | ||
-- default = use as Commons link, don't access wikidata | -- default = use as Commons link, don't access wikidata | ||
-- search = string to search for | -- search = string to search for | ||
-- fallback = string to search for if wikidata fails | -- fallback = string to search for if wikidata fails | ||
-- | -- formatting = formatting parameters | ||
-- qid = QID to lookup in wikidata (for testing only) | -- qid = QID to lookup in wikidata (for testing only) | ||
-- Returns: | -- Returns: | ||
-- formatted wikilink to Commons in specified namespace | -- formatted wikilink to Commons in specified namespace | ||
function p._getCommons(namespace,default | function p._getCommons(namespace,default,search,fallback,formatting,qid) | ||
local nsColon | local nsColon | ||
if not namespace or namespace == "" then | if not namespace or namespace == "" then | ||
Line 237: | Line 265: | ||
end | end | ||
if default then | if default then | ||
return "[[Commons:"..nsColon..default.."|".. | return "[[Commons:"..nsColon..default.."|".._formatResult(default,formatting).."]]" | ||
end | end | ||
if search then | if search then | ||
return "[[Commons:Special:Search/"..nsColon..search.."|".. | return "[[Commons:Special:Search/"..nsColon..search.."|".._formatResult(search,formatting).."]]" | ||
end | end | ||
local wp_title, wp_ns | local wp_title, wp_ns | ||
wp_title, wp_ns, qid = _getTitleQID(qid) | wp_title, wp_ns, qid = _getTitleQID(qid) | ||
local commonsLink = nil | local commonsLink = nil | ||
local consistent = true | local consistent = true | ||
Line 256: | Line 281: | ||
-- use wikidata if consistent | -- use wikidata if consistent | ||
if commonsLink and consistent then | if commonsLink and consistent then | ||
return "[[Commons:"..nsColon..commonsLink.."|".. | return "[[Commons:"..nsColon..commonsLink.."|".._formatResult(commonsLink,formatting).."]]" | ||
end | end | ||
-- if not consistent, fall back to search and add to tracking cat | -- if not consistent, fall back to search and add to tracking cat | ||
-- construct default result (which searches for title) | |||
local searchResult = "[[Commons:Special:Search/"..nsColon..(fallback or wp_title) | |||
.."|".._formatResult(fallback or wp_title,formatting).."]]" | |||
if not consistent and wp_ns == "" then | if not consistent and wp_ns == "" then | ||
local friendlyNS | local friendlyNS | ||
Line 274: | Line 302: | ||
-- Arguments: | -- Arguments: | ||
-- default = use as Commons link, don't access wikidata | -- default = use as Commons link, don't access wikidata | ||
-- search = string to search for | -- search = string to search for | ||
-- fallback = string to search for if wikidata lookup fails | |||
-- formatting = formatting parameters | |||
-- qid = QID to lookup in wikidata (for testing only) | -- qid = QID to lookup in wikidata (for testing only) | ||
-- Returns: | -- Returns: | ||
-- formatted wikilink to Commons "best" landing page | -- formatted wikilink to Commons "best" landing page | ||
function p._getGalleryOrCategory(default | function p._getGalleryOrCategory(default, search, fallback, formatting, qid) | ||
if default then | if default then | ||
return "[[Commons:"..default.."|"..( | return "[[Commons:"..default.."|".._formatResult(default,formatting).."]]" | ||
end | end | ||
if search then | if search then | ||
return "[[Commons:Special:Search/"..search.."|"..( | return "[[Commons:Special:Search/"..search.."|".._formatResult(search,formatting).."]]" | ||
end | end | ||
local wp_title, wp_ns | local wp_title, wp_ns | ||
wp_title, wp_ns, qid = _getTitleQID(qid) | wp_title, wp_ns, qid = _getTitleQID(qid) | ||
local trackingCats = "" | local trackingCats = "" | ||
local galleryLink, consistent, commonsSitelink = _lookupGallery(qid,true) | local galleryLink, consistent, commonsSitelink = _lookupGallery(qid,true) | ||
-- use wikidata if either sitelink or P935 exist, and they both agree | -- use wikidata if either sitelink or P935 exist, and they both agree | ||
if galleryLink and consistent then | if galleryLink and consistent then | ||
return "[[Commons:"..galleryLink.."|"..( | return "[[Commons:"..galleryLink.."|".._formatResult(galleryLink,formatting).."]]" | ||
end | end | ||
if not consistent and wp_ns == "" then | if not consistent and wp_ns == "" then | ||
Line 304: | Line 330: | ||
categoryLink, consistent = _lookupCategory(qid,false,commonsSitelink) | categoryLink, consistent = _lookupCategory(qid,false,commonsSitelink) | ||
if categoryLink and consistent then | if categoryLink and consistent then | ||
return "[[Commons:Category:"..categoryLink.."|"..( | return "[[Commons:Category:"..categoryLink.."|".._formatResult(categoryLink,formatting).."]]"..trackingCats | ||
end | end | ||
if not consistent and wp_ns == "" then | if not consistent and wp_ns == "" then | ||
trackingCats = trackingCats.."[[Category:Inconsistent wikidata for Commons category]]" | trackingCats = trackingCats.."[[Category:Inconsistent wikidata for Commons category]]" | ||
end | end | ||
-- return search result looking for title as last attempt | |||
return "[[Commons:Special:Search/" .. (fallback or wp_title) .. | |||
"|" .. _formatResult(fallback or wp_title,formatting) .. "]]" .. trackingCats | |||
-- | |||
end | end | ||
Line 334: | Line 345: | ||
-- defaultCategory = default category link to use, instead of wikidata | -- defaultCategory = default category link to use, instead of wikidata | ||
-- categoryText = if both gallery and category, text to use in category link ("category" by default) | -- categoryText = if both gallery and category, text to use in category link ("category" by default) | ||
-- | -- oneSearch = only emit one search result | ||
-- | -- formatting = formatting parameters | ||
-- qid = qid of page to lookup in wikidata (testing only) | -- qid = qid of page to lookup in wikidata (testing only) | ||
function p._getGalleryAndCategory(defaultGallery,defaultCategory, | function p._getGalleryAndCategory(defaultGallery, defaultCategory, | ||
categoryText, oneSearch, formatting, qid | |||
) | |||
local wp_title, wp_ns | local wp_title, wp_ns | ||
wp_title, wp_ns, qid = _getTitleQID(qid) | wp_title, wp_ns, qid = _getTitleQID(qid) | ||
categoryText = categoryText or "category" | categoryText = categoryText or "category" | ||
local trackingCats = "" | local trackingCats = "" | ||
local galleryLink, galleryConsistent | local galleryLink, galleryConsistent | ||
Line 371: | Line 379: | ||
end | end | ||
local firstLink | local firstLink | ||
-- construct default result (which searches for title) | |||
local searchResult = "[[Commons:Special:Search/"..wp_title.."|".._formatResult(wp_title,formatting).."]]" | |||
if not oneSearch then | |||
searchResult = searchResult.." ([[Commons:Special:Search/Category:"..wp_title.."|"..categoryText.."]])" | |||
end | |||
local linkText = nil | |||
if galleryGood then | if galleryGood then | ||
firstLink = galleryLink | firstLink = galleryLink | ||
linkText = | linkText = galleryLink | ||
elseif categoryGood then | elseif categoryGood then | ||
firstLink = "Category:"..categoryLink | firstLink = "Category:"..categoryLink | ||
linkText = | linkText = categoryLink | ||
else | else | ||
return searchResult..trackingCats | return searchResult..trackingCats | ||
end | end | ||
local resultVal = | local resultVal = "[[Commons:"..firstLink.."|".._formatResult(linkText,formatting).."]]" | ||
if galleryGood and categoryGood then | if galleryGood and categoryGood then | ||
resultVal = resultVal.." ([[Commons:Category:"..categoryLink.."|"..categoryText.."]])" | resultVal = resultVal.." ([[Commons:Category:"..categoryLink.."|"..categoryText.."]])" | ||
Line 394: | Line 408: | ||
s2 = mw.ustring.gsub(s2,"^[^:]+:","") | s2 = mw.ustring.gsub(s2,"^[^:]+:","") | ||
return s1 == s2 | return s1 == s2 | ||
end | |||
local galleryTrackingCats = { | |||
commons_link_on_wikidata = '[[Category:Commons link is on Wikidata]]', | |||
commons_link_defined_as_pagename = '[[Category:Commons link is defined as the pagename]]', | |||
commons_link_locally_defined = '[[Category:Commons link is locally defined]]', | |||
commons_link_from_wikidata = '[[Category:Commons link from Wikidata]]', | |||
commons_link_is_pagename = '[[Category:Commons link is the pagename]]', | |||
inconsistent = '[[Category:Inconsistent wikidata for Commons gallery]]' | |||
} | |||
local categoryTrackingCats = { | |||
commons_link_on_wikidata = '[[Category:Commons category link is on Wikidata]]', | |||
commons_link_defined_as_pagename = '[[Category:Commons category link is defined as the pagename]]', | |||
commons_link_locally_defined = '[[Category:Commons category link is locally defined]]', | |||
commons_link_from_wikidata = '[[Category:Commons category link from Wikidata]]', | |||
commons_link_is_pagename = '[[Category:Commons category link is the pagename]]', | |||
inconsistent = '[[Category:Inconsistent wikidata for Commons category]]' | |||
} | |||
local function selectTrackingCat(trackingCats,wikidata,consistent,default,title) | |||
if not consistent then | |||
return trackingCats.inconsistent | |||
end | |||
if default then | |||
-- construct warning message | |||
if default == wikidata then | |||
return trackingCats.commons_link_on_wikidata | |||
end | |||
local warning = "" | |||
if wikidata then | |||
local generateWarning = require('Module:If preview')._warning | |||
warning = generateWarning({ | |||
"Commons link does not match Wikidata – [[Template:Commons_category#Resolving_discrepancies|please check]]" | |||
}) | |||
end | |||
if titleMatch(default,title) then | |||
return trackingCats.commons_link_defined_as_pagename .. warning | |||
end | |||
return trackingCats.commons_link_locally_defined .. warning | |||
end | |||
if wikidata then | |||
return trackingCats.commons_link_from_wikidata | |||
end | |||
return trackingCats.commons_link_is_pagename | |||
end | end | ||
Line 420: | Line 479: | ||
return "" | return "" | ||
end | end | ||
-- determine title and namespace of wikidata and wp article | -- determine title and namespace of wikidata and wp article | ||
local wikidata = nil | local wikidata = nil | ||
local consistent = nil | |||
-- Tracking code works for all 4 cases of states of fetchGallery/Category | -- Tracking code works for all 4 cases of states of fetchGallery/Category | ||
-- fetchGallery takes precedence | -- fetchGallery takes precedence | ||
if fetchGallery then | if fetchGallery then | ||
wikidata = p. | wikidata, consistent = p._hasGalleryConsistent(qid) | ||
if default or not fetchCategory or (consistent and wikidata) then | |||
return selectTrackingCat(galleryTrackingCats,wikidata,consistent, | |||
default,title) | |||
end | |||
end | end | ||
if fetchCategory then | |||
local cat_wikidata, cat_consistent = p._hasCategoryConsistent(qid,true) | |||
if not fetchGallery or (cat_consistent and cat_wikidata) then | |||
return selectTrackingCat(categoryTrackingCats,cat_wikidata, | |||
cat_consistent,default,title) | |||
end | |||
return selectTrackingCat(galleryTrackingCats,wikidata,consistent, | |||
default,title) | |||
end | |||
return "" -- nothing fetched, nothing tracked | |||
end | |||
local function _createFormatting(args) | |||
local formatting = {} | |||
formatting.linktext = args.linktext | |||
formatting.lcfirst = yesNo(args.lcfirst) | |||
formatting.bold = yesNo(args.bold) | |||
formatting.italic = yesNo(args.italic) | |||
formatting.nowrap = yesNo(args.nowrap) | |||
return formatting | |||
return | |||
end | end | ||
Line 472: | Line 531: | ||
function p.getGallery(frame) | function p.getGallery(frame) | ||
local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false}) | local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false}) | ||
return p._getCommons("",args[1] | return p._getCommons("",args[1],args.search,args.fallback,_createFormatting(args),args.qid) | ||
end | end | ||
Line 478: | Line 537: | ||
function p.getCategory(frame) | function p.getCategory(frame) | ||
local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false}) | local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false}) | ||
local retval = p._getCommons("Category",args[1], | local retval = p._getCommons("Category", args[1], | ||
args.search, args.fallback, _createFormatting(args), args.qid | |||
) | |||
if args.tracking then | if args.tracking then | ||
local default = nil | local default = nil | ||
Line 484: | Line 545: | ||
default = "Category:"..args[1] | default = "Category:"..args[1] | ||
end | end | ||
retval = retval..p._tracking(default,false,true,args.qid) | retval = retval..p._tracking(default, false, true, args.qid) | ||
end | end | ||
return retval | return retval | ||
Line 491: | Line 552: | ||
function p.getGalleryOrCategory(frame) | function p.getGalleryOrCategory(frame) | ||
local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false}) | local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false}) | ||
local retval = p._getGalleryOrCategory(args[1],args. | local retval = p._getGalleryOrCategory( | ||
args[1], args.search, args.fallback, _createFormatting(args), args.qid | |||
) | |||
if args.tracking then | if args.tracking then | ||
retval = retval..p._tracking(args[1],true,true,args.qid) | retval = retval..p._tracking(args[1],true,true,args.qid) | ||
Line 515: | Line 578: | ||
function p.getGalleryAndCategory(frame) | function p.getGalleryAndCategory(frame) | ||
local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false}) | local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false}) | ||
return p._getGalleryAndCategory(args[1],args[2] | return p._getGalleryAndCategory(args[1], args[2], | ||
args. | args.categoryText, args.oneSearch, _createFormatting(args), args.qid) | ||
end | end | ||
function p.tracking(frame) | function p.tracking(frame) | ||
local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false}) | local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false}) | ||
return p._tracking(args[1],args.fetchGallery,args.fetchCategory,args.qid) | return p._tracking(args[1], args.fetchGallery, args.fetchCategory, args.qid) | ||
end | end | ||
return p | return p |
Revision as of 14:48, 31 May 2024
Documentation for this module may be created at Module:Commons link/doc
require('strict')
-- Module to find commons galleries and categories based on wikidata entries
local getArgs = require('Module:Arguments').getArgs
local yesNo = require('Module:Yesno')
local p = {}
-- Check if string is a valid QID
-- Argument: QID to check
-- Returns: valid (bool)
local function _validQID(qid)
return qid and mw.ustring.find(qid,"^[Qq]%d+$")
end
-- Check if string is a valid wikidata property string
-- Argument: property string to check
-- Returns: valid (bool)
local function _validProp(prop)
return prop and mw.ustring.find(prop,"^[Pp]%d+$")
end
local function _lcfirst(s)
return mw.ustring.lower(mw.ustring.sub(s,1,1))..mw.ustring.sub(s,2)
end
-- Format displayed linktext
-- Arguments:
-- s = string to display
-- formatting = formatting table:
-- formatting.linktext = if defined, override s
-- formatting.lcfirst = lower case the first letter in display
-- formatting.bold = whether to bold the display
-- formatting.italic = whether to italicize the display
-- formatting.nowrap = set nowrapping
-- Returns:
-- formatted string
local function _formatResult(s, formatting)
local resultVal = formatting.linktext or s
if formatting.lcfirst then
resultVal = _lcfirst(resultVal)
end
local style = ""
if formatting.italic then style = "font-style:italic; " end
if formatting.bold then style = style.."font-weight:bold; " end
if formatting.nowrap then style = style.."white-space:nowrap; " end
if style ~= "" then
resultVal = '<span style="'..mw.text.trim(style)..'">'..resultVal..'</span>'
end
return resultVal
end
-- Get title, namespace, and QID for current page
-- Arguments:
-- qid = testing only: get title of alternative page with QID=qid
-- nsQid = whether to return the ns of the qid page or current
-- Returns:
-- title, namespace (string), qid of current page (or test page)
local function _getTitleQID(qid,nsQid)
local titleObject = mw.title.getCurrentTitle()
-- look up qid for current page (if not testing)
local nsText = mw.ustring.gsub(titleObject.nsText,"_"," ")
if not _validQID(qid) then
qid = mw.wikibase.getEntityIdForCurrentPage()
return titleObject.text, nsText, qid
end
-- testing-only path: given a qid, determine title
-- always use namespace from current page (to suppress tracking cat)
qid = qid:upper()
local title = mw.wikibase.getSitelink(qid) or ""
-- strip any namespace from sitelink
local firstColon = mw.ustring.find(title,':',1,true)
local qidNsText = ""
if firstColon then
qidNsText = mw.ustring.sub(title,1,firstColon-1)
title = mw.ustring.sub(title,firstColon+1)
end
if nsQid then
return title, qidNsText, qid
end
return title, nsText, qid
end
-- Lookup Commons gallery in Wikidata
-- Arguments:
-- qid = QID of current article
-- fetch = whether to lookup Commons sitelink (bool)
-- commonsSitelink = default value for Commons sitelink
-- Returns:
-- categoryLink = name of Commons category, nil if nothing is found
-- consistent = multiple wikidata fields are examined: are they consistent?
-- commonsSitelink = commons sitelink for current article
local function _lookupGallery(qid,fetch,commonsSitelink)
if not _validQID(qid) then
return nil, true, nil
end
qid = qid:upper()
local galleryLink = nil
local consistent = true
-- look up commons sitelink for article, use if not category
if fetch then
commonsSitelink = mw.wikibase.getSitelink(qid,"commonswiki") or commonsSitelink
end
if commonsSitelink and mw.ustring.sub(commonsSitelink,1,9) ~= "Category:" then
galleryLink = commonsSitelink
end
-- P935 is the "commons gallery" property for this article
local P935 = mw.wikibase.getBestStatements(qid, "P935")[1]
if P935 and P935.mainsnak.datavalue then
local gallery = P935.mainsnak.datavalue.value
if galleryLink and galleryLink ~= gallery then
consistent = false
else
galleryLink = gallery
end
end
return galleryLink, consistent, commonsSitelink
end
-- Find fallback category by looking up Commons sitelink of different page
-- Arguments:
-- qid = QID for current article
-- property = property that refers to other article whose sitelink to return
-- Returns: either category-stripped name of article, or nil
local function _lookupFallback(qid,property)
if not _validQID(qid) or not _validProp(property) then
return nil
end
qid = qid:upper()
property = property:upper()
-- If property exists on current article, get value (other article qid)
local value = mw.wikibase.getBestStatements(qid, property)[1]
if value and value.mainsnak.datavalue and value.mainsnak.datavalue.value.id then
-- Look up Commons sitelink of other article
local sitelink = mw.wikibase.getSitelink(value.mainsnak.datavalue.value.id,"commonswiki")
-- Check to see if it starts with "Category:". If so, strip it and return
if sitelink and mw.ustring.sub(sitelink,1,9) == "Category:" then
return mw.ustring.sub(sitelink,10)
end
end
return nil
end
-- Find Commons category by looking in wikidata
-- Arguments:
-- qid = QID of current article
-- fetch = whether to lookup Commons sitelink (bool)
-- commonsSitelink = default value for Commons sitelink
-- Returns:
-- categoryLink = name of Commons category, nil if nothing is found
-- consistent = multiple wikidata fields are examined: are they consistent?
-- commonsSitelink = commons sitelink for current article
local function _lookupCategory(qid, fetch, commonsSitelink)
if not _validQID(qid) then
return nil, true, nil
end
qid = qid:upper()
local categoryLink = nil
local consistent = true
-- look up commons sitelink for article, use if starts with "Category:"
if fetch then
commonsSitelink = mw.wikibase.getSitelink(qid,"commonswiki") or commonsSitelink
end
if commonsSitelink and mw.ustring.sub(commonsSitelink,1,9) == "Category:" then
categoryLink = mw.ustring.sub(commonsSitelink,10)
end
-- P910 is the "topic's main category". Look for commons sitelink there
local fallback = _lookupFallback(qid,"P910")
if fallback then
if categoryLink and categoryLink ~= fallback then
consistent = false
qid = nil
else
categoryLink = fallback
end
end
-- P1754 is the "list's main category". Look for commons sitelink there
fallback = _lookupFallback(qid,"P1754")
if fallback then
if categoryLink and categoryLink ~= fallback then
consistent = false
qid = nil
else
categoryLink = fallback
end
end
-- P373 is the "commons category" property for this article. This is
-- a low-quality field, so should only be used as a last resort.
if categoryLink == nil and _validQID(qid) then
local P373 = mw.wikibase.getBestStatements(qid, "P373")[1]
if P373 and P373.mainsnak.datavalue then
categoryLink = P373.mainsnak.datavalue.value
consistent = true -- P373 is never used if anything else is available
end
end
return categoryLink, consistent, commonsSitelink
end
-- Does the article have a Commons gallery, and is it consistent?
-- Arguments:
-- qid = QID to lookup in wikidata (for testing only)
-- Returns:
-- filename at Commons, bool: is wikidata consistent for this article?
function p._hasGalleryConsistent(qid)
local wp_title, wp_ns
wp_title, wp_ns, qid = _getTitleQID(qid)
return _lookupGallery(qid,true)
end
-- Does the article have a corresponding Commons gallery?
-- Arguments:
-- qid = QID to lookup in wikidata (for testing only)
-- Returns:
-- filename at Commons if so, false if not
function p._hasGallery(qid)
local galleryLink, consistent = p._hasGalleryConsistent(qid)
return consistent and galleryLink
end
-- Does the article have a Commons category? Is wikidata consistent for that?
-- Arguments:
-- qid = QID to lookup in wikidata (for testing only)
-- prefix = whether to add "Category:" to return string (default true)
-- Returns:
-- filename at Commons, bool: consistent
function p._hasCategoryConsistent(qid,prefix)
if prefix == nil then
prefix = true
end
local wp_title, wp_ns
wp_title, wp_ns, qid = _getTitleQID(qid)
local categoryLink, consistent = _lookupCategory(qid,true)
if categoryLink and prefix then
categoryLink = "Category:"..categoryLink
end
return categoryLink, consistent
end
-- Does the article have a corresponding Commons category?
-- Arguments:
-- qid = QID to lookup in wikidata (for testing only)
-- prefix = whether to add "Category:" to return string (default true)
-- Returns:
-- filename at Commons if so, blank if not
function p._hasCategory(qid,prefix)
local categoryLink, consistent = p._hasCategoryConsistent(qid,prefix)
return consistent and categoryLink
end
-- Create Commons link corresponding to current article
-- Arguments:
-- namespace = namespace in Commons ("" for galleries)
-- default = use as Commons link, don't access wikidata
-- search = string to search for
-- fallback = string to search for if wikidata fails
-- formatting = formatting parameters
-- qid = QID to lookup in wikidata (for testing only)
-- Returns:
-- formatted wikilink to Commons in specified namespace
function p._getCommons(namespace,default,search,fallback,formatting,qid)
local nsColon
if not namespace or namespace == "" then
nsColon = ""
else
nsColon = namespace..":"
end
if default then
return "[[Commons:"..nsColon..default.."|".._formatResult(default,formatting).."]]"
end
if search then
return "[[Commons:Special:Search/"..nsColon..search.."|".._formatResult(search,formatting).."]]"
end
local wp_title, wp_ns
wp_title, wp_ns, qid = _getTitleQID(qid)
local commonsLink = nil
local consistent = true
if nsColon == "" then
commonsLink, consistent = _lookupGallery(qid,true)
elseif namespace:lower() == "category" then
commonsLink, consistent = _lookupCategory(qid,true)
end
-- use wikidata if consistent
if commonsLink and consistent then
return "[[Commons:"..nsColon..commonsLink.."|".._formatResult(commonsLink,formatting).."]]"
end
-- if not consistent, fall back to search and add to tracking cat
-- construct default result (which searches for title)
local searchResult = "[[Commons:Special:Search/"..nsColon..(fallback or wp_title)
.."|".._formatResult(fallback or wp_title,formatting).."]]"
if not consistent and wp_ns == "" then
local friendlyNS
if nsColon == "" then
friendlyNS = "gallery"
else
friendlyNS = namespace:lower()
end
searchResult = searchResult.."[[Category:Inconsistent wikidata for Commons "..friendlyNS.."]]"
end
return searchResult
end
-- Returns "best" Commons link: first look for gallery, then try category
-- Arguments:
-- default = use as Commons link, don't access wikidata
-- search = string to search for
-- fallback = string to search for if wikidata lookup fails
-- formatting = formatting parameters
-- qid = QID to lookup in wikidata (for testing only)
-- Returns:
-- formatted wikilink to Commons "best" landing page
function p._getGalleryOrCategory(default, search, fallback, formatting, qid)
if default then
return "[[Commons:"..default.."|".._formatResult(default,formatting).."]]"
end
if search then
return "[[Commons:Special:Search/"..search.."|".._formatResult(search,formatting).."]]"
end
local wp_title, wp_ns
wp_title, wp_ns, qid = _getTitleQID(qid)
local trackingCats = ""
local galleryLink, consistent, commonsSitelink = _lookupGallery(qid,true)
-- use wikidata if either sitelink or P935 exist, and they both agree
if galleryLink and consistent then
return "[[Commons:"..galleryLink.."|".._formatResult(galleryLink,formatting).."]]"
end
if not consistent and wp_ns == "" then
trackingCats = "[[Category:Inconsistent wikidata for Commons gallery]]"
end
-- if gallery is not good, fall back looking for category
local categoryLink
categoryLink, consistent = _lookupCategory(qid,false,commonsSitelink)
if categoryLink and consistent then
return "[[Commons:Category:"..categoryLink.."|".._formatResult(categoryLink,formatting).."]]"..trackingCats
end
if not consistent and wp_ns == "" then
trackingCats = trackingCats.."[[Category:Inconsistent wikidata for Commons category]]"
end
-- return search result looking for title as last attempt
return "[[Commons:Special:Search/" .. (fallback or wp_title) ..
"|" .. _formatResult(fallback or wp_title,formatting) .. "]]" .. trackingCats
end
-- Return link(s) Commons gallery, or category, or both from wikidata
-- Arguments:
-- defaultGallery = default gallery link to use, instead of wikidata
-- defaultCategory = default category link to use, instead of wikidata
-- categoryText = if both gallery and category, text to use in category link ("category" by default)
-- oneSearch = only emit one search result
-- formatting = formatting parameters
-- qid = qid of page to lookup in wikidata (testing only)
function p._getGalleryAndCategory(defaultGallery, defaultCategory,
categoryText, oneSearch, formatting, qid
)
local wp_title, wp_ns
wp_title, wp_ns, qid = _getTitleQID(qid)
categoryText = categoryText or "category"
local trackingCats = ""
local galleryLink, galleryConsistent
local commonsSitelink = nil
if defaultGallery then
galleryLink = defaultGallery
galleryConsistent = true
else
galleryLink, galleryConsistent, commonsSitelink = _lookupGallery(qid,true)
end
local galleryGood = galleryLink and galleryConsistent
if not galleryConsistent and wp_ns == "" then
trackingCats = "[[Category:Inconsistent wikidata for Commons gallery]]"
end
local categoryLink, categoryConsistent
if defaultCategory then
categoryLink = defaultCategory
categoryConsistent = true
else
categoryLink, categoryConsistent = _lookupCategory(qid,defaultGallery,commonsSitelink)
end
local categoryGood = categoryLink and categoryConsistent
if not categoryConsistent and wp_ns == "" then
trackingCats = trackingCats.."[[Category:Inconsistent wikidata for Commons category]]"
end
local firstLink
-- construct default result (which searches for title)
local searchResult = "[[Commons:Special:Search/"..wp_title.."|".._formatResult(wp_title,formatting).."]]"
if not oneSearch then
searchResult = searchResult.." ([[Commons:Special:Search/Category:"..wp_title.."|"..categoryText.."]])"
end
local linkText = nil
if galleryGood then
firstLink = galleryLink
linkText = galleryLink
elseif categoryGood then
firstLink = "Category:"..categoryLink
linkText = categoryLink
else
return searchResult..trackingCats
end
local resultVal = "[[Commons:"..firstLink.."|".._formatResult(linkText,formatting).."]]"
if galleryGood and categoryGood then
resultVal = resultVal.." ([[Commons:Category:"..categoryLink.."|"..categoryText.."]])"
end
return resultVal..trackingCats
end
-- Compare two titles with their namespaces stripped
local function titleMatch(s1,s2)
s1 = s1 or ""
s2 = s2 or ""
s1 = mw.ustring.gsub(s1,"^[^:]+:","")
s2 = mw.ustring.gsub(s2,"^[^:]+:","")
return s1 == s2
end
local galleryTrackingCats = {
commons_link_on_wikidata = '[[Category:Commons link is on Wikidata]]',
commons_link_defined_as_pagename = '[[Category:Commons link is defined as the pagename]]',
commons_link_locally_defined = '[[Category:Commons link is locally defined]]',
commons_link_from_wikidata = '[[Category:Commons link from Wikidata]]',
commons_link_is_pagename = '[[Category:Commons link is the pagename]]',
inconsistent = '[[Category:Inconsistent wikidata for Commons gallery]]'
}
local categoryTrackingCats = {
commons_link_on_wikidata = '[[Category:Commons category link is on Wikidata]]',
commons_link_defined_as_pagename = '[[Category:Commons category link is defined as the pagename]]',
commons_link_locally_defined = '[[Category:Commons category link is locally defined]]',
commons_link_from_wikidata = '[[Category:Commons category link from Wikidata]]',
commons_link_is_pagename = '[[Category:Commons category link is the pagename]]',
inconsistent = '[[Category:Inconsistent wikidata for Commons category]]'
}
local function selectTrackingCat(trackingCats,wikidata,consistent,default,title)
if not consistent then
return trackingCats.inconsistent
end
if default then
-- construct warning message
if default == wikidata then
return trackingCats.commons_link_on_wikidata
end
local warning = ""
if wikidata then
local generateWarning = require('Module:If preview')._warning
warning = generateWarning({
"Commons link does not match Wikidata – [[Template:Commons_category#Resolving_discrepancies|please check]]"
})
end
if titleMatch(default,title) then
return trackingCats.commons_link_defined_as_pagename .. warning
end
return trackingCats.commons_link_locally_defined .. warning
end
if wikidata then
return trackingCats.commons_link_from_wikidata
end
return trackingCats.commons_link_is_pagename
end
-- Figure out tracking categories and editor warnings
-- Arguments:
-- default = Commons link argument passed to template
-- fetchGallery = whether to fetch a gallery from Wikidata
-- fetchCategory = whether to fetch a category from Wikidata
-- qid = force a qid for testing
-- Returns:
-- tracking category and possible user warning
--
-- Note: the logic for the tracking is quite different than the logic
-- for generating Commons links (above). Thus, it is separated into another
-- function for code clarity and maintainability. This should not seriously
-- affect performance: server time is dominated by fetching wikidata entities,
-- and those entities should be cached and shared between the Commons generating
-- code and this tracking code.
function p._tracking(default, fetchGallery, fetchCategory, qid)
local title, wp_ns, wp_qid = _getTitleQID(qid,true)
if wp_ns ~= "" then
title = wp_ns..":"..title
end
-- only track if test or namespace=article or namespace=category
if not (qid or wp_ns == "" or wp_ns == "Category") then
return ""
end
-- determine title and namespace of wikidata and wp article
local wikidata = nil
local consistent = nil
-- Tracking code works for all 4 cases of states of fetchGallery/Category
-- fetchGallery takes precedence
if fetchGallery then
wikidata, consistent = p._hasGalleryConsistent(qid)
if default or not fetchCategory or (consistent and wikidata) then
return selectTrackingCat(galleryTrackingCats,wikidata,consistent,
default,title)
end
end
if fetchCategory then
local cat_wikidata, cat_consistent = p._hasCategoryConsistent(qid,true)
if not fetchGallery or (cat_consistent and cat_wikidata) then
return selectTrackingCat(categoryTrackingCats,cat_wikidata,
cat_consistent,default,title)
end
return selectTrackingCat(galleryTrackingCats,wikidata,consistent,
default,title)
end
return "" -- nothing fetched, nothing tracked
end
local function _createFormatting(args)
local formatting = {}
formatting.linktext = args.linktext
formatting.lcfirst = yesNo(args.lcfirst)
formatting.bold = yesNo(args.bold)
formatting.italic = yesNo(args.italic)
formatting.nowrap = yesNo(args.nowrap)
return formatting
end
-- Testing-only entry point for _getTitleQID
function p.getTitleQID(frame)
local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false})
local text, ns, qid = _getTitleQID(args[1],args[2])
return text..","..ns..","..(qid or "nil")
end
-- Testing-only entry point for _lookupFallback
function p.lookupFallback(frame)
local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false})
local fallback = _lookupFallback(args[1],args[2])
return fallback or "nil"
end
-- Find the Commons gallery page associated with article
function p.getGallery(frame)
local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false})
return p._getCommons("",args[1],args.search,args.fallback,_createFormatting(args),args.qid)
end
-- Find the Commons category page associated with article
function p.getCategory(frame)
local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false})
local retval = p._getCommons("Category", args[1],
args.search, args.fallback, _createFormatting(args), args.qid
)
if args.tracking then
local default = nil
if args[1] then
default = "Category:"..args[1]
end
retval = retval..p._tracking(default, false, true, args.qid)
end
return retval
end
function p.getGalleryOrCategory(frame)
local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false})
local retval = p._getGalleryOrCategory(
args[1], args.search, args.fallback, _createFormatting(args), args.qid
)
if args.tracking then
retval = retval..p._tracking(args[1],true,true,args.qid)
end
return retval
end
function p.hasGallery(frame)
local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false})
return p._hasGallery(args.qid) or ""
end
function p.hasCategory(frame)
local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false})
return p._hasCategory(args.qid) or ""
end
function p.hasGalleryOrCategory(frame)
local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false})
return p._hasGallery(args.qid) or p._hasCategory(args.qid) or ""
end
function p.getGalleryAndCategory(frame)
local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false})
return p._getGalleryAndCategory(args[1], args[2],
args.categoryText, args.oneSearch, _createFormatting(args), args.qid)
end
function p.tracking(frame)
local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false})
return p._tracking(args[1], args.fetchGallery, args.fetchCategory, args.qid)
end
return p