Modul:Wikidata/Filterers
Vzhled
require "Modul:No globals"
local p = {}
local lib = require 'Modul:Wikidata/lib'
local function checkLimit(array, limit)
local limit = limit and tonumber(limit)
if limit then
return #array >= limit
end
return true
end
local function applyLimit(array, limit)
local limit = limit and tonumber(limit)
while limit and #array > limit do
table.remove(array)
end
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
local function filterBySnaktype(statement)
return lib.IsSnakValue(statement.mainsnak)
end
local function filterHasTarget(statement, target)
local Formatters = require 'Modul:Wikidata/Formatters'
return Formatters.getRawValue(statement.mainsnak) == target
end
local function filterHasQualifier(statement, prop)
return statement.qualifiers and statement.qualifiers[prop:upper()] and true
end
local function filterHasRanks(statement, ranks)
for _, rank in ipairs(ranks) do
if statement.rank == rank then
return true
end
end
return false
end
local function filterHasReferences(statement, options)
if statement.references then
if #p.filterReferences(statement.references, options) > 0 then
return true
end
end
return false
end
local function filterItemHasLabel(statement, langs)
local datatype = statement.mainsnak.datatype
if datatype ~= 'wikibase-item' and datatype ~= 'wikibase-property' then
return error(lib.raiseInvalidDatatype('filterItemHasLabel', datatype, { 'wikibase-item', 'wikibase-property' }))
end
if lib.IsSnakValue(statement.mainsnak) then
local Formatters = require 'Modul:Wikidata/Formatters'
langs = langs or { 'cs', 'en', 'sk' }
if lib.getLabelInLanguage(Formatters.getRawValue(statement.mainsnak), langs) then
return true
end
end
return false
end
local function filterItemIsInstance(statement, options)
local datatype = statement.mainsnak.datatype
if datatype ~= 'wikibase-item' and datatype ~= 'wikibase-property' then
return error(lib.raiseInvalidDatatype('filterItemIsInstance', datatype, { 'wikibase-item', 'wikibase-property' }))
end
local Module = require 'Modul:Wikidata/Tree'
if lib.IsSnakValue(statement.mainsnak) then
local item = lib.getEntityIdFromValue(statement.mainsnak.datavalue.value)
if Module.IsInstance(item, options) then
return true
end
end
return false
end
local function filterMainsnakInLanguage(statement, options)
return IsInLanguage(statement.mainsnak, options.withlang)
end
local function filter(array, callback, ...)
local i = #array
while i > 0 do
if not callback(array[i], ...) then
table.remove(array, i)
end
i = i - 1
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)
local statements = mw.clone(entity.claims[property])
if not statements then
return {}
end
p.filterStatements(statements, options)
return statements
end
function p.filterStatements(statements, options)
local options = lib.common.cleanArgs(options)
-- apply filter by rank
local rank = options.rank or "valid"
if rank ~= "all" then
if rank == "valid" or rank == "best" then
filter(statements, filterHasRanks, { "normal", "preferred" })
if rank == "best" and #statements > 0 then
for _, statement in ipairs(statements) do
if statement.rank == "preferred" then
filter(statements, filterHasRanks, { "preferred" })
break
end
end
end
else
filter(statements, filterHasRanks, { rank })
end
if #statements == 0 then return end
end
-- apply filter by source
if options.ref then
filter(statements, filterHasReferences, options)
if #statements == 0 then return end
end
-- apply filter by snak type
if not lib.IsOptionTrue(options, 'showspecial') then
filter(statements, filterBySnaktype)
if #statements == 0 then return end
end
-- apply filter by target value
if options.withtarget then
filter(statements, filterHasTarget, options.withtarget)
if #statements == 0 then return end
end
-- apply filter by qualifier property
if options.withqualifier then
filter(statements, filterHasQualifier, options.withqualifier)
if #statements == 0 then return end
end
-- apply filter by language
if options.withlang then
filter(statements, filterMainsnakInLanguage, options)
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
date = Time.newFromIso8601(options.date)
end
if not date then
return error(lib.formatError('invalid-date', tostring(options.date)))
end
local oldStatements = statements
statements = {}
local temp_value
local Formatters = require 'Modul:Wikidata/Formatters'
local Date = require 'Modul:Wikidata/datum'
for _, statement in ipairs(oldStatements) do
if statement.qualifiers then
local Values = {}
for key, array in pairs(lib.props) do
for _, prop in ipairs(array) do
if statement.qualifiers[prop] then
for _, snak in ipairs(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
end
if lib.IsOptionTrue(options, 'withlabel') then
filter(statements, filterItemHasLabel, options.withlang)
if #statements == 0 then return end
end
-- apply filter by class
if options.instance then
filter(statements, filterItemIsInstance, options)
if #statements == 0 then return end
end
-- sort statements if needed
if options.sort then -- patří to sem?
local Sorters = require 'Modul:Wikidata/Sorters'
Sorters.sortStatements(statements, options)
end
-- apply filter by limit
applyLimit(statements, options.limit)
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 ipairs(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(#Qualifiers)].datatype
if datatype == 'wikibase-item' or datatype == 'wikibase-property' then
oldQualifiers, Qualifiers = Qualifiers, {}
local Module = require 'Modul:Wikidata/Tree'
for _, snak in ipairs(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"
Sorters.sortQualifiers(Qualifiers, options) --fixme: undefined!
end ]]--
applyLimit(Qualifiers, options['qualifiers limit'])
-- @deprecated
return Qualifiers
end
function p.filterReferences(references, options)
local options = lib.common.cleanArgs(options)
if options.ref == '#any' then
-- @deprecated
return references
end
local oldReferences, References = references, {}
if options.ref == 'valid' then
local map = (require 'Modul:Wikidata/cite').props
for _, ref in ipairs(oldReferences) do
for _, props in pairs(map) do
for _, prop in ipairs(props) do
if ref.snaks[prop] then
table.insert(References, ref)
end
end
end
end
end
if options.min_ref and not checkLimit(References, options.min_ref) then
return {}
end
-- @deprecated
return References
end
return p