Modiwl:Plain sister
Documentation for this module may be created at Modiwl:Plain sister/doc
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, '[[' .. target .. '|' .. display .. ']]' )
end
end
if #links == 0 then -- links table length is zero
return ''
end
return '<li class="sisitem">'
.. '<span class="sisicon" style="padding-right:1ex;">[[Image:Wikimedia-logo.svg|frameless|18px|link=Special:sitematrix|alt=Sister Projects.]]</span>'
.. '[[Special:sitematrix|sister projects]]: ' .. table.concat( links, ', ' )
.. '.</li>'
end
return p
-- Debug console testing:
-- =p.interprojetPart(mw.getCurrentFrame():newChild{title='nop',args={wikidata='Q23308118'}})