Module:Plain sister

local p = {}

local getArgs = require('Module:Arguments').getArgs

-- table of site data local sites = { -- interwiki prefix: parameter,      label and            site id (for Wikidata) ['w'] =			 { 'wikipedia',  'Wikipedia article', 'enwiki' }, ['c'] =         { 'commons',     'Commons gallery',   'commonswiki' }, ['c:Category'] = { 'commonscat', 'Commons category',  'commonswiki' }, ['q'] =         { 'wikiquote',   'quotes',            'enwikiquote' }, ['n'] =         { 'wikinews',    'news',              'enwikinews' }, ['wikt'] =      { 'wiktionary',  'definition',        'enwiktionary' }, ['b'] =         { 'wikibooks',   'textbook',          'enwikibooks' }, ['v'] =         { 'wikiversity', 'course',            'enwikiversity' }, ['wikispecies'] ={ 'wikispecies', 'taxonomy',         'specieswiki' }, ['voy'] =       { 'wikivoyage',  'travel guide',      'enwikivoyage' }, ['d'] =         { 'wikidata',    'Wikidata item',     'wikidatawiki' }, ['m'] =         { 'meta',        'Meta',              'metawiki' } }

-- sites is display order (keyed as above) local sites_in_order = {'w', 'c', 'c:Category', 'q', 'n', 'wikt', 'b', 'v', 'wikispecies', 'voy', 'd', 'm' }

-- some properties are not wanted from certain transitive links -- for example, the P921 (main topic) should not add the Commons category -- this is a map of WD property -> WD site ID keys local transitiveLinkBlacklist = { P921 = { 'commonswiki', 'wikiquote', 'wikinews', 'wiktionary', 'wikiversity', 'wikivoyage', 'meta' }, }

-- Get the item associated with the current page, or specified by the 'wikidata' -- parameter (of either the module invocation, or the parent template). -- @return mw.wikibase.entity function getItem( args ) local item = nil -- Firstly, see if the calling tempate or module has a "wikidata" argument. if args.wikidata then item = mw.wikibase.getEntity( args.wikidata ) end -- Failing thar just use the current page's item. if item == nil then item = mw.wikibase.getEntity end return item end

-- Get the page title of the first sitelink found on the target item for the -- given property. -- @return string|nil function getFirstSitelink( item, property, sitename ) local statements = item:getBestStatements( property ) if #statements > 0 then -- Go through each 'edition of' statement. for _, statement in pairs( statements ) do			-- datavalue is missing if set to "unknown value" if statement['mainsnak']['datatype'] == 'wikibase-item' and statement['mainsnak']['datavalue'] then local otherItemId = statement['mainsnak']['datavalue']['value']['id'] local otherItem = mw.wikibase.getEntity( otherItemId ) local sitelink = otherItem:getSitelink( sitename ) -- If the parent has the required sitelink, return it. if sitelink ~= '' then -- mw.log(sitename, property, sitelink) return sitelink end end -- if		end end return nil end

function listContains( list, item ) for _, v in pairs( list ) do		if v == item then return true end end return false end

function transitivePropertyBlacklisted( prop, wdSitelinkKey ) -- reject prop/key pairs that we don't want local blacklisted = transitiveLinkBlacklist[ prop ] and listContains( transitiveLinkBlacklist[ prop ], wdSitelinkKey ) return blacklisted end

function p.getLinks( args ) local item = getItem( args )

local links = {}

-- Build all the wikitext links. for prefix, site in pairs( sites ) do		local val = nil local wd_sitelink_key = site[3] local arg_name = site[1] -- Allow overriding of individual sitelinks. if args[ arg_name ] then val = args[ arg_name ] end if not val and wd_sitelink_key ~= '' and item then -- fetch it from wikidata val = item:getSitelink( wd_sitelink_key ) if wd_sitelink_key == 'wikidatawiki' and item.id then val = item.id 			elseif wd_sitelink_key == 'commonswiki' and val then -- we have link to commons local catFlag = (#val>9 and string.sub(val, 1, 9) == 'Category:') if (arg_name == 'commonscat' and catFlag==false) or (arg_name=='commons' and catFlag==true) then val = nil -- link is to a wrong namespace so let's nuke it				elseif (arg_name =='commonscat' and catFlag==true) then val = string.sub(val,10) -- trim 'Category:' from the front end end end -- Commons gallery. if not val and arg_name == 'commons' and item then local statements = item:getBestStatements('P935' ) -- get commons gallery page from P935 property if statements[1] and statements[1].mainsnak.datavalue then val = statements[1].mainsnak.datavalue.value end end -- Commons category. if not val and arg_name == 'commonscat' and item then local statements = item:getBestStatements('P373' )  -- get commons category page from P373 property if statements[1] and statements[1].mainsnak.datavalue then val = statements[1].mainsnak.datavalue.value end end

-- edition or translation of (P629) -- category's main topic (P301) -- Wikimedia portal's main topic (P1204) -- main subject (P921) if item then for _,prop in pairs( { 'P629', 'P301', 'P1204', 'P921' } ) do				if not val and not transitivePropertyBlacklisted( prop, wd_sitelink_key ) then local workSitelink = getFirstSitelink( item, prop, wd_sitelink_key ) if workSitelink ~= nil then val = workSitelink break end end end end

if val then links[ prefix ] = val end end -- tidy up redundancies in the WD data -- strip redundant commons category prefix if links[ 'c:Category' ] then links[ 'c:Category' ] = links[ 'c:Category' ]:gsub( '^Category:', '' ) end -- the gallery is exactly the same as the category, so just keep the category if links[ 'c' ] and links[ 'c:Category' ] and ( 'Category:' .. links[ 'c:Category' ]) == links[ 'c' ] then links[ 'c' ] = nil end return links end

-- Get an HTML list of all links to all sister projects. function p.interprojetPart( frame ) local args = getArgs(frame) local item = getItem( args )

local link_data = p.getLinks( args ) local links = {}

-- iterate the links in the desired order and construct Wikitext links for k, v in pairs( sites_in_order ) do		if link_data[ v ] then local display = sites[ v ][2] local target = v .. ':' .. link_data[v] table.insert( links,  .. display ..  ) end end

if #links == 0 then -- links table length is zero return '' end

return ' ' .. ' '		.. 'sister projects:&#32;' .. table.concat( links, ',&#32;' ) .. '.' end

return p

-- Debug console testing: -- =p.interprojetPart(mw.getCurrentFrame:newChild{title='nop',args={wikidata='Q23308118'}})