Mô đun:Commons link
Giao diện
require('strict')-- Module to find commons galleries and categories based on wikidata entrieslocal getArgs = require('Mô đun:Arguments').getArgslocal yesNo = require('Mô đun: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+$")endlocal 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 stringlocal 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 resultValend-- 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 = string.gsub(titleObject.nsText,"_"," ") -- [[phab:T369784]] 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, qidend-- 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 articlelocal 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, commonsSitelinkend-- 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 nillocal 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 nilend-- 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 articlelocal 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, commonsSitelinkend-- 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 notfunction p._hasGallery(qid) local galleryLink, consistent = p._hasGalleryConsistent(qid) return consistent and galleryLinkend-- 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: consistentfunction 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, consistentend-- 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 notfunction p._hasCategory(qid,prefix) local categoryLink, consistent = p._hasCategoryConsistent(qid,prefix) return consistent and categoryLinkend-- 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 namespacefunction 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 = "thư viện" else friendlyNS = namespace:lower() end searchResult = searchResult.."[[Thể loại:Wikidata không nhất quán cho "..friendlyNS.." Commons]]" end return searchResultend-- 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 pagefunction 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 = "[[Thể loại:Wikidata không nhất quán cho thư viện Commons]]" 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.."[[Thể loại:Wikidata không nhất quán cho thể loại Commons]]" end -- return search result looking for title as last attempt return "[[Commons:Special:Search/" .. (fallback or wp_title) .. "|" .. _formatResult(fallback or wp_title,formatting) .. "]]" .. trackingCatsend-- 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 "thể loại" 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 = "[[Thể loại:Wikidata không nhất quán cho thư viện Commons]]" 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.."[[Thể loại:Wikidata không nhất quán cho thể loại Commons]]" 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..trackingCatsend-- Compare two titles with their namespaces strippedlocal function titleMatch(s1,s2) s1 = s1 or "" s2 = s2 or "" s1 = mw.ustring.gsub(s1,"^[^:]+:","") s2 = mw.ustring.gsub(s2,"^[^:]+:","") return s1 == s2endlocal galleryTrackingCats = { commons_link_on_wikidata = '[[Thể loại:Liên kết Commons có ở Wikidata]]', commons_link_defined_as_pagename = '[[Thể loại:Liên kết Commons được định rõ là tên trang]]', commons_link_locally_defined = '[[Thể loại:Liên kết Commons được định rõ cục bộ]]', commons_link_from_wikidata = '[[Thể loại:Liên kết Commons từ Wikidata]]', commons_link_is_pagename = '[[Thể loại:Liên kết Commons là tên trang]]', inconsistent = '[[Thể loại:Wikidata không nhất quán cho thư viện Commons]]'}local categoryTrackingCats = { commons_link_on_wikidata = '[[Thể loại:Liên kết thể loại Commons có ở Wikidata]]', commons_link_defined_as_pagename = '[[Thể loại:Liên kết Commons được định rõ là tên trang]]', commons_link_locally_defined = '[[Thể loại:Liên kết thể loại Commons được định rõ cục bộ]]', commons_link_from_wikidata = '[[Thể loại:Liên kết thể loại Commons từ Wikidata]]', commons_link_is_pagename = '[[Thể loại:Liên kết thể loại Commons là tên trang]]', inconsistent = '[[Thể loại:Wikidata không nhất quán cho thể loại Commons]]' }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('Mô đun:If preview')._warning warning = generateWarning({ "Liên kết Commons không khớp với Wikidata – [[Bản mẫu:Thể loại Commons#Giải quyết sự không nhất quán|vui lòng kiểm tra lại]]" }) 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_pagenameend-- 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 trackedendlocal 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 formattingend-- Testing-only entry point for _getTitleQIDfunction 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 _lookupFallbackfunction 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 articlefunction 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 articlefunction 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 retvalendfunction 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 retvalendfunction p.hasGallery(frame) local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false}) return p._hasGallery(args.qid) or ""endfunction p.hasCategory(frame) local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false}) return p._hasCategory(args.qid) or ""endfunction p.hasGalleryOrCategory(frame) local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false}) return p._hasGallery(args.qid) or p._hasCategory(args.qid) or ""endfunction 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)endfunction p.tracking(frame) local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false}) return p._tracking(args[1], args.fetchGallery, args.fetchCategory, args.qid)endreturn p