پودمان:Commons link

    از دزفول ویکی

    توضیحات این پودمان می‌تواند در پودمان:Commons link/توضیحات قرار گیرد.

    -- Module to find commons galleries and categories based on wikidata entries
    local getArgs = require('Module:Arguments').getArgs
    local yesNo = require('Module:Yesno')
    local generateWarning = require('Module:If preview')._warning
    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(doit,s)
    	if doit then
    		return mw.ustring.lower(mw.ustring.sub(s,1,1))..mw.ustring.sub(s,2)
    	end
    	return s
    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
    	resultVal = _lcfirst(formatting.lcfirst,resultVal)
    	if formatting.italic then resultVal = "<i>" .. resultVal .. "</i>" end
    	if formatting.bold then resultVal = "<b>" .. resultVal .. "</b>" end
    	if formatting.nowrap then 
    		resultVal = '<span style="white-space:nowrap;">' .. 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
    	-- purposefully do not look in P373 ("commons category" property)
    	-- if P373 is desired, then restore search code here
    
    	-- 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
    		else
    			categoryLink = fallback
    		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 = "نگارخانه"
    		elseif namespace:lower() == 'category' then namespace = 'رده'
    			friendlyNS = namespace
    		end
    		searchResult = searchResult.."[[رده:ویکی‌داده متناقض برای "..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 = "[[رده:ویکی‌داده متناقض برای نگارخانه انبار]]"
    	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.."[[رده:ویکی‌داده متناقض برای رده انبار]]"
    	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 "رده"
    	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 = "[[رده:ویکی‌داده متناقض برای نگارخانه انبار]]"
    	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.."[[رده:ویکی‌داده متناقض برای رده انبار]]"
    	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 = '[[رده:پیوند انبار در ویکی‌داده است]]',
    	commons_link_defined_as_pagename = '[[رده:پیوند انبار مانند نام صفحه تعریف شده‌است]]',
    	commons_link_locally_defined = '[[رده:پیوند انبار به‌صورت محلی تعریف شده‌است]]',
    	commons_link_from_wikidata = '[[رده:پیوند انبار از ویکی‌داده]]',
    	commons_link_is_pagename = '[[رده:پیوند انبار نام صفحه است]]',
    	inconsistent = '[[رده:ویکی‌داده متناقض برای نگارخانه انبار]]'
    }
    
    local categoryTrackingCats = {
    		commons_link_on_wikidata = '[[رده:پیوند رده انبار در ویکی‌داده است]]',
    		commons_link_defined_as_pagename = '[[رده:پیوند رده انبار مانند نام صفحه تعریف شده‌است]]',
    		commons_link_locally_defined = '[[رده:پیوند رده انبار که به صورت محلی تعریف شده است]]',
    		commons_link_from_wikidata = '[[رده:پیوند رده انبار از ویکی‌داده]]',
    		commons_link_is_pagename = '[[رده:پیوند رده انبار همان نام صفحه است]]',
    		inconsistent = '[[رده:ویکی‌داده متناقض برای رده انبار]]'
    	}
    
    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
    			warning = generateWarning({
    					"پیوند ویکی‌انبار با ویکی‌داده منطبق نیست – [[:en:Template:Commons_category#Resolving_discrepancies|لطفاً بررسی کنید]]"
    				})
    		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 == "رده") 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
    		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)
    	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