Modul:Wikidata/Filterers

Dokumentaciju za ovaj modul možete napraviti na stranici Modul:Wikidata/Filterers/dok

require "Modul:No globals"

local p = {}

local lib = require 'Modul:Wikidata/lib'

local function checkLimit(sequence, limit)
	local limit = limit and tonumber(limit)
	if limit then
		return #sequence >= limit
	end
	return true
end

local function applyLimit(sequence, limit)
	local limit = limit and tonumber(limit)
	if limit then
		while #sequence > limit do
			table.remove(sequence)
		end
	end
	return sequence
end

local function IsInLanguage(snak, lang)
	if snak.datatype ~= 'monolingualtext' then
		return error(lib.raiseInvalidDatatype('IsInLanguage', snak.datatype, 'monolingualtext'))
	else
		return lib.IsSnakValue(snak) and snak.datavalue.value.language == lang
	end
end

function p.filterStatementsFromEntity(entity, options)
	if not options.property or options.property == '' then
		return error(lib.formatError('param-not-provided', 'property'))
	end
	if not entity or not entity.claims then
		return {}
	end
	local property = mw.ustring.upper(options.property)
	if not entity.claims[property] then
		return {}
	end

	return p.filterStatements(entity.claims[property], options)
end

function p.filterStatements(statements, options)
	local options = lib.common.cleanArgs(options)
	local Statements, oldStatements = statements, {}
	-- apply filter by rank
	if not options.rank or options.rank ~= "all" then
		oldStatements, Statements = Statements, {}
		if not options.rank or options.rank == "best" or options.rank == "valid" then
			if options.rank == "best" then
				for _, statement in pairs(oldStatements) do
					if statement.rank == "preferred" then
						table.insert(Statements, statement)
					end
				end
				if #Statements == 0 then
					for _, statement in pairs(oldStatements) do
						if statement.rank == "normal" then
							table.insert(Statements, statement)
						end
					end
				end
			else
				for _, statement in pairs(oldStatements) do
					if statement.rank ~= "deprecated" then
						table.insert(Statements, statement)
					end
				end
			end
		else
			for _, statement in pairs(oldStatements) do
				if statement.rank == options.rank then
					table.insert(Statements, statement)
				end
			end
		end
		if #Statements == 0 then return {} end
	end
	-- apply filter by source
	if options.ref then
		oldStatements, Statements = Statements, {}
		for _, statement in pairs(oldStatements) do
			if statement.references then
				if #p.filterReferences(statement.references, options) > 0 then
					table.insert(Statements, statement)
				end
			end
		end
		if #Statements == 0 then return {} end
	end
	-- apply filter by snak type
	if not lib.IsOptionTrue(options, 'showspecial') then
		oldStatements, Statements = Statements, {}
		for _, statement in pairs(oldStatements) do
			if lib.IsSnakValue(statement.mainsnak) then
				table.insert(Statements, statement)
			end
		end
		if #Statements == 0 then return {} end
	end
	-- apply filter by qualifier property
	if options.withqualifier then
		oldStatements, Statements = Statements, {}
		for _, statement in pairs(oldStatements) do
			if statement.qualifiers and statement.qualifiers[options.withqualifier:upper()] then
				table.insert(Statements, statement)
			end
		end
		if #Statements == 0 then return {} end
	end
	-- apply filter by class
	if options.instance then
		local datatype = Statements[math.random(1, #Statements)].mainsnak.datatype
		if datatype == 'wikibase-item' or datatype == 'wikibase-property' then
			local Module = require 'Modul:Wikidata/Tree'
			oldStatements, Statements = Statements, {}
			for _, statement in pairs(oldStatements) do
				if lib.IsSnakValue(statement.mainsnak) then
					local item = lib.getEntityIdFromValue(statement.mainsnak.datavalue.value)
					if Module.IsInstance(item, options) then
						table.insert(Statement, statement)
					end
				end
			end
			if #Statements == 0 then return {} end
		else
			return error(lib.raiseInvalidDatatype('inClass', datatype, {'wikibase-item', 'wikibase-property'}))
		end
	end
	-- apply filter by language
	if options.withlang then
		oldStatements, Statements = Statements, {}
		for _, statement in pairs(oldStatements) do
			if IsInLanguage(statement.mainsnak, options.withlang) then
				table.insert(Statements, statement)
			end
		end
		if #Statements == 0 then return {} end
	end
	-- apply filter by time
	if options.date then
		local date
		local Time = require 'Modul:TimeWikiD'
		if type(options.date) == 'table' then
			date = options.date
		elseif options.date == '#now' then
			date = Time.new(os.date('!*t'))
		--elseif mw.ustring.find(options.date, '^[Pp][1-9]%d-$') then TODO
		else
			local Time = require 'Modul:TimeWikiD'
			date = Time.newFromIso8601(options.date)
		end
		if date then
			oldStatements, Statements = Statements, {}
			local temp_value
			local Formatters = require 'Modul:Wikidata/Formatters'
			local Date = require 'Modul:Wikidata/datum'
			for _, statement in pairs(oldStatements) do
				if statement.qualifiers then
					local Values = {}
					for key, array in pairs(lib.props) do
						for _, prop in pairs(array) do
							if statement.qualifiers[prop] then
								for _, snak in pairs(statement.qualifiers[prop]) do
									if lib.IsSnakValue(snak) then
										Values[key] = Formatters.getRawValue(snak)
										break
									end
								end
							end
						end
					end
					if Values.point then
						if not Date.IsSecondLaterThanFirst(date, Values.point) then
							if not temp_value then
								Statements = { statement }
								temp_value = Values.point
							else
								if Date.IsSecondLaterThanFirst(Values.point, temp_value) then
									Statements = { statement }
									temp_value = Values.point
								elseif Date.AreDatesSame(temp_value, Values.point) then
									table.insert(Statements, statement)
								end
							end
						end
					else
						if Values.begin then
							if Date.IsSecondLaterThanFirst(Values.begin, date) then
								if not Values.ending then
									table.insert(Statements, statement)
								elseif Date.IsSecondLaterThanFirst(date, Values.ending) then
									table.insert(Statements, statement)
								end
							end
						elseif Values.ending then
							if Date.IsSecondLaterThanFirst(date, Values.ending) then
								if not Values.begin then
									table.insert(Statements, statement)
								elseif Date.IsSecondLaterThanFirst(Values.begin, date) then
									table.insert(Statements, statement)
								end
							end
						end
					end
				end
			end
			if #Statements == 0 then return {} end
		else
			return error(lib.formatError('invalid-date', options.date))
		end
	end
	if lib.IsOptionTrue(options, 'withlabel') then
		local datatype = Statements[math.random(1, #Statements)].mainsnak.datatype
		if datatype == 'wikibase-item' or datatype == 'wikibase-property' then
			oldStatements, Statements = Statements, {}
			local Formatters = require 'Modul:Wikidata/Formatters'
			for _, statement in pairs() do
				if lib.IsSnakValue(statement.mainsnak) then
					local value = Formatters.getRawValue(statement.mainsnak)
					if mw.wikibase.label(value) then
						table.insert(Statements, statement)
					end
				end
			end
		else
			return error(lib.raiseInvalidDatatype('withlabel', datatype, {'wikibase-item', 'wikibase-property'}))
		end
	end
	-- sort statements if needed
	if options.sort then
		local Sorters = require "Modul:Wikidata/Sorters"
		Statements = Sorters.sortStatements(Statements, options)
	end
	-- apply filter by limit
	Statements = applyLimit(Statements, options.limit)
	return Statements
end

function p.filterQualifiers(qualifiers, options)
	local options = lib.common.cleanArgs(options)
	local Qualifiers, oldQualifiers = qualifiers, {}
	if options['qualifiers withlang'] then
		oldQualifiers, Qualifiers = Qualifiers, {}
		for _, snak in pairs(oldQualifiers) do
			if IsInLanguage(snak, options['qualifiers withlang']) then
				table.insert(Qualifiers, snak)
			end
		end
		if #Qualifiers == 0 then return {} end
	end
	if options['qualifiers class'] then
		local datatype = Qualifiers[math.random(1, #Qualifiers)].datatype
		if datatype == 'wikibase-item' or datatype == 'wikibase-property' then
			oldQualifiers, Qualifiers = Qualifiers, {}
			local Module = require 'Modul:Wikidata/Tree'
			for _, snak in pairs(oldQualifiers) do
				if lib.IsSnakValue(snak) then
					local item = lib.getEntityIdFromValue(snak.datavalue.value)
					if Module.IsInTree(item, options['qualifiers class'], 'P279', 20, {}) then
						table.insert(Qualifiers, snak)
					end
				end
			end
			if #Qualifiers == 0 then return {} end
		else
			return error(lib.raiseInvalidDatatype('inClass', datatype, {'wikibase-item', 'wikibase-property'}))
		end
	end
	if options['sort qualifiers'] then
		local Sorters = require "Modul:Wikidata/Sorters"
		Qualifiers = Sorters.sortQualifiers(Qualifiers, options)
	end
	Qualifiers = applyLimit(Qualifiers, options['qualifiers limit'])
	return Qualifiers
end

function p.filterReferences(references, options)
	local options = lib.common.cleanArgs(options)
	if options.ref == '#any' then
		return references
	end

	local oldReferences, References = references, {}
	if options.ref == 'valid' then
		local props = {'P248', 'P854'} --(require 'Modul:Wikidata/cite').props
		for _, ref in pairs(oldReferences) do
			for _, prop in pairs(props) do
				if ref.snaks[prop] then
					table.insert(References, ref)
				end
			end
		end
	end

	if options.min_ref and not checkLimit(References, options.min_ref) then
		return {}
	end
	return References
end

function p.test(id)
	local entity = mw.wikibase.getEntity(id)
	for prop, claim in pairs(entity.claims) do
		for i, statement in pairs(claim) do
			if statement.references then
				mw.log(prop, i)
				mw.logObject(statement.mainsnak)
				mw.logObject(statement.references)
				return
			end
		end
	end
end

return p