Module:Edition

-- 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. --

require('strict')

local instanceOfProp = 'P31' local authorProp = 'P50' local editionOrTranslationOfProp = 'P629' local equivalentClassProp = 'P1709' local topicsMainWikimediaPortalProp = 'P1151';

-- Insert a value into a table, but not if it's already there. local 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. local function get_author_sitelink( authorItem ) local siteLink = authorItem:getSitelink( mw.language.getContentLanguage.code .. 'wikisource' ) if ( siteLink ~= nil ) then return siteLink end local 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

-- Get the schema.org URL for the itemtype of the given item. local 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

-- Create the HTML (including wikitext link) for all provided authors, -- and add it to the given authorLinks table (for later concatenation). local 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,  .. authorHtmlStr ..  ) end end 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. local 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. -- local 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. -- local function inline( args ) local item = getItem( args ) local outHtml = mw.html.create if ( item == nil ) then outHtml:wikitext( ' Unable to determine the Wikidata item to use ' ) return tostring( outHtml ) end

-- Make sure it's an edition. local editionOrTranslationOfStmts = item:getBestStatements( editionOrTranslationOfProp ) if #editionOrTranslationOfStmts == 0 then outHtml:wikitext( ' ' .. item.id .. ' is not an edition or translation of a work (missing P629) ' ) 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 =  .. label ..  end outHtml:wikitext( title .. ' ' );

-- Publication date local publicationDate = item:formatPropertyValues( 'P577' ) outHtml:wikitext( '(' .. publicationDate.value .. ') ' )

-- Authors if args.hideauthors == nil or args.hideauthors == '' then local authorList = author_list( args ) if authorList ~= '' then outHtml:wikitext( ' by ' .. authorList .. ' ' ) end end

-- 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 = '' 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'}}) -- local 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 = ' ' if args.indicator ~= nil then badgeOut = '' .. badgeOut .. ' '			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

-- Exported method. local 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 = propItem:getLabel if not propLabel then if propItem.aliases.en and propItem.aliases.en[1].value then propLabel = propItem.aliases.en[1].value else propLabel = propertyId end end 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; }