require 'strict'local p = {}local lib = require 'Modul:Wikidata/lib'local i18n = mw.loadData('Modul:Wikidata/i18n')local getArgs = (require 'Modul:Arguments').getArgslocal function outputBool(arg, ifexpr)local mapif ifexpr thenmap = { [true] = 1, [false] = 0 }elsemap = { [true] = 1, [false] = '' }endreturn map[arg]endlocal function removeDuplicates(values)local TableTools = require 'Modul:TableTools'return TableTools.removeDuplicates(values)endlocal function getEntityIdFromStatements(statements)for _, statement in ipairs(statements) doif lib.IsSnakValue(statement.mainsnak) thenif statement.mainsnak.datavalue.type ~= 'wikibase-entityid' thenerror(lib.raiseInvalidDatatype('getEntityIdFromStatements',statement.mainsnak.datatype, {'wikibase-item', 'wikibase-property'}))endlocal Formatters = require 'Modul:Wikidata/Formatters'return Formatters.getRawValue(statement.mainsnak, {})endbreakendreturn nilendlocal function getEntityIdFromEntity(entity, prop)local prop = mw.ustring.upper(prop)local statements = entity:getBestStatements(prop)return getEntityIdFromStatements(statements)endlocal function getEntityIdFromId(id, prop)local prop = mw.ustring.upper(prop)local statements = mw.wikibase.getBestStatements(id, prop)return getEntityIdFromStatements(statements)endlocal function getIdFromTitle(titleString, wiki)if wiki thenreturn mw.wikibase.getEntityIdForTitle(titleString, wiki)endlocal title = mw.title.new(titleString)while title dolocal id = mw.wikibase.getEntityIdForTitle(title.prefixedText)if id thenreturn idendtitle = title.redirectTargetendreturn nilendlocal function findEntityId(options)local idif options.entity and type(options.entity) == 'table' thenid = options.entity.idendif not id and options.page thenid = getIdFromTitle(options.page, options.wiki)if not id thenreturn nilendendif not id thenid = options.id or p.getCurrentId()endif id and options.of thenid = getEntityIdFromId(id, options.of)endreturn idendlocal function findEntity(options)local entityif options.entity and type(options.entity) == 'table' thenentity = options.entityendif not entity thenif options.id thenlocal id = options.id:upper()entity = mw.wikibase.getEntity(id)if entity and entity.id ~= id thenmw.log(id .. ' je přesměrování na ' .. entity.id)endelseif options.page thenlocal id = getIdFromTitle(options.page, options.wiki)if id thenentity = mw.wikibase.getEntity(id)endelseentity = mw.wikibase.getEntity()endendendif options.of thenif entity thenlocal id = getEntityIdFromEntity(entity, options.of)if id thenreturn mw.wikibase.getEntity(id)endendreturn nilendreturn entityendlocal function getSitelink(options)local id = findEntityId(options)if not id thenreturn nilendlocal site = options.site or options[1]local sitelink = mw.wikibase.getSitelink(id, site)if not sitelink thenreturn nilendif options.pattern thensitelink = lib.formatFromPattern(sitelink, options.pattern)endif lib.IsOptionTrue(options, 'addclass') thensitelink = lib.addWdClass(sitelink)endreturn sitelinkendlocal function formatStatementAndData(statement, options)if not statement.type or statement.type ~= 'statement' thenerror(lib.formatError('unknown-claim-type', statement.type or '[neznámý]')) -- fixme: i18nendlocal Filterers = require 'Modul:Wikidata/Filterers'local Formatters = require 'Modul:Wikidata/Formatters'local result = { Formatters.getFormattedValue(statement.mainsnak, options) }local qualifiersif statement.qualifiers and options.showqualifier thenlocal PropList = lib.textToTable(options.showqualifier)-- TODO: move this to a better place (config)local default_options = {isQualifier = true,label = 'short',nolink = lib.IsOptionTrue(options, 'nolink'),precision = 9,}for _, property in ipairs(PropList) dolocal property = mw.ustring.upper(property)local Values = {}local qualifiers_options = lib.augmentArgs(options, default_options, 'qualifiers ')if statement.qualifiers[property] thenlocal Qualifiers = mw.clone(statement.qualifiers[property])qualifiers_options.property = propertyif not qualifiers_options.nolink thenqualifiers_options.nolink = (Qualifiers[1].datatype == 'time')endFilterers.filterQualifiers(Qualifiers, qualifiers_options)for _, snak in ipairs(Qualifiers) dotable.insert(Values, Formatters.getFormattedValue(snak, qualifiers_options))endelseif property == 'TIME' thenlocal Data = {}-- TODO: factor outfor key, array in pairs(lib.props) dofor _, prop in ipairs(array) dofor _, snak in ipairs(statement.qualifiers[prop] or {}) doif lib.IsSnakValue(snak) then -- dokud nebude jasné, jak to používatData[key] = snakbreakendendendendif Data.begin or Data.ending thenqualifiers_options.nolink = truetable.insert(Values, lib.formatDateRange(Data, qualifiers_options))endendif #Values > 0 thenresult[property] = mw.text.listToText(removeDuplicates(Values),qualifiers_options.separator,qualifiers_options.conjunction)endendendif statement.references and lib.IsOptionTrue(options, 'showsource') then-- TODO: configure custom formatterlocal Module = require 'Modul:Wikidata/cite'result.ref = Module.formatReferences(statement.references, options) -- or table of references?endreturn resultendlocal function formatStatement(statement, options)local data = formatStatementAndData(statement, options)local result = data[1]if options.isQualifier == true thenreturn resultendlocal qualifiersif statement.qualifiers and options.showqualifier thenlocal PropList = lib.textToTable(options.showqualifier)local tmp = {}for _, prop in ipairs(PropList) dolocal prop = mw.ustring.upper(prop)if data[prop] thentable.insert(tmp, data[prop])endendif #tmp > 0 thenqualifiers = table.concat(tmp, i18n['qualifiers separator'])endendif not qualifiers and options.showtargetdata thenlocal entitylocal Filterers = require 'Modul:Wikidata/Filterers'local Formatters = require 'Modul:Wikidata/Formatters'if lib.IsSnakValue(statement.mainsnak) thenif statement.mainsnak.datavalue.type == 'wikibase-entityid' thenentity = mw.wikibase.getEntity(Formatters.getRawValue(statement.mainsnak, {}))elseerror(lib.formatError('invalid-datatype', statement.mainsnak.property, statement.mainsnak.datatype, 'wikibase-item/wikibase-property'))endendif entity thenlocal PropList = lib.textToTable(options.showtargetdata)local datelocal rank = 'best'if options.targetdate thenif lib.isPropertyId(options.targetdate) thendate = p.getRawValueFromLua{ entity = options.entity, property = options.targetdate }elsedate = options.targetdateendif date thenrank = 'valid'endendlocal options = {addclass = false,autoformat = true,date = date,entity = entity,isQualifier = true,label = 'short',nolink = true,precision = 9,rank = rank,sort = {'date'},}local Snaks = {}for _, property in ipairs(PropList) dolocal resultif mw.ustring.lower(property) == 'time' thenlocal Data = {}for key, array in pairs(lib.props) dofor _, prop in ipairs(array) dooptions.property = proplocal Statements = Filterers.filterStatementsFromEntity(entity, options)for _, statement in ipairs(Statements) doData[key] = statement.mainsnakbreakendendendif Data.begin or Data.ending thenresult = lib.formatDateRange(Data, options)endelseoptions.property = propertyresult = p.formatStatementsFromLua(options)endif result thentable.insert(Snaks, result)endendif #Snaks > 0 thenqualifiers = table.concat(Snaks, i18n['qualifiers separator'])endendendif qualifiers thenif options.delimiter thenresult = result .. options.delimiter .. qualifierselseresult = result .. ' (' .. qualifiers .. ')'endendif data.ref and data.ref ~= '' thenreturn result .. data.ref .. lib.category('references')endreturn resultendlocal function formatStatements(statements, options)local formattedStatements = {}for _, statement in ipairs(statements) dotable.insert(formattedStatements, formatStatement(statement, options))endreturn formattedStatementsendlocal function getStatements(id, options)if not id thenreturn {}endlocal statements = mw.wikibase.getAllStatements(id, options.property:upper())local Filterers = require 'Modul:Wikidata/Filterers'Filterers.filterStatements(statements, options)return statementsendlocal function prepareShowMore(options)if options.limit and lib.IsOptionTrue(options, 'showmore') thenoptions.limit = options.limit + 1return trueendreturn falseendlocal function handleShowMore(values, limit, add_more)if add_more thenif #values == limit thentable.remove(values)elseadd_more = falseendendreturn add_moreendlocal function makeList(values, options, add_more, link)values = removeDuplicates(values) -- TODO: maybe make optionalif add_more thenlocal parts = mw.text.split(link, '#', true) -- b/ctable.insert(values, mw.ustring.format(i18n['more-on-Wikidata'], parts[1], parts[2] or ''))endlocal textif options.list == 'ul' or options.list == 'ol' thenlocal li = {}for _, val in ipairs(values) dotable.insert(li, mw.ustring.format('<li>%s</li>', val))endtext = mw.ustring.format('<%s class="wd">%s</%s>', options.list, table.concat(li), options.list)elsetext = mw.text.listToText(values, options.separator, options.conjunction)if lib.IsOptionTrue(options, 'addlink') then-- TODO: data-bridge-edit-flowtext = mw.ustring.format('%s <sup class="wd-link">([[d:%s|e]])</sup>', text, link)endif tostring(options.addclass) ~= 'false' thentext = lib.addWdClass(text)endendreturn textendlocal function getFormattedStatements(options)options.limit = tonumber(options.limit) --TODO default?local add_more = prepareShowMore(options)local id = findEntityId(options)local statements = getStatements(id, options)if #statements == 0 then return nil endadd_more = handleShowMore(statements, options.limit, add_more)options.id = id-- Format statements and concat them cleanlylocal formattedStatements = formatStatements(statements, options)local property = mw.ustring.upper(options.property)local link = mw.ustring.format('%s#%s', id, property)local text = makeList(formattedStatements, options, add_more, link)if lib.IsOptionTrue(options, 'addcat') thentext = text .. lib.category('used-property', property)endreturn textendlocal function getRawValue(options)if not options.rank thenoptions.rank = 'best'endfor _, statement in ipairs(p.getStatements(options)) dolocal Formatters = require 'Modul:Wikidata/Formatters'return Formatters.getRawValue(statement.mainsnak, options)endreturn nilendlocal function getQualifiers(args)if not args.qualifier thenerror(lib.formatError('param-not-provided', 'qualifier'))endif not args.rank thenargs.rank = 'best'endfor _, statement in ipairs(p.getStatements(args)) doif statement.qualifiers thenlocal qualifier_args = lib.augmentArgs(args, {}, 'qualifiers ')local qualifiers = mw.clone(statement.qualifiers[mw.ustring.upper(args.qualifier)] or {})local Filterers = require 'Modul:Wikidata/Filterers'Filterers.filterQualifiers(qualifiers, qualifier_args)return qualifiersendreturn {}endreturn {}end----- API pro šablony -----function p.compareStatements(frame)local args = getArgs(frame, { frameOnly = true })return p._compareStatements(args)endfunction p.dumpWikidataEntity(frame)local args = getArgs(frame, { frameOnly = true })return mw.dumpObject( mw.wikibase.getEntity( args.id ) )endfunction p.getBadges(frame)local args = getArgs(frame, { frameOnly = true })local site = args.siteif not site thenerror(lib.formatError('param-not-provided', 'site'))endlocal id = findEntityId(args)if not id thenreturn nilendlocal Badges = {}local Formatters = require 'Modul:Wikidata/Formatters'for _, badge in ipairs(mw.wikibase.getBadges(id, site)) dotable.insert(Badges, Formatters.formatRawValue(badge, 'wikibase-entityid'))endreturn table.concat(Badges, ', ')endfunction p.getLabel(frame)local args = getArgs(frame, { frameOnly = true })local id = findEntityId(args)if not id thenreturn nilendlocal lang, label = args.langif lang thenlabel = mw.wikibase.getLabelByLang(id, lang)elselabel, lang = mw.wikibase.getLabelWithLang(id)endif not label then return nil endlabel = mw.text.nowiki(label)if lib.IsOptionTrue(args, 'addclass') thenif lang ~= i18n.lang thenreturn lib.addWdClass(lib.formatTextInLanguage(label, lang))elsereturn lib.addWdClass(label)endendreturn labelendfunction p.getDescription(frame)local args = getArgs(frame, { frameOnly = true })local id = findEntityId(args)if not id thenreturn nilendlocal lang, description = args.langif lang thendescription = mw.wikibase.getDescriptionByLang(id, lang)elsedescription, lang = mw.wikibase.getDescriptionWithLang(id)endif not description then return nil enddescription = mw.text.nowiki(description)if lib.IsOptionTrue(args, 'addclass') thenif lang ~= i18n.lang thenreturn lib.addWdClass(lib.formatTextInLanguage(description, lang))elsereturn lib.addWdClass(description)endendreturn descriptionendfunction p.getAliases(frame)local args = getArgs(frame, { frameOnly = true })local entity = findEntity(args)local lang = args.lang or i18n.langif not entity or not entity.aliases or not entity.aliases[lang] thenreturn nilendargs.limit = tonumber(args.limit)local add_more = prepareShowMore(args)local limit = args.limitlocal Aliases = {}for i, alias in ipairs(entity.aliases[lang]) dotable.insert(Aliases, mw.text.nowiki(alias.value))if i == limit thenbreakendendadd_more = handleShowMore(Aliases, limit, add_more)return makeList(Aliases, args, add_more, entity.id)endfunction p.getId(frame)local args = getArgs(frame, {frameOnly = false,parentOnly = false,parentFirst = false,})if not args[1] thenreturn mw.wikibase.getEntityIdForCurrentPage()endfor _, titleString in ipairs(args) dolocal id = getIdFromTitle(titleString, args.wiki)if id thenreturn idendendreturn nilendfunction p.getSitelink(frame)return getSitelink(getArgs(frame, { frameOnly = true }))endfunction p.formatStatements(frame)local args = getArgs(frame, { frameOnly = true })if args.value then return args.value end -- b/c for other wikislocal parent_args = getArgs(frame, { parentOnly = true })local addif parent_args.item and not args.id thenargs.id = parent_args.itemadd = lib.category('arbitrary-data')endlocal value = getFormattedStatements(args)if add and value thenreturn value .. addendreturn valueendfunction p.formatTimespan(frame)local args = getArgs(frame, { frameOnly = true })local subargs = {}local data = {}local defaults = { sort = 'default' }for key in pairs{ start = true, ['end'] = true } dolocal prefix = key .. ' 'if not args[prefix .. 'property'] thenerror('param-not-provided', prefix .. 'property')endsubargs[key] = lib.augmentArgs(args, defaults, prefix)local statements = p.getStatements(subargs[key])if #statements > 0 thendata[key] = statementsendendif not data.start and not data['end'] thenreturn nilendlocal out = {}if data.start and data['end'] thenfor _, startSt in ipairs(data.start) dofor _, endSt in ipairs(data['end']) dolocal separator = ' – '-- TODOtable.insert(out,mw.ustring.format('%s%s%s',formatStatement(startSt, subargs.start),separator,formatStatement(endSt, subargs['end'])))endendelsefor key in pairs{ start = true, ['end'] = true } dofor _, statement in ipairs(data[key] or {}) dotable.insert(out,mw.ustring.format(args[key .. '-format'] or i18n.date[key],formatStatement(statement, subargs[key])))endendendreturn makeList(out, args, false, '')endfunction p.formatStatementsFromTemplate(frame)local args = getArgs(frame, {frameOnly = false,parentOnly = false,parentFirst = false,})return getFormattedStatements(args)endfunction p.getCount(frame)local args = getArgs(frame, { frameOnly = true })args.limit = nilreturn #p.getStatements(args)endfunction p.getRawValue(frame)return getRawValue(getArgs(frame, { frameOnly = true }))endfunction p.getQualifier(frame)local args = getArgs(frame, { frameOnly = true })args.limit = tonumber(args['qualifiers limit'] or args.limit)local add_more = prepareShowMore(args)local limit = args.limitargs['qualifiers limit'] = limitargs.limit = 1local qualifiers = getQualifiers(args)if #qualifiers == 0 thenreturn nilendadd_more = handleShowMore(qualifiers, limit, add_more)local Formatters = require 'Modul:Wikidata/Formatters'local formattedQualifiers = {}for _, qualifier in ipairs(qualifiers) dotable.insert(formattedQualifiers, Formatters.getFormattedValue(qualifier, args))endlocal link = '' -- TODO: we don't have statement anchor-- TODO: references?return makeList(formattedQualifiers, args, add_more, link)endfunction p.getRawQualifier(frame)local args = getArgs(frame, { frameOnly = true })args.limit = 1for _, qualifier in ipairs(getQualifiers(args)) dolocal Formatters = require 'Modul:Wikidata/Formatters'return Formatters.getRawValue(qualifier, args)endreturn nilendfunction p.getCurrentId()return mw.wikibase.getEntityIdForCurrentPage()endfunction p.formatEntity(frame)local args = getArgs(frame, { frameOnly = true })args.id = args.id or p.getCurrentId()if args.id thenlocal Formatters = require 'Modul:Wikidata/Formatters'return Formatters.formatRawValue(args.id, 'wikibase-entityid', args)endreturn nilendfunction p.entityExists(frame)return outputBool(mw.wikibase.entityExists(frame.args.id or frame.args[1]),lib.IsOptionTrue(frame.args, 'ifexpr'))endfunction p.isValidEntityId(frame)return outputBool(mw.wikibase.isValidEntityId(frame.args.id or frame.args[1]),lib.IsOptionTrue(frame.args, 'ifexpr'))end----- API pro moduly -----function p.formatStatementsFromLua(options)return getFormattedStatements(options)endfunction p.getSitelinkFromLua(options)return getSitelink(options or {})endfunction p.getStatements(args)local id = findEntityId(args)return getStatements(id, args)endfunction p.getStatementsWithData(args)local statements = p.getStatements(args)local result = {}for _, statement in ipairs(statements) dotable.insert(result, formatStatementAndData(statement, args))endreturn resultendfunction p.getRawValueFromLua(options)return getRawValue(options)endfunction p.getRawValues(options)local Values = {}local Formatters = require 'Modul:Wikidata/Formatters'for _, st in ipairs(p.getStatements(options)) dotable.insert(Values, Formatters.getRawValue(st.mainsnak, options))endreturn Valuesendp.formatStatementsTable = formatStatementsfunction p._compareStatements(args)if not args.value thenerror(lib.formatError('param-not-provided', 'value'))endlocal statements = p.getStatements(args)local compare = require 'Modul:Wikidata/compare'return compare.compareValues(args.value, statements, args)endreturn p