Module:Creator

From Wikisource
Jump to navigation Jump to search
--[=[
WORK IN PROGRESS

The Creator module provides a class object that represents a single author or
other "creating entity" (e.g. an organisation)

This is a Lua-only module that is intended as a core module for other modules,
rather than being directly called by templates.

Generally, the object is initialised with newCreator( id_or_title ) and properties
are accessed though members of the returned object (the same general princible
as proofreadPage.newIndex, mw.title, etc.)
]=]

local p = {} --p stands for package

-- This is provided by the core Scribunto library
local util = require 'libraryUtil'

-- TODO: ship out to /data when this gets big enough to be a memory burden
local PROPS = {
	isA = 'P31',
	title = 'P1476',
}

local ENTITIES = {
	human = 'Q5',
}

--[=[
Util function: return true if the item is in the given table
]=]
local function valueIn( t, v )
	for _, tv in pairs( t ) do
		if tv == v then
			return true
		end
	end
	return false
end


--[=[
Get the entity for a QID, or a page title
]=]
local function getEntity( titleOrQid ) 
	local item
	if type(titleOrQid) == 'table' then
		-- this is already Wikibase item data
		item = titleOrQid
	elseif string.match( titleOrQid, 'Q%d+', 1 ) then
		-- it's a QID
		item = mw.wikibase.getEntity( titleOrQid )
	else
		-- assume it's a page title
		item = mw.wikibase.getEntityIdForTitle( titleOrQid )	
	end
	return item
end

local function getPropIds( entity, prop )
	local ids = {}
	
	if not entity.claims[ prop ] then
		return nil
	end
	
	for _, v in pairs( entity.claims[ prop ] ) do
		if v.mainsnak.snaktype == 'value' and v.mainsnak.datatype == 'wikibase-item' then
			table.insert( ids, v.mainsnak.datavalue.value.id )
		end
	end
	return ids
end

local function getPropEntities( entity, prop )
	local ids = getPropIds( entity, prop )
	if not ids then
		return nil	
	end
	local ents = {}
	for _, id in pairs( ids ) do
		table.insert( ents, mw.wikibase.getEntity( id ) )
	end
	return ents
end

local function getLocalStringProp( entity, prop )
	local lang = 'en'
	if not entity.claims[ prop ] then
		error("No claim found for property: " .. prop)
	end
	return entity.claims[ prop ][ 1 ].mainsnak.datavalue.value.text
end

local function getStringProp( entity, prop )
	if not entity.claims[ prop ] then
		error("No claim found for property: " .. prop)
	end
	return entity.claims[ prop ][ 1 ].mainsnak.datavalue.value
end

local function getYearProp( entity, prop )
	
	if not entity.claims[ prop ] then
		return nil
	end
	
	local v = entity.claims[ prop ][ 1 ]
	if v.mainsnak.datavalue.type == 'time' then
		local timestamp = v.mainsnak.datavalue.value.time
		timestamp = timestamp
			:gsub( '^%+', '' )
			:gsub( '-.*', '' )
			
		-- decade precision
		if v.mainsnak.datavalue.value.precision == 8 then
			timestamp = timestamp .. 's'
		end
		return timestamp
	end
end

local function getLocalSiteLink( entity )
	return entity:getSitelink( 'enwikisource' )	
end

--[=[
Get the local lable of the entity - this is probably a good string to use
in links
]=]
local function getLocalLabel( entity )
	local localLabel = entity.labels['en']
	if localLabel then
		return localLabel.value	
	end
	return nil
end

--[=[
The main entry point
]=]
function p.newCreator( titleOrQid )
	local obj = {}

	-- the function that checks if a call to a method is using . instead of :
	local checkSelfFunc = util.makeCheckSelfFunction( 'Module:Work',
		'aWork', obj, 'work object' );

	local item = getEntity( titleOrQid )

	local data = {
		item = item
	}

	return setmetatable( obj, {
		__eq = item.equals,
		__lt = item.__lt,
		__tostring = function ( t )
			return item.prefixedText
		end,
		__index = function ( t, k )
			
			-- lazily load the relevant properties only when actually needed

			if k == 'wsPage' then
				if data.wsPage == nil then
					data.wsPage = getLocalSiteLink( item )
				end
				return data.wsPage
			end
			
			if k == 'label' then
				if data.label == nil then
					data.label = getLocalLabel( item )
				end
				return data.label
			end
			
			return data[k]
		end,
		__newindex = function ( t, k, v )
			error( "index '" .. k .. "' is read only", 2 )
		end
	} )
end

return p