Modul:Wikidata/Filterers
Vzhled
require "Modul:No globals"
local p = {}
local lib = require 'Modul:Wikidata/lib'
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.formatError('invalid-datatype', snak.property, snak.datatype, 'monolingualtext'))
end
if lib.IsSnakValue(snak) then
if snak.datavalue.value.language == lang then
return true
end
end
return false
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.class then -- TODO: separate function or handler
local datatype = Statements[math.random(1, #Statements)].mainsnak.datatype
if datatype == 'wikibase-item' or datatype == 'wikibase-property' then
local class = options.class:upper()
oldStatements, Statements = Statements, {}
for _, statement in pairs(oldStatements) do
if lib.IsSnakValue(statement.mainsnak) then
local function IsInClass(id)
local entity = mw.wikibase.getEntity(id)
local Classes = entity:getBestStatements('P279')
if Classes then
for _, class in pairs(Classes) do
if lib.IsSnakValue(class.mainsnak) then
local id = lib.getEntityIdFromValue(class.mainsnak.datavalue.value)
if class == id or IsInClass(id) then
return true
end
end
end
end
return false
end
local entity = mw.wikibase.getEntity(lib.getEntityIdFromValue(statement.mainsnak.datavalue.value))
local Instances = entity:getBestStatements('P31')
if Instances then
for _, instance in pairs(Instances) do
if lib.IsSnakValue(instance.mainsnak) then
local id = lib.getEntityIdFromValue(instance.mainsnak.datavalue.value)
if class == id or IsInClass(id) then
table.insert(Statements, statement)
break
end
end
end
end
end
end
if #Statements == 0 then return {} end
else
return error(lib.formatError('invalid-datatype', options.property, 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:Time'
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:Time'
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
-- 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['withlang qualifiers'] then
oldQualifiers, Qualifiers = Qualifiers, {}
for _, snak in pairs(oldQualifiers) do
if IsInLanguage(snak, options['qualifier withlang']) then
table.insert(Qualifiers, snak)
end
end
end
if options['class qualifiers'] then
-- TODO: wait for separate function or handler
end
if options['sort qualifiers'] then
local Sorters = require "Modul:Wikidata/Sorters"
Qualifiers = Sorters.sortQualifiers(Qualifiers, options)
end
Qualifiers = applyLimit(Qualifiers, options['limit qualifiers'])
return Qualifiers
end
function p.filterReferences(references, options)
local options = lib.common.cleanArgs(options)
local References, oldReferences = references, {}
if options.ref == '#any' then
return references
else
oldReferences, References = References, {}
for _, snaks in pairs(oldReferences.snaks) do
-- TODO
end
end
return References
end
function p.test()
local time1 = os.clock()
local entity = mw.wikibase.getEntity('Q183')
local time2 = os.clock() - time1
return time2, #entity.claims.P1082, #p.filterStatements(entity.claims.P1082, {})
end
return p