Module:Edition
From Suresh Joshi
Documentation for this module may be created at Module:Edition/doc
--------------------------------------------------------------------------------
-- Organisation of this module: the exports are listed at the bottom; their
-- direct functions are just above there, and supporting functions are higher
-- up.
--
-- Please add testcases before modifying anything.
--
--------------------------------------------------------------------------------
instanceOfProp = 'P31'
authorProp = 'P50'
editionOrTranslationOfProp = 'P629'
equivalentClassProp = 'P1709'
topicsMainWikimediaPortalProp = 'P1151';
--------------------------------------------------------------------------------
-- Insert a value into a table, but not if it's already there.
function tableInsertUnique( theTable, value )
for _, item in pairs( theTable ) do
if item == value then
-- Already present
return
end
end
-- Otherwise, add the new value.
table.insert( theTable, value )
end
--------------------------------------------------------------------------------
-- For the given author item, find the Wikisource sitelink. If there isn't one,
-- check to see if there the author has a topicsMainWikimediaPortal statement,
-- and then see if that portal has a sitelink instead.
function get_author_sitelink( authorItem )
local siteLink = authorItem:getSitelink( mw.language.getContentLanguage().code .. 'wikisource' )
if ( siteLink ~= nil ) then
return siteLink
end
portalStatements = authorItem:getBestStatements( topicsMainWikimediaPortalProp )
for _, mainPortal in pairs( portalStatements ) do
local mainPortalId = mainPortal['mainsnak']['datavalue']['value']['id']
local mainPortalItem = mw.wikibase.getEntity( mainPortalId )
siteLink = mainPortalItem:getSitelink( mw.language.getContentLanguage().code .. 'wikisource' )
end
return siteLink
end
--------------------------------------------------------------------------------
-- Create the HTML (including wikitext link) for all provided authors,
-- and add it to the given authorLinks table (for later concatenation).
function process_authors( authorLinks, authors )
if authors == nil or #authors == 0 then
return
end
for _, author in pairs( authors ) do
local authorId = author['mainsnak']['datavalue']['value']['id']
local authorItem = mw.wikibase.getEntity( authorId )
local siteLink = get_author_sitelink( authorItem )
local authorName = authorItem:getLabel()
if siteLink ~= nil then
authorName = mw.title.new( siteLink ).text
end
local authorHtml = mw.html.create('span')
:attr('itemprop', 'author')
:attr('itemscope', '')
:attr('itemtype', getSchemaorgItemtype( authorItem ) )
local authorNameHtml = authorHtml:tag( 'span' )
authorNameHtml:attr( 'itemprop', 'name' )
:wikitext( authorName )
local authorHtmlStr = tostring( authorHtml )
if siteLink == nil then
tableInsertUnique( authorLinks, authorHtmlStr )
else
tableInsertUnique( authorLinks, '[[' .. siteLink .. '|' .. authorHtmlStr .. ']]' )
end
end
end
--------------------------------------------------------------------------------
-- Get the schema.org URL for the itemtype of the given item.
function getSchemaorgItemtype( item )
local schemaPrefix = 'http://schema.org/'
for _, instanceOf in pairs( item:getBestStatements( instanceOfProp ) ) do
local instanceOfId = instanceOf['mainsnak']['datavalue']['value']['id']
local instanceOfItem = mw.wikibase.getEntity( instanceOfId )
-- Now go through each of the instance-of item's class statements,
-- seeing if we can find a matching schema.org URL.
for _, equivClass in pairs( instanceOfItem:getBestStatements( equivalentClassProp ) ) do
local val = equivClass['mainsnak']['datavalue']['value']
if string.sub( val, 1, #schemaPrefix ) == schemaPrefix then
-- This is a schema.org URL.
return val
end
end
end
-- If we've not figured it out by now, give up with the default.
return schemaPrefix .. 'Thing'
end
--------------------------------------------------------------------------------
-- Exported method.
--
function author_list( args )
local item = getItem( args )
if item == nil then
return ''
end
local authorLinks = {}
-- Collect the authors of this item.
local authors = item:getBestStatements( authorProp )
process_authors( authorLinks, authors )
-- Also collect the authors of the parent work.
local works = item:getBestStatements( editionOrTranslationOfProp )
for _, work in pairs( works ) do
local workId = work['mainsnak']['datavalue']['value']['id']
local workItem = mw.wikibase.getEntity( workId )
authors = workItem:getBestStatements( authorProp )
if #authors > 0 then
process_authors( authorLinks, authors )
end
end
-- Output the final list of links.
local outHtml = mw.html.create()
local separator = args.separator or ', '
local last_separator = args.last_separator or ', and '
local i = 1
for _, link in pairs( authorLinks ) do
outHtml:wikitext( link )
if i == ( #authorLinks - 1 ) then
outHtml:wikitext( last_separator )
elseif #authorLinks > 1 and i ~= #authorLinks then
outHtml:wikitext( separator )
end
i = i + 1
end
return tostring( outHtml )
end
--------------------------------------------------------------------------------
-- Exported method.
--
function inline( args )
local item = getItem( args )
local outHtml = mw.html.create()
mw.logObject(args)
mw.logObject(item)
if ( item == nil ) then
outHtml:wikitext( '<span class="error">Unable to determine the Wikidata item to use</span>' )
return tostring( outHtml )
end
-- Make sure it's an edition.
local editionOrTranslationOfStmts = item:getBestStatements( editionOrTranslationOfProp )
if #editionOrTranslationOfStmts == 0 then
outHtml:wikitext( '<span class="error">' .. item.id .. ' is not an edition or translation of a work (missing P629)</span>' )
return tostring( outHtml )
end
-- Title/label.
local title = item:getSitelink( 'enwikisource' )
local label = item:getLabel( 'en' )
local hasWikisourcePage = false
if title == nil or title == '' then
title = label
else
hasWikisourcePage = true
title = '[[' .. title .. '|' .. label .. ']]'
end
outHtml:wikitext( title .. ' ' );
-- Publication date
local publicationDate = item:formatPropertyValues( 'P577' )
outHtml:wikitext( '(' .. publicationDate.value .. ') ' )
-- Scanned file on Wikimedia Commons.
if not hasWikisourcePage then
-- Add links to Index page or Commons file.
local hasIndexOrCommonsLink = false
local scannedFileOnWikimediaCommons = 'P996'
local scannedFileOnWikimediaCommonsStmts = item:getBestStatements( scannedFileOnWikimediaCommons )
for _, stmt in pairs( scannedFileOnWikimediaCommonsStmts ) do
local commonsFilename = stmt['mainsnak']['datavalue']['value']
outHtml:wikitext( ' ' .. mw.getCurrentFrame():expandTemplate{ title = 'Small scan link', args = { commonsFilename } } )
hasIndexOrCommonsLink = true;
end
-- Add link to the IA item if no links were added above.
if not hasIndexOrCommonsLink then
local internetArchiveIdProp = 'P724'
local internetArchiveIdStmts = item:getBestStatements( internetArchiveIdProp )
for _, stmt in pairs( internetArchiveIdStmts ) do
local internetArchiveId = stmt['mainsnak']['datavalue']['value']
outHtml:wikitext( ' ' .. mw.getCurrentFrame():expandTemplate{ title = 'IA small link', args = { internetArchiveId } } )
end
end
end
-- Wikidata and Wikipedia links.
local img = '[[File:Wikidata-books-task-force-logo.svg|20px|alt=Wikidata books task force logo|link=d:' .. item.id .. '|View on Wikidata]]'
outHtml:wikitext( img )
return tostring( outHtml )
end
--------------------------------------------------------------------------------
-- Exported method. Get wikitext for displaying an edition's badges from Wikidata.
-- To get an indicator, pass args.indicator = true
-- Testing: =p.badge({args={wikidata='Q75043199'}})
--
function badge( args )
local item = getItem( args )
if not ( item and item.sitelinks and item.sitelinks.enwikisource and item.sitelinks.enwikisource.badges ) then
return ''
end
local badges = item.sitelinks.enwikisource.badges
local out = ''
for _, badge in pairs( badges ) do
local badgeOut = ''
local badgeItem = mw.wikibase.getEntity( badge )
local badgeName = ''
local wikisourceBadgeClass = 'Q75042035'
if badgeItem.claims.P31[1].mainsnak.datavalue.value.id == wikisourceBadgeClass and badgeItem.claims.P18 ~= nil then
local imageName = badgeItem.claims.P18[1].mainsnak.datavalue.value
if mw.wikibase.getLabel( badge ) ~= nil then
badgeName = mw.wikibase.getLabel( badge )
end
badgeOut = '<span class="indicator-badge">[[File:' .. imageName .. '|16px|link=Help:Text status|' .. badgeName .. ']]</span>'
if args.indicator ~= nil then
badgeOut = '<indicator name="wikisource-badge-' .. badgeName .. '">' .. badgeOut .. '</indicator>'
end
if args.category ~= nil and badgeItem.claims.P910 ~= nil then
local categoryQid = badgeItem.claims.P910[1].mainsnak.datavalue.value.id
local category = mw.wikibase.getEntity( categoryQid )
badgeOut = badgeOut .. '[[' .. category.sitelinks.enwikisource.title .. ']]'
end
out = out .. badgeOut
end
end
return mw.getCurrentFrame():preprocess( out )
end
--------------------------------------------------------------------------------
-- Get an Item based on what's passed in the 'wikidata' or 'page' parameters of
-- the args, or the current page's ID otherwise.
function getItem( args )
local id = nil
-- If args is a table with an appropriate element, use it.
if type( args ) == 'table' then
if args.wikidata ~= '' and args.wikidata ~= nil then
id = args.wikidata
elseif args.wikidata_id ~= '' and args.wikidata_id ~= nil then
id = args.wikidata_id
elseif args.page ~= '' and args.page ~= nil then
local title = mw.title.new( args.page )
id = mw.wikibase.getEntityIdForTitle( title.nsText .. title.text )
-- If no entity for this page, maybe it's a subpage and we should look for the root page's entity.
if id == nil then
id = mw.wikibase.getEntityIdForTitle( title.nsText .. title.rootText )
end
end
end
if type( args ) == 'string' and args ~= '' then
id = args
end
return mw.wikibase.getEntity( id )
end
--------------------------------------------------------------------------------
-- Exported method.
function authority_control( args )
local item = getItem( args )
-- Gather every 'external-id' statement.
local out = mw.html.create( '' )
for propertyId,claims in pairs( item.claims) do
local propItem = getItem( propertyId )
for _,claim in pairs( claims ) do
if claim.mainsnak.datatype == 'external-id' then
local propLabel = propertyId
if propItem.aliases.en[1].value then
propLabel = propItem.aliases.en[1].value
end
-- mw.logObject(propItem)
out:wikitext( '* [[' .. propLabel .. ']]: ' .. claim.mainsnak.datavalue.value .. '\n' )
end
end
end
return tostring( out )
end
--------------------------------------------------------------------------------
-- Export all public functions.
return {
-- =p.author_list({args={wikidata='Q28913867'}})
author_list = function( frame ) return author_list( frame.args ) end;
-- =p.inline({args={wikidata_id='Q28913867'}})
inline = function( frame ) return inline( frame.args ) end;
-- =p.badge({args={wikidata='Q28020002'}})
badge = function( frame ) return badge( frame.args ) end;
-- =p.authority_control({args={wikidata='Q19035838'}})
authority_control = function( frame ) return authority_control( frame.args ) end;
}