Module:Wikidata/utils

Lua
CodeDiscussionLinksLink count SubpagesDocumentationTestsResultsSandboxLive code All modules

Documentation for this module may be created at Module:Wikidata/utils/doc

Code

-- Higher level functions for maminuplating Wikidata data
local p = {}
local wikidata = require('Module:Wikidata')
local linguistic = require('Module:Linguistic')
local daterange = require('Module:Daterange')
local ppath = require('Module:PropertyPath')

local function itemidfromclaim(claim) -- returns 'Q' + the numeric ID of the mainsnak value of a claim so that it can be used by mw.wikibase.getEntityObject
	if claim.mainsnak.snaktype == 'value' and claim.mainsnak.datavalue.value[ "entity-type"] == 'item'  then
		return 'Q' .. claim.mainsnak.datavalue.value['numeric-id'] 
	else
		return nil
	end
end

local function checkloop(tocheck, target, property, checked) --check if an item is a value of something
	local checked = {}
	for i, item in pairs(tocheck) do
		if item == target then
			return true
		end
        if not checked[item] then
			local newitems = wikidata.getClaims({property = property, item = item, rank= 'valid'})
			if newitems then
				for i, j in pairs(newitems) do
					table.insert(tocheck, itemidfromclaim(j))
				end
			end
		end
		checked[item] = true
    end
    return false
end

local function isinchain(origitem, targetitem, property)
	if (not origitem) or (not targetitem) or (not property) then
		return error()
	end
	return checkloop({origitem}, targetitem, property, {})
end

function p.issuperclass(origitem, targetitem)
	return isinchain(origitem, targetitem, 'P279')
end

function p.isinstance(origitem, targetitem)
	local directinstanceof = wikidata.getClaims({property = 'P31', item = origitem, rank= 'valid'}) -- get the P31 values
	if not directinstanceof then
		return false
	end
	for i, j in pairs(directinstanceof) do -- check if they are superclass of the target item
		if p.issuperclass(itemidfromclaim(j), targetitem) then
			return true
		end
	end
	return false
end

function p.getdate(claim) 
--[[
return a "timedata" object as used by the date modules with the date of an item from the p580, p582 and p585 qualifiers 
	object format:
		* timestamp 28 char string value for the timepoint, or if non the beginning or if none, the end (for easy sorting)
		* timepoint: snak
		* begin: snak
]]--
	local timedata = {}

	if not claim.mainsnak.snaktype == 'value' then -- TODO: handle unknown dates
		return nil
	end
	if not claim.mainsnak.datavalue.type == 'item' then
		return nil -- error() ??
	end
	local q = claim.qualifiers
	if not q or not (q.P585 or q.P580 or q.P582) then
		return nil
	end
	if q.P582 and q.P582[1].snaktype == 'value' then
		timedata.endpoint = q.P582[1].datavalue.value
		timedata.timestamp = q.P582[1].datavalue.value.time
	end
	if q.P580 and q.P580[1].snaktype == 'value' then 
		timedata.startpoint = q.P580[1].datavalue.value
		timedata.timestamp = q.P580[1].datavalue.value.time
	end
	if q.P585 and q.P585[1].snaktype == 'value' then
		timedata.timepoint = q.P585[1].datavalue.value
		timedata.timestamp = q.P585[1].datavalue.value.time
	end
	return timedata
end

function p.claimwithdate(claim, displayparams) -- format an avent with date todo: define displayformats
	if not claim then
		return nil
	end
	local timedata = p.getdate(claim) 
	if timedata then
		return wikidata.formatStatement(claim, displayparams) .. ' ' .. linguistic.inparentheses(daterange.wikibasedaterange(timedata, displayparams.lang), displayparams.lang)
	end
	return wikidata.formatStatement(claim, displayparams)
end

function p.isa(frame)
	local item = frame.args.item or frame.args[1]
	local target = frame.args.target  or frame.args[2]
	mw.log(item)
	mw.log(target)
	return ppath.matches(item, "P31/P27*", target)
end

return p