Module:Commons link
require('Module:No globals')
 
 -- 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,&quot;^[Qq]%d+$&quot;)
 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,&quot;^[Pp]%d+$&quot;)
 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 = &quot;&quot;
 	if formatting.italic then style = &quot;font-style:italic; &quot; end
 	if formatting.bold then style = style..&quot;font-weight:bold; &quot; end
 	if formatting.nowrap then style = style..&quot;white-space:nowrap; &quot; end
     if style ~= &quot;&quot; then
     	resultVal = '&lt;span style=&quot;'..mw.text.trim(style)..'&quot;&gt;'..resultVal..'&lt;/span&gt;'
     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,&quot;_&quot;,&quot; &quot;)
 	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 &quot;&quot;
 	-- strip any namespace from sitelink
 	local firstColon = mw.ustring.find(title,':',1,true)
 	local qidNsText = &quot;&quot;
 	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,&quot;commonswiki&quot;) or commonsSitelink
 	end
 	if commonsSitelink and mw.ustring.sub(commonsSitelink,1,9) ~= &quot;Category:&quot; then
 		galleryLink = commonsSitelink
 	end
 	-- P935 is the &quot;commons gallery&quot; property for this article
 	local P935 = mw.wikibase.getBestStatements(qid, &quot;P935&quot;)[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,&quot;commonswiki&quot;)
 		-- Check to see if it starts with &quot;Category:&quot;. If so, strip it and return
 		if sitelink and mw.ustring.sub(sitelink,1,9) == &quot;Category:&quot; 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 &quot;Category:&quot;
 	if fetch then
 		commonsSitelink = mw.wikibase.getSitelink(qid,&quot;commonswiki&quot;) or commonsSitelink
 	end
 	if commonsSitelink and mw.ustring.sub(commonsSitelink,1,9) == &quot;Category:&quot; then
 		categoryLink = mw.ustring.sub(commonsSitelink,10)
 	end
 	-- P910 is the &quot;topic's main category&quot;. Look for commons sitelink there
 	local fallback = _lookupFallback(qid,&quot;P910&quot;)
 	if fallback then
 		if categoryLink and categoryLink ~= fallback then
 			consistent = false
 			qid = nil
 		else
 			categoryLink = fallback
 		end
 	end
 	-- P1754 is the &quot;list's main category&quot;. Look for commons sitelink there
 	fallback = _lookupFallback(qid,&quot;P1754&quot;)
 	if fallback then
 		if categoryLink and categoryLink ~= fallback then
 			consistent = false
 			qid = nil
 		else
 			categoryLink = fallback
 		end
 	end
     -- P373 is the &quot;commons category&quot; 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, &quot;P373&quot;)[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 &quot;Category:&quot; 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 = &quot;Category:&quot;..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 &quot;Category:&quot; 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 (&quot;&quot; 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 == &quot;&quot; then
 		nsColon = &quot;&quot;
 	else
 		nsColon = namespace..&quot;:&quot;
 	end
 	if default then
 		return &quot;[[Commons:&quot;..nsColon..default..&quot;|&quot;.._formatResult(default,formatting)..&quot;]]&quot;
 	end
 	if search then
 		return &quot;[[Commons:Special:Search/&quot;..nsColon..search..&quot;|&quot;.._formatResult(search,formatting)..&quot;]]&quot;
 	end
 	local wp_title, wp_ns
 	wp_title, wp_ns, qid = _getTitleQID(qid)
 	local commonsLink = nil
 	local consistent = true
 	if nsColon == &quot;&quot; then
 		commonsLink, consistent = _lookupGallery(qid,true)
 	elseif namespace:lower() == &quot;category&quot; then
 		commonsLink, consistent = _lookupCategory(qid,true)
 	end
 	-- use wikidata if consistent
 	if commonsLink and consistent then
 		return &quot;[[Commons:&quot;..nsColon..commonsLink..&quot;|&quot;.._formatResult(commonsLink,formatting)..&quot;]]&quot;
 	end
 	-- if not consistent, fall back to search and add to tracking cat
 	-- construct default result (which searches for title)
 	local searchResult = &quot;[[Commons:Special:Search/&quot;..nsColon..(fallback or wp_title)
 		..&quot;|&quot;.._formatResult(fallback or wp_title,formatting)..&quot;]]&quot;
 	if not consistent and wp_ns == &quot;&quot; then
 		local friendlyNS
 		if nsColon == &quot;&quot; then
 			friendlyNS = &quot;gallery&quot;
 		else
 			friendlyNS = namespace:lower()
 		end
 		searchResult = searchResult..&quot;[[Category:Inconsistent wikidata for Commons &quot;..friendlyNS..&quot;]]&quot;
 	end
 	return searchResult
 end
 
 -- Returns &quot;best&quot; 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 &quot;best&quot; landing page
 function p._getGalleryOrCategory(default, search, fallback, formatting, qid)
 	if default then
 		return &quot;[[Commons:&quot;..default..&quot;|&quot;.._formatResult(default,formatting)..&quot;]]&quot;
 	end
 	if search then
 		return &quot;[[Commons:Special:Search/&quot;..search..&quot;|&quot;.._formatResult(search,formatting)..&quot;]]&quot;
 	end
 	local wp_title, wp_ns
 	wp_title, wp_ns, qid = _getTitleQID(qid)
 	local trackingCats = &quot;&quot;
 	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 &quot;[[Commons:&quot;..galleryLink..&quot;|&quot;.._formatResult(galleryLink,formatting)..&quot;]]&quot;
 	end
 	if not consistent and wp_ns == &quot;&quot; then
 		trackingCats = &quot;[[Category:Inconsistent wikidata for Commons gallery]]&quot;
 	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 &quot;[[Commons:Category:&quot;..categoryLink..&quot;|&quot;.._formatResult(categoryLink,formatting)..&quot;]]&quot;..trackingCats
 	end
 	if not consistent and wp_ns == &quot;&quot; then
 		trackingCats = trackingCats..&quot;[[Category:Inconsistent wikidata for Commons category]]&quot;
 	end
 	-- return search result looking for title as last attempt
 	return &quot;[[Commons:Special:Search/&quot; .. (fallback or wp_title) ..
 		&quot;|&quot; .. _formatResult(fallback or wp_title,formatting) .. &quot;]]&quot; .. 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 (&quot;category&quot; 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 &quot;category&quot;
 	local trackingCats = &quot;&quot;
 	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 == &quot;&quot; then
 		trackingCats = &quot;[[Category:Inconsistent wikidata for Commons gallery]]&quot;
 	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 == &quot;&quot; then
 		trackingCats = trackingCats..&quot;[[Category:Inconsistent wikidata for Commons category]]&quot;
 	end
 	local firstLink
 	-- construct default result (which searches for title)
 	local searchResult = &quot;[[Commons:Special:Search/&quot;..wp_title..&quot;|&quot;.._formatResult(wp_title,formatting)..&quot;]]&quot;
 	if not oneSearch then
 		searchResult = searchResult..&quot; ([[Commons:Special:Search/Category:&quot;..wp_title..&quot;|&quot;..categoryText..&quot;]])&quot;
 	end
 	local linkText = nil
 	if galleryGood then
 		firstLink = galleryLink
 		linkText = galleryLink
 	elseif categoryGood then
 		firstLink = &quot;Category:&quot;..categoryLink
 		linkText = categoryLink
 	else
 		return searchResult..trackingCats
 	end
 	local resultVal = &quot;[[Commons:&quot;..firstLink..&quot;|&quot;.._formatResult(linkText,formatting)..&quot;]]&quot;
 	if galleryGood and categoryGood then
 		resultVal = resultVal..&quot; ([[Commons:Category:&quot;..categoryLink..&quot;|&quot;..categoryText..&quot;]])&quot;
 	end
 	return resultVal..trackingCats
 end
 
 -- Compare two titles with their namespaces stripped
 local function titleMatch(s1,s2)
 	s1 = s1 or &quot;&quot;
 	s2 = s2 or &quot;&quot;
     s1 = mw.ustring.gsub(s1,&quot;^[^:]+:&quot;,&quot;&quot;)
     s2 = mw.ustring.gsub(s2,&quot;^[^:]+:&quot;,&quot;&quot;)
     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 = &quot;&quot;
 		if wikidata then
 			warning = generateWarning({
 					&quot;Commons link does not match Wikidata – [[Template:Commons_category#Resolving_discrepancies|please check]]&quot;
 				})
 		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 ~= &quot;&quot; then
 		title = wp_ns..&quot;:&quot;..title
 	end
 	-- only track if test or namespace=article or namespace=category
 	if not (qid or wp_ns == &quot;&quot; or wp_ns == &quot;Category&quot;) then
 		return &quot;&quot;
 	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 &quot;&quot; -- 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..&quot;,&quot;..ns..&quot;,&quot;..(qid or &quot;nil&quot;)
 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 &quot;nil&quot;
 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(&quot;&quot;,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(&quot;Category&quot;, args[1], 
 		args.search, args.fallback, _createFormatting(args), args.qid
 	)
 	if args.tracking then
 		local default = nil
 		if args[1] then
 			default = &quot;Category:&quot;..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 &quot;&quot;
 end
 
 function p.hasCategory(frame)
 	local args = getArgs(frame,{frameOnly=true,parentOnly=false,parentFirst=false})
 	return p._hasCategory(args.qid) or &quot;&quot;
 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 &quot;&quot;
 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