Documentación del módulo
Los editores pueden experimentar en la zona de pruebas de este módulo.
Por favor, añade las categorías e interwikis a la subpágina de documentación. Subpáginas de este módulo.
--[=[
Importado de la Wikisource inglesa en esta versión: 
https://en.wikisource.org/w/index.php?title=Module:Work&oldid=12000562

Se trata de un módulo que genera un objeto (una tabla) cuyos elementos o 
propiedades son las propiedades de una edición/obra ]=]

local p = {} --p stands for package

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

-- Creator objects, used for authors, etc
local Creator = require('Módulo:Creador')

-- Module constants
p.TYPES = {
	EDITION = 'edition',
	WORK = 'work',
	ARTICLE = 'article' --scholarly articles
}

-- TODO: ship out to /data when this gets big enough to be a memory burden
local PROPS = {
	isA = 'P31',
	title = 'P1476',
	pubDate = 'P577',
	author = 'P50',
	translator = 'P655',
	editor = 'P98',
	illustrator = 'P110',
	introducer = 'P2679',
	volume = 'P478',
	issue = 'P433',
	pages = 'P304',
	publishedIn = 'P1433',
	inception = 'P571',
	commonsFile = 'P996'
}

local ENTITIES = {
	human = 'Q5',
	edition = 'Q3331189',
	scholarlyArticle = 'Q13442814',
	creativeWork = 'Q17537576',
}

--[=[
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 )
	elseif string.find( titleOrQid, '%.pdf' ) or string.find( titleOrQid, '%.djvu' ) then
		-- es un índice!
		index = mw.ext.proofreadPage.newIndex( titleOrQid )
		Qid = index.fields.Wikidata
		item = mw.wikibase.getEntity( Qid )
	else
		-- assume it's a page title
		-- TODO only return the ID and look it up (expensive) only if actually used
		item = mw.wikibase.getEntity(
			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 = 'es'
	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 getFiles( entity, prop )
-- obtener los archivos de commons para enlazar directamente al proyecto 
-- de transcripcion.
	if not entity.claims[ prop ] then
		return nil
	end
	
	local files = {}
	for _, t in pairs(entity.claims[ prop ]) do
		table.insert(files, t.mainsnak.datavalue.value)
	end
	return files
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( 'eswikisource' )	
end

--[=[
Get the 'type' of the work

Options are: edition, articles (as in journal articles), or works
]=]
local function getWorkType( entity )
	local isVals = getPropIds( entity, PROPS.isA )
	
	if valueIn( isVals, ENTITIES.edition ) then
		return p.TYPES.EDITION
	elseif valueIn( isVals, ENTITIES.scholarlyArticle ) then
		return p.TYPES.ARTICLE
	end
	
	-- assume it's a work, but maybe we should be more careful?
	return p.TYPES.WORK
end

--[=[
Get the list of Creator objects for this property
]=]
local function getCreatorList( item, prop )
	local creators = getPropEntities( item, prop )
	
	if not creators or #creators == 0 then
		return nil
	end
	
	local list = {}
	for _, v in pairs( creators ) do
		local creatorObject = Creator.newCreator( v )
		table.insert( list, creatorObject )
	end
	return list
end

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

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

	local item = getEntity( titleOrQid )
	
	local index
	if string.find( titleOrQid, '%.pdf' ) or string.find( titleOrQid, '%.djvu' ) then
		index = titleOrQid
	end
	
	if not item then
		mw.error( 'Failed to look up item: ' .. titleOrQid )	
	end

	local data = {
		item = item,
		index = index,
	}
	
	local getType = function ()
		if data.type == nil then
			data.type = getWorkType( item )
		end
		return data.type
	end
	
	return setmetatable( obj, {
		__eq = item.equals,
		__lt = item.__lt,
		__tostring = function ( t )
			return item.prefixedText
		end,
		__index = function ( t, k )
			
			-- lazily load the relvant properties only when actually needed
			if k == 'type' then
				return getType()
			end

			if k == 'wsPage' then
				if data.wsPage == nil then
					data.wsPage = getLocalSiteLink( item )
				end
				return data.wsPage
			end

			if k == 'title' then
				if data.title == nil then
					data.title = getLocalStringProp( item, PROPS.title )
				end
				return data.title
			end
			
			if k == 'pubYear' then
				if data.pubYear == nil then
					
					local theDate
					-- for works specifically, check inception first
					if getType() == 'work' then
						theDate = getYearProp( item, PROPS.inception )
					end
					
					if not theDate then
						theDate = getYearProp( item, PROPS.pubDate )
					end
					
					data.pubYear = theDate
				end
				return data.pubYear
			end
			
			if k == 'author' then
				if data.author == nil then
					data.author = getCreatorList( item, PROPS.author )
				end
				return data.author
			end
			
			if k == 'illustrator' then
				if data.illustrator == nil then
					data.illustrator = getCreatorList( item, PROPS.illustrator )
				end
				return data.illustrator
			end
			
			if k == 'introducer' then
				if data.introducer == nil then
					data.introducer = getCreatorList( item, PROPS.introducer )
				end
				return data.introducer
			end
			
			if k == 'editor' then
				if data.editor == nil then
					data.editor = getCreatorList( item, PROPS.editor )
				end
				return data.editor
			end
			
			if k == 'translator' then
				if data.translator == nil then
					data.translator = getCreatorList( item, PROPS.translator )
				end
				return data.translator
			end
			
			if k == 'parentWork' then
				if data.parentWork == nil then
					local id = getPropIds( item, PROPS.publishedIn )[ 1 ]
					if id then
						data.parentWork = p.newWork( id )
					end
				end
				return data.parentWork
			end
			
			if k == 'commonsFile' then
				if data.commonsFile == nil then
					if data.index == nil then
						data.commonsFile = getFiles( item, PROPS.commonsFile )
					else
						data.commonsFile = {data.index}
					end
				end
				return data.commonsFile
			end
			
			return data[k]
		end,
		__newindex = function ( t, k, v )
			error( "index '" .. k .. "' is read only", 2 )
		end
	} )
end

return p