Modul:Wikidata-ro
Documentation for this module may be created at Modul:Wikidata-ro/doc
local getArgs = require('Module:Arguments-ro').getArgs
local SepEntries = require('Module:Separated entries')
local StringUtils = require('Modul:StringUtils')
local DateUtils = require('Modul:DateUtils')
local GregorianDate = require('Modul:GregorianDate')
local Citation = require('Modul:Citation/CS1')
local TableTools = require('Modul:TableTools-ro')
local LangUtils = require('Modul:LangUtils')
local plural = require('Modul:Plural').build_plural
local Transliteration = require('Modul:Transliteration')
local Set = require('Modul:Set')
local p = {}
local lang = mw.language.getContentLanguage()
local libraryUtil = require('libraryUtil')
local wdReferences = {}
-- internationalisation
local i18n = {
["errors"] = {
["property-not-found"] = "Proprietatea nu a fost găsită.",
["entity-not-found"] = "Itfemul Wikidata nu a fost găsit.",
["unknown-claim-type"] = "Tip de afirmație negăsit.",
["unknown-snak-type"] = "Tip de Snak negăsit.",
["unknown-datavalue-type"] = "Tip de date negăsit.",
["unknown-entity-type"] = "Tip de item negăsit.",
["qualifier-not-found"] = "Calificator negăsit.",
["site-not-found"] = "Proiect Wikimedia negăsit.",
},
["somevalue"] = "O valoare",
["novalue"] = "Nicio valoare",
["datetime"] =
{
-- $1 is a placeholder for the actual number
[0] = "$1 miliarde de ani", -- precision: billion years
[1] = "$100 milioane de ani", -- precision: hundred million years
[2] = "$10 milioane de ani", -- precision: ten million years
[3] = "$1 milioane de ani", -- precision: million years
[4] = "$100.000 de ani", -- precision: hundred thousand years
[5] = "$10.000 de ani", -- precision: ten thousand years
[6] = "mileniul $1", -- precision: millennium
[7] = "secolul $1", -- precision: century
[8] = "deceniul anilor $1", -- precision: decade
-- the following use the format of #time parser function
[9] = "Y", -- precision: year,
[10] = "F Y", -- precision: month
[11] = "j F Y", -- precision: day
[12] = 'j F Y, "orele" G', -- precision: hour
[13] = "j F Y G:i", -- precision: minute
[14] = "j F Y G:i:s", -- precision: second
["beforenow"] = "acum $1", -- how to format negative numbers for precisions 0 to 5
["afternow"] = "peste $1", -- how to format positive numbers for precisions 0 to 5
["bc"] = '$1 "î.e.n."', -- how print negative years
["ad"] = "$1" -- how print positive years
},
["monolingualtext"] = '<span lang="%language">%text</span>',
["warnDump"] = "[[Categorie:Apel de funcție 'Dump' din modulul Wikidata]]"
}
local function propAndEntity(arg1, arg2)
local propId, entId
for _,eachArg in ipairs({arg1, arg2}) do
if mw.ustring.match(eachArg, 'Q%d+') == eachArg then
entId = eachArg
elseif mw.ustring.match(eachArg, 'P%d+') == eachArg then
propId = eachArg
end
end
return propId, entId
end
local function wrapInLangSpan(text, lang)
if not text then return nil end
if not lang or lang == 'ro' then return text end
local langSpan = mw.html.create('span'):attr('lang', lang):wikitext(text)
return tostring(langSpan)
end
local function isClaimTrue(claim)
return mw.wikibase.entity.claimRanks['RANK_' .. mw.ustring.upper(claim.rank)] >= mw.wikibase.entity.claimRanks.RANK_NORMAL
end
p.isClaimTrue = isClaimTrue
--- returns true if the claim has a better (or equal) rank than the threshhold specified
--- threshholdRank can be "normal", "preferred" etc.
local function hasBetterRank(claim, threshholdRank)
return (not threshholdRank
or mw.wikibase.entity.claimRanks['RANK_' .. mw.ustring.upper(claim.rank)] >= mw.wikibase.entity.claimRanks['RANK_' .. mw.ustring.upper(threshholdRank)])
and isClaimTrue(claim)
end
p.hasBetterRank = hasBetterRank
function p.descriptionIn(frame)
local langcode = frame.args[1]
local id = frame.args[2]
-- return description of a Wikidata entity in the given language or the default language of this Wikipedia site
local entity = mw.wikibase.getEntityObject(id)
if entity then
return entity.descriptions[langcode or lang.code].value
end
return ""
end
function p.getEntityId(frame)
return mw.wikibase.getEntityIdForCurrentPage()
end
function p.labelIn(frame)
local langcode = frame.args[1]
local id = frame.args[2] or mw.wikibase.getEntityIdForCurrentPage()
-- return label of a Wikidata entity in the given language or the default language of this Wikipedia site
local entity
if id then
return mw.wikibase.getLabelByLang(id, langcode or lang.code)
end
return ""
end
local function isValueSnak(snak)
return snak and snak.snaktype == 'value'
end
p.isValueSnak = isValueSnak
local function hasValueSnak(claim)
return claim and claim.type == 'statement' and isValueSnak(claim.mainsnak)
end
p.hasValueSnak = hasValueSnak
local function hasRankAtLeastNormal(claim)
return claim and claim.rank and mw.wikibase.entity.claimRanks['RANK_' .. mw.ustring.upper(claim.rank)] > mw.wikibase.entity.claimRanks.RANK_DEPRECATED
end
p.claimHasRankAtLeastNormal = hasRankAtLeastNormal
local function isWritingSystemLatn(lId)
local writingSystems = { lId }
local loopIdx = 1
repeat
local crtWritingSystemId = table.remove(writingSystems, 1)
local writingSystemInstanceOfClaims = p.findBestClaimsForProperty(crtWritingSystemId, 'P31')
if writingSystemInstanceOfClaims then for _,eachScriptInstanceOfClaim in ipairs(writingSystemInstanceOfClaims) do
if p.hasValueSnak(eachScriptInstanceOfClaim) and eachScriptInstanceOfClaim.mainsnak.datavalue.value.id == 'Q29575627' then
return true
end
end end
local writingSystemClaims = p.findBestClaimsForProperty(crtWritingSystemId, 'P282')
if writingSystemClaims then for _,eachWritingSystemClaim in ipairs(writingSystemClaims) do
if p.hasValueSnak(eachWritingSystemClaim) then
if eachWritingSystemClaim.mainsnak.datavalue.value.id == 'Q8229' then
return true
end
table.insert(writingSystems, eachWritingSystemClaim.mainsnak.datavalue.value.id)
end
end end
loopIdx = loopIdx + 1
until #writingSystems == 0 or loopIdx >= 20
return false
end
local function findNativeOrEnglishLabel(entityId, capitalize)
local label
local labelLang
if not entityId then
entityId = mw.wikibase.getEntityIdForCurrentPage()
end
if not entityId then return nil end
local langIds = {}
for _,eachLangProp in ipairs({'P103', 'P407', 'P37', 'P364'}) do
for __,eachLangClaim in ipairs(mw.wikibase.getBestStatements(entityId, eachLangProp)) do
if hasValueSnak(eachLangClaim) then
table.insert(langIds, eachLangClaim.mainsnak.datavalue.value.id)
end
end
end
for _,eachCountryProp in ipairs({'P17', 'P27'}) do
for __,eachCountry in ipairs(mw.wikibase.getBestStatements(entityId, eachCountryProp)) do
if hasValueSnak(eachCountry) then
for ___,eachOffLang in ipairs(mw.wikibase.getBestStatements(eachCountry.mainsnak.datavalue.value.id, 'P37')) do
if hasValueSnak(eachOffLang) then
table.insert(langIds, eachOffLang.mainsnak.datavalue.value.id)
end
end
end
end
end
table.insert(langIds, 'Q1860')
langIds = TableTools.mergeSort(langIds, function(l1, l2)
if l2 and not l1 then return 1 end
if l1 and not l2 then return -1 end
if l1 == l2 then return 0 end
local l1IsLatn = isWritingSystemLatn(l1) or Transliteration.isTransliterationSupported(p.loadOneValueInChain({l1, 'P218'}))
local l2IsLatn = isWritingSystemLatn(l2) or Transliteration.isTransliterationSupported(p.loadOneValueInChain({l2, 'P218'}))
if l1IsLatn and not l2IsLatn then
return -1
elseif not l1IsLatn and l2IsLatn then
return 1
else
return 0
end
end)
local langsToTry = {}
for _,eachLangId in ipairs(langIds) do
for __,eachLangCodeClaim in ipairs(mw.wikibase.getBestStatements(eachLangId, 'P424')) do
if not labelLang and hasValueSnak(eachLangCodeClaim) then
table.insert(langsToTry, eachLangCodeClaim.mainsnak.datavalue.value)
end
end
end
local simplifiedLangsToTry = {}
for _,eachLangToTry in ipairs(langsToTry) do
local simplifiedLang = StringUtils._substringBefore({StringUtils._substringBefore({eachLangToTry, '_'}), '-'})
table.insert(simplifiedLangsToTry, simplifiedLang)
end
langsToTry = simplifiedLangsToTry
for _,eachLang in ipairs(langsToTry) do
if label == nil then
label = mw.wikibase.getLabelByLang(entityId, eachLang)
description = mw.wikibase.getDescription(entityId)
labelLang = eachLang
end
if label then break end
end
if label then
if labelLang and labelLang ~= 'crh' and not Transliteration.isTransliterationSupported(labelLang) then
label = wrapInLangSpan(label, labelLang)
end
if Transliteration.isTransliterationSupported(labelLang) then
label = wrapInLangSpan(Transliteration.transliterate(label, labelLang), labelLang .. '-Latn')
end
if capitalize then
label = lang:ucfirst(label)
end
end
return label, labelLang
end
p.findNativeOrEnglishLabel = findNativeOrEnglishLabel
p.getNativeOrEnglishLabel = function(frame)
local args = getArgs(frame)
local label, lang = findNativeOrEnglishLabel(args[1], args[2])
if label then return label else return nil end
end
local function computeLinkToItem(entityId, capitalize, callFunction, plainCallFunction)
local qIfiedEntityId = StringUtils._prependIfMissing({tostring(entityId), 'Q'})
local sitelink = mw.wikibase.sitelink(qIfiedEntityId)
local label = nil
local labelLang = nil
local object = nil
local out = ""
local description = nil
if plainCallFunction and type(plainCallFunction) == 'function' then
label, labelLang = plainCallFunction(qIfiedEntityId)
elseif callFunction and type(callFunction) == 'function' then
object = mw.wikibase.getEntityObject(qIfiedEntityId)
label, labelLang = callFunction(object)
end
if label == nil or (labelLang and labelLang ~= lang.code) then
label = mw.wikibase.getLabelByLang(qIfiedEntityId, 'ro')
if label then labelLang = 'ro' end
description = mw.wikibase.getDescription(qIfiedEntityId)
end
if not label then
label, labelLang = findNativeOrEnglishLabel(qIfiedEntityId, capitalize)
elseif capitalize then
label = lang:ucfirst(label)
end
if not label then
label = qIfiedEntityId
labelLang = nil
end
if description then description = "(" .. description .. ")" end
if label == qIfiedEntityId then
out = "[[Category:Articole cu legături către elemente fără etichetă]] "
elseif labelLang ~= 'ro' then
out = "[[Category:Articole cu legături către elemente fără etichetă în limba română]] "
end
description = description or ""
if sitelink then
return out .. "[[:" .. sitelink .. "|" .. label .. "]]"
else
local coextensiveWithPageId = p.loadOneValueInChain({qIfiedEntityId, 'P3403', 'raw'})
local listPageId = p.loadOneValueInChain({qIfiedEntityId, 'P2354', 'raw'})
local listPageSitelink = listPageId and mw.wikibase.sitelink(listPageId) or coextensiveWithPageId and mw.wikibase.sitelink(coextensiveWithPageId)
if listPageSitelink then return "[[:" .. listPageSitelink .. "|" .. label .. "]]" end
return out .. "[[:d:" .. qIfiedEntityId .. "|" .. label .. "]]<abbr title='Articolul încă nu există în acest wiki'>[*]</abbr>" .. mw.getCurrentFrame():preprocess("{{invizibil|1=[[" .. label .." " .. description .. "|​]]}}")
end
end
p.findLinkToItemWithLabel = function(entityId, label)
local sitelink = mw.wikibase.sitelink(StringUtils._prependIfMissing({tostring(entityId), 'Q'}))
if sitelink then
return "[[:" .. sitelink .. "|" .. label .. "]]"
else
return computeLinkToItem(entityId, false, nil, function() return label end)
end
end
p.findLinkToItemWithCallback = function(entityId, capitalize, callBack, plainCallBack)
return computeLinkToItem(entityId, capitalize, callBack, plainCallBack)
end
p.findLinkToItemWithLabelFromAnyClaim = function(entityId, capitalize, propertyIdsTable)
local callFunction = nil
if propertyIdsTable then
callFunction = function(object)
local returnValue = nil
for propIdIdx,propertyId in pairs(propertyIdsTable) do
if object and object.claims and object.claims[propertyId] and returnValue == nil then
for eachClaimIdx, eachClaim in pairs(object.claims[propertyId]) do
if hasValueSnak(eachClaim) and eachClaim.mainsnak.datavalue then
if eachClaim.mainsnak.datavalue.type == 'monolingualtext' then
if eachClaim.mainsnak.datavalue.value.language == 'ro' then returnValue = eachClaim.mainsnak.datavalue.value.text end
elseif eachClaim.mainsnak.datavalue.type == 'wikibase-entityid' then
returnValue = mw.wikibase.label(StringUtils._prependIfMissing({tostring(eachClaim.mainsnak.datavalue.value['numeric-id']), 'Q'}))
elseif eachClaim.mainsnak.datavalue.type == 'string' then
returnValue = eachClaim.mainsnak.datavalue.value
end
end
end
end
end
return returnValue
end
end
return computeLinkToItem(entityId, capitalize, callFunction)
end
p.findLinkToItemWithLabelFromClaim = function(entityId, capitalize, propertyId)
return p.findLinkToItemWithLabelFromAnyClaim(entityId, capitalize, { propertyId })
end
p.findLinkToItem = function(entityId, capitalize, feminine, shortestAlias)
if type(entityId) == 'number' then entityId = StringUtils._prependIfMissing({tostring(entityId), 'Q'}) end
if capitalize == nil then capitalize = false end
local label
local returnedLang = nil
local bestRanks = { ["crh"] = nil, ["en"] = nil }
if shortestAlias then
local returnedAlias = nil
local bestShortNameClaims = mw.wikibase.getAllStatements(entityId, 'P1813')
if bestShortNameClaims then
local shortNameEn = nil
for shortNameIdx,shortNameClaim in pairs(bestShortNameClaims) do
if shortNameClaim.mainsnak.datavalue.value.language == 'en' and hasBetterRank(shortNameClaim, bestRanks["en"]) then
shortNameEn = shortNameClaim.mainsnak.datavalue.value.text
bestRanks["en"] = shortNameClaim.rank
end
if shortNameClaim.mainsnak.datavalue.value.language == 'crh' and hasBetterRank(shortNameClaim, bestRanks["ro"]) then
returnedAlias = shortNameClaim.mainsnak.datavalue.value.text
bestRanks["crh"] = shortNameClaim.rank
end
end
if returnedAlias then
returnedLang = 'crh'
elseif shortNameEn then
returnedAlias = shortNameEn
returnedLang = 'en'
end
returnedAlias = capitalize and StringUtils._capitalize({returnedAlias}) or returnedAlias
end
label = wrapInLangSpan(returnedAlias, returnedLang)
end
if feminine then
local feminineForms = mw.wikibase.getBestStatements(entityId, 'P2521')
if feminineForms then
for _idx, eachFForm in pairs(feminineForms) do
if hasValueSnak(eachFForm) and eachFForm.mainsnak.datatype == 'monolingualtext' and eachFForm.mainsnak.datavalue.type == 'monolingualtext' and eachFForm.mainsnak.datavalue.value and eachFForm.mainsnak.datavalue.value.language == 'crh' then
label = eachFForm.mainsnak.datavalue.value.text
returnedLang = eachFForm.mainsnak.datavalue.value.language
end
end
end
end
return computeLinkToItem(entityId, capitalize, nil, function() return label, returnedLang end)
end
p.getLinkToItem = function(frame)
local args = getArgs(frame, {frameOnly=true})
local entityId = args[1]
return p.findLinkToItem(entityId, false, false, false)
end
local function printRawValue(snak)
if (isValueSnak(snak)) then
if snak.datavalue.type == "wikibase-entityid" then
return snak.datavalue.value.id
elseif snak.datavalue.type == "time" then
return snak.datavalue.value.time
elseif snak.datavalue.type == "monolingualtext" then
return snak.datavalue.value.text
elseif snak.datavalue.type == "quantity" then
return snak.datavalue.value.amount .. ' ' .. snak.datavalue.value.unit
else
return snak.datavalue.value
end
end
return ''
end
local function snakToString(snak, feminine)
if (isValueSnak(snak)) then
if (snak.datavalue.type == "wikibase-entityid") then
return p.findLinkToItem(snak.datavalue.value["numeric-id"], nil, feminine)
end
if (snak.datavalue.type == "time") then
return formatDate(snak.datavalue.value.time, snak.datavalue.value.precision, snak.datavalue.value.timezone)
end
if (snak.datavalue.type == "monolingualtext") then
return snak.datavalue.value.text
end
if (snak.datavalue.type == "quantity") then
local unit = '1'
local amount = snak.datavalue.value.amount
local ret = nil
local unitQ = mw.ustring.match(snak.datavalue.value.unit, 'Q%d+')
if unitQ ~= nil then
unit = p.findLanguageText('P5061', 'ro', unitQ) or p.findLanguageText('P5061', 'ro', unitQ)
if not unit or mw.ustring.len(unit) == 0 then
unit = p.findLabel(unitQ, nil)
if tonumber(amount) > 1 and unit then
mw.incrementExpensiveFunctionCount()
ret = plural(tonumber(amount), unit)
end
end
unit = unit or '1'
end
if tonumber(amount) ~= nil then
amount = mw.language.new(lang.code):formatNum(tonumber(amount))
end
if ret == nil then
ret = amount .. (unit ~= '1' and (mw.text.decode(' ') .. unit) or '')
end
return ret
end
return snak.datavalue.value
end
return ""
end
p.printSnak = function(snak)
return snakToString(snak)
end
p.outputReferences = function (claim)
local refMapping = {}
local authorityPropertiesMap = {}
local frame = mw.getCurrentFrame()
refMapping["P1433"] = "publisher"
refMapping["P123"] = "publisher"
refMapping["P143"] = "publisher"
refMapping["P1476"] = "contribution"
refMapping["P854"] = "url"
refMapping["P813"] = "accessdate"
refMapping["P50"] = "author"
refMapping["P2093"] = "author"
refMapping["P577"] = "date"
refMapping["P248"] = "title"
refMapping["P304"] = "page"
refMapping["P958"] = "contribution"
refMapping["P1810"] = "contribution"
refMapping["P212"] = "isbn"
authorityPropertiesMap['Q20666306'] = 'P268' -- BnF identifier
authorityPropertiesMap['Q15241312'] = 'P646' -- Freebase identifier
authorityPropertiesMap['Q36578'] = 'P227' -- GND identifier
authorityPropertiesMap['Q37312'] = 'P345' -- IMDb identifier
authorityPropertiesMap['Q278487'] = 'P662' -- PubChem identifier
authorityPropertiesMap['Q1139587'] = 'P2334' -- Swedish film database identifier
local primaryProperties = {}
primaryProperties["P1433"] = "publisher"
primaryProperties["P123"] = "publisher"
primaryProperties["P1476"] = "contribution"
primaryProperties["P248"] = "title"
primaryProperties["P854"] = "url"
primaryProperties["P50"] = "author"
local out = ""
local referencesCount = 0
if claim then
for ref in pairs(claim.references or {}) do
local citationArguments = {}
local citationArgumentsFound = false
local refname = ""
for snakkey, snakval in pairs(claim.references[ref].snaks) do
if refMapping[snakkey] ~= nil then
local snakData = {}
for snakIndex,snakValElement in ipairs(snakval) do
local formattedSnakValElement = snakToString(snakValElement)
if isValueSnak(snakValElement) and snakValElement.datatype == 'time' then
formattedSnakValElement = DateUtils.formatDate(DateUtils.parseWikidataDate(snakValElement.datavalue.value.time, snakValElement.datavalue.value.precision), false , true)
elseif isValueSnak(snakValElement) and snakkey == 'P1476' and snakValElement.datatype == 'monolingualtext' and snakValElement.datavalue.value.language ~= 'ro' then
citationArguments['language'] = snakValElement.datavalue.value.language
end
table.insert(snakData, formattedSnakValElement)
end
citationArguments[refMapping[snakkey]] = table.concat(snakData, ", ", 1, #snakData)
refname = refname .. '_' .. refMapping[snakkey] .. '_' .. mw.ustring.gsub(mw.ustring.gsub(mw.text.nowiki(citationArguments[refMapping[snakkey]]), '&#%d+;', ''), ' ', '')
if primaryProperties[snakkey] then
citationArgumentsFound = true
end
if snakkey == 'P248' or snakkey == 'P143' then -- "stated in" or "imported from", can be an authority file
if snakval[1].datavalue and snakval[1].datavalue.type == 'wikibase-entityid' then
local statedInWbId = snakval[1].datavalue.value.id
-- if Wikimedia project, ignore
for _idx, eachStatedInInstanceOfClaim in pairs(mw.wikibase.getAllStatements(statedInWbId, 'P31')) do
if eachStatedInInstanceOfClaim.mainsnak and eachStatedInInstanceOfClaim.mainsnak.datavalue and eachStatedInInstanceOfClaim.mainsnak.datavalue.type == 'wikibase-entityid' and
(eachStatedInInstanceOfClaim.mainsnak.datavalue.value['numeric-id'] == 10876391 or eachStatedInInstanceOfClaim.mainsnak.datavalue.value['numeric-id'] == 14827288) then
citationArgumentsFound = false
break
end
end
for _idx, eachStatedInInstanceOfClaim in pairs(mw.wikibase.getAllStatements(statedInWbId, 'P1269')) do
if eachStatedInInstanceOfClaim.mainsnak and eachStatedInInstanceOfClaim.mainsnak.datavalue and eachStatedInInstanceOfClaim.mainsnak.datavalue.type == 'wikibase-entityid' and
eachStatedInInstanceOfClaim.mainsnak.datavalue.value['numeric-id'] == 16222597 then
citationArgumentsFound = false
break
end
end
-- extract data about authority file
local authorityWbEntityId = authorityPropertiesMap[StringUtils._prependIfMissing({statedInWbId, 'Q'})]
if authorityWbEntityId then
local authorityUrlFormatClaims = mw.wikibase.getBestStatements(authorityWbEntityId, 'P1630')
if authorityUrlFormatClaims and 0 < #authorityUrlFormatClaims then
local formatterUrl = snakToString(authorityUrlFormatClaims[1].mainsnak)
local crtEntityId = mw.wikibase.getEntityIdForCurrentPage()
if crtEntityId then
local entityAuthIdClaims = mw.wikibase.getBestStatements(crtEntityId, authorityWbEntityId)
if entityAuthIdClaims and 0 < #entityAuthIdClaims and hasValueSnak(entityAuthIdClaims[1]) then
citationArguments['chapterurl'] = mw.ustring.gsub(formatterUrl, '%$1', entityAuthIdClaims[1].mainsnak.datavalue.value)
citationArguments['chapter'] = p.labelIn({args = {'ro'}}) or p.labelIn({args = {'en'}})
end
end
end
elseif citationArgumentsFound == true then
--extract URL from target entity
local statedInUrl = nil
-- the order of the array is important, as we only search the first occurence
local onlinelinksprops = {'P953', 'P854', 'P856', 'P1581', 'P2397','P1065'}
for _,eachOnlineLinkProp in ipairs(onlinelinksprops) do
local linkId = p.findOneValueNoRef(eachOnlineLinkProp, statedInWbId)
if linkId then
local linkFormatter = p.findOneValueNoRef('P1630', eachOnlineLinkProp) or '$1'
if linkFormatter then
linkId = mw.ustring.gsub(linkId, '%%', '%%%%')
statedInUrl = mw.ustring.gsub(linkFormatter, '$1', linkId)
break
else
statedInUrl = linkId
break
end
end
end
if statedInUrl then
citationArguments[refMapping[snakkey]] = StringUtils._capitalize({p.findTitleOfWork(statedInWbId)})
citationArguments['url'] = statedInUrl
else
local props = p.getEntityIdsList(statedInWbId, 'P1687')
if props then for _,eachOnlineLinkProp in ipairs(onlinelinksprops) do
for _,prop in ipairs(props) do
if eachOnlineLinkProp == 'P' .. prop then
citationArguments[refMapping[snakkey]] = StringUtils._capitalize({p.findTitleOfWork(statedInWbId)})
citationArguments['url'] = p.findOneValueNoRef(eachOnlineLinkProp)
end
break
end
end end
end
end
end
end
end
end
if citationArgumentsFound then
--post-process citation arguments:
--1. if publisher is missing and contribution and title are present, change title to publisher and contribution to title
if citationArguments['publisher'] == nil and citationArguments['contribution'] and citationArguments['title'] then
citationArguments['publisher'] = citationArguments['title']
citationArguments['title'] = citationArguments['contribution']
citationArguments['contribution'] = nil
end
--2. if contribution is present but title is not, change contribution to title
if citationArguments['contribution'] and citationArguments['title'] == nil then
citationArguments['title'] = citationArguments['contribution']
citationArguments['contribution'] = nil
end
--3. if title is a wikilink, break it down and assign article link separately
if citationArguments['title'] then
local titlink, titplain = mw.ustring.match(citationArguments['title'], '%[%[(.*)|(.*)%]%]')
if titlink and titplain then
if not citationArguments['url'] then citationArguments['titlelink'] = titlink end
citationArguments['title'] = titplain
end
end
local citationHash = mw.hash.hashValue('md5', refname)
if referencesCount < 4 then
if wdReferences[citationHash] then
out = out .. frame:extensionTag{name="ref", args={name = citationHash}}
else
local refText = Citation.citationFromArgs(citationArguments, {CitationClass = 'citation'}, false)
out = out .. frame:extensionTag("ref", refText, { name = citationHash })
wdReferences[citationHash] = true
end
referencesCount = referencesCount + 1
end
end
end
end
return out
end
p.getValueListLimited = function(entityId, propertyId, limitVal)
if limitVal == nil or limitVal <= 0 then limitVal = math.huge end
entityId = entityId or mw.wikibase.getEntityIdForCurrentPage()
if propertyId == nil or entityId == nil then return nil,0 end
local claims = mw.wikibase.getAllStatements(entityId, propertyId)
if not claims then return nil,0 end
if #claims == 0 then return {},0 end
local rez = {}
local feminine = false
local genders = mw.wikibase.getBestStatements(entityId, 'P21')
if genders and #genders > 0 and genders[1] and hasValueSnak(genders[1]) and genders[1].mainsnak.datatype == 'wikibase-item' and genders[1].mainsnak.datavalue.type == 'wikibase-entityid' and genders[1].mainsnak.datavalue.value['numeric-id'] == 6581072 then
feminine = true
end
local count = 0
for k, v in pairs(claims) do
if hasValueSnak(v) then
count = count+1
if k <= limitVal then
table.insert(rez, snakToString(v.mainsnak, feminine) .. p.outputReferences(v))
end
end
end
return rez, count
end
p.getValueList = function(entityId, propertyId)
local rez, _ = p.getValueListLimited(entityId, propertyId, nil)
return rez
end
local function findTimestampInTable(tbl)
local crtEntry = ''
if tbl then
if tbl['P585'] then
crtEntry = crtEntry .. snakToString(tbl['P585'][1].mainsnak or tbl['P585'][1])
elseif tbl['P580'] then
if tbl['P582'] then
local starttime = snakToString(tbl['P580'][1].mainsnak or tbl['P580'][1])
local endtime = snakToString(tbl['P582'][1].mainsnak or tbl['P582'][1])
if starttime == endtime then
crtEntry = crtEntry .. starttime
else
crtEntry = crtEntry .. starttime .. mw.text.decode('–', true) .. endtime
end
else
crtEntry = crtEntry .. 'din ' .. snakToString(tbl['P580'][1].mainsnak or tbl['P580'][1])
end
elseif tbl['P582'] then
local endtime = DateUtils.extractDateFromWikidataSnak(tbl['P582'][1].mainsnak or tbl['P582'][1])
if endtime then
crtEntry = crtEntry .. 'până ' .. ((endtime.precision == 9 or endtime.precision == 10) and 'în' or 'la') .. ' ' .. DateUtils.formatDate(endtime)
end
end
end
return crtEntry
end
p.printTimestampForClaim = function(claim)
if claim and claim.qualifiers then
return tostring(mw.html.create('small'):wikitext(' (' .. findTimestampInTable(claim.qualifiers) .. ')'))
end
return ''
end
p.findTimestamp = function(entityId)
if type(entityId) == 'number' then entityId = StringUtils._prependIfMissing({tostring(entityId), 'Q'}) end
if type(entityId) == 'table' then entityId = entityId.id end
entityId = entityId or mw.wikibase.getEntityIdForCurrentPage()
if entityId then
local tbl = {}
for _,propId in ipairs({'P580', 'P582', 'P585'}) do
local propClaims = mw.wikibase.getAllStatements(entityId, propId)
if propClaims and #propClaims > 0 then
tbl[propId] = propClaims
end
end
return findTimestampInTable(tbl)
end
return ''
end
p.getTimestamp = function(frame)
return p.findTimestamp(frame and frame.args and frame.args[1] or nil)
end
p.getValueListWithDecoratedQualifiers = function(frame)
local args = getArgs(frame)
local entityId = args['q']
local propertyId = args['p']
local best = (args['best'] ~= nil)
local bracketTemplates = nil
local bracketTemplatesIdces = TableTools.affixNums(args, 'bracketTemplate')
if bracketTemplatesIdces and #bracketTemplatesIdces > 0 then
bracketTemplates = {}
for _, bracketTemplatesIdx in ipairs(bracketTemplatesIdces) do
table.insert(bracketTemplates, args['bracketTemplate' .. tostring(bracketTemplatesIdx)])
end
end
local pictureSize = args['pictureSize'] or '40px'
local pictureProp = args['picturePid'] or nil
local seps = nil
local sepsIdces = TableTools.affixNums(args, 'sep')
if sepsIdces and #sepsIdces > 0 then
seps = {}
for _, sepsIdx in ipairs(sepsIdces) do
table.insert(seps, args['sep' .. tostring(sepsIdx)])
end
end
local rezList = p.findValueListWithQualifiersInBrackets(entityId, propertyId, best, bracketTemplates, seps, pictureProp, pictureSize)
return table.concat(rezList, tostring(mw.html.create('br')))
end
p.getValueListWithQualifiersInBrackets = p.getValueListWithDecoratedQualifiers
p.findValueListWithDecoratedQualifiers = function(entityId, propertyId, best, bracketTemplates, seps, pictureProp, pictureSize)
entityId = entityId or mw.wikibase.getEntityIdForCurrentPage()
if (type(bracketTemplates) == 'string') then
bracketTemplates = { bracketTemplates }
end
seps = seps or {}
table.insert(seps, 1, '')
if #seps < #bracketTemplates then for idx=#seps + 1,#bracketTemplates do table.insert(seps, ', ') end end
if propertyId == nil or entityId == nil then return nil end
local claims
local qualProps = {}
for _,bracketTemplate in ipairs(bracketTemplates) do
mw.ustring.gsub(bracketTemplate, '%$(P%d+)', function(qualProp)
table.insert(qualProps, qualProp)
return nil
end)
end
if best then
claims = mw.wikibase.getBestStatements(entityId, propertyId)
else
claims = mw.wikibase.getAllStatements(entityId, propertyId)
end
local rez = {}
if claims and claims[1] then
local rawclaims = {}
for k, v in pairs(claims) do
if hasValueSnak(v) and hasRankAtLeastNormal(v) then
table.insert(rawclaims, v)
end
end
for k, v in pairs(rawclaims) do
local crtEntry = snakToString(v.mainsnak)
if pictureProp then
local ts
local picture
if v.qualifiers and v.qualifiers['P582'] then for _,endTimeQual in ipairs(v.qualifiers['P582']) do
ts = DateUtils.extractDateFromWikidataSnak(endTimeQual)
end end
if ts then
local pictureClaim = p.findClaimForTimestamp(v.mainsnak.datavalue.value.id, pictureProp, ts)
if (p.hasValueSnak(pictureClaim)) then
picture = pictureClaim.mainsnak.datavalue.value
end
else
picture = p.loadOneValueInChain({v.mainsnak.datavalue.value.id, pictureProp, 'raw'})
end
if picture and picture ~= '' then
crtEntry = StringUtils._prependToString({crtEntry, '[[Fișier:' .. picture .. '|' .. pictureSize .. ']]' .. mw.text.decode(' ')})
end
end
if v.qualifiers and #qualProps > 0 then
local qualPropValues = {}
for _,eachQualProp in pairs(qualProps) do
if v.qualifiers[eachQualProp] then
local qualPropValuesList = {}
for __,eachQualSnak in ipairs(v.qualifiers[eachQualProp]) do
if isValueSnak(eachQualSnak) then
table.insert(qualPropValuesList, snakToString(eachQualSnak))
end
end
qualPropValues[eachQualProp] = mw.text.listToText(qualPropValuesList, ', ', ' și ')
else
qualPropValues[eachQualProp] = ''
end
end
local bracketData = {}
local usedSeps = {}
for bracketTemplateIdx,bracketTemplate in ipairs(bracketTemplates) do
local substedBracketTemplate = mw.ustring.gsub(bracketTemplate, '%$(P%d+)', function(qualProp)
return qualPropValues[qualProp]
end)
if substedBracketTemplate ~= bracketTemplate and substedBracketTemplate ~= "" then
bracketData[bracketTemplateIdx] = substedBracketTemplate
usedSeps[bracketTemplateIdx] = seps[bracketTemplateIdx]
end
end
bracketData = TableTools.compressSparseArray(bracketData)
usedSeps = TableTools.compressSparseArray(usedSeps)
local bracketText = ''
for bracketDatumIdx=1,#bracketData do
bracketText = bracketText .. (bracketDatumIdx == 1 and '' or usedSeps[bracketDatumIdx])
bracketText = bracketText .. bracketData[bracketDatumIdx]
end
crtEntry = StringUtils._appendToString({crtEntry, tostring(mw.html.create('small'):wikitext(StringUtils._encloseString({bracketText, ' (', ')'})))})
end
crtEntry = crtEntry .. p.outputReferences(v)
table.insert(rez, crtEntry)
end
end
return rez
end
p.findValueListWithQualifiersInBrackets = p.findValueListWithDecoratedQualifiers
p.getTimestampedValueList = function(entityId, propertyId, best)
entityId = entityId or mw.wikibase.getEntityIdForCurrentPage()
if propertyId == nil or entityId == nil then return nil end
local claims
if best then
claims = mw.wikibase.getBestStatements(entityId, propertyId)
else
claims = mw.wikibase.getAllStatements(entityId, propertyId)
end
local rez = {}
if claims and claims[1] then
local rawclaims = {}
for k, v in pairs(claims) do
if hasValueSnak(v) then
table.insert(rawclaims, v)
end
end
for k, v in pairs(rawclaims) do
local crtEntry = snakToString(v.mainsnak)
crtEntry = crtEntry .. p.printTimestampForClaim(v)
crtEntry = crtEntry .. p.outputReferences(v)
table.insert(rez, crtEntry)
end
end
return rez
end
p._getValueListWithSeparator = function(funcArgs)
local separator = mw.text.trim(funcArgs[1] or ", ")
local propertyId
local entityId
propertyId, entityId = propAndEntity(funcArgs[2], funcArgs[3])
entityId = entityId or mw.wikibase.getEntityIdForCurrentPage()
local limit = funcArgs[4] or funcArgs['limit']
local limitVal = 0
if limit and limit == mw.ustring.match(limit, '%d+') then
limitVal = tonumber(limit)
end
local values, vcount = p.getValueListLimited(entityId, propertyId, limitVal)
if not values then return nil end
local extraSpec = nil
if 0 < limitVal and vcount > limitVal + 1 then
local hiddenVals = vcount - limitVal
extraSpec = '[[:d:' .. entityId .. '#' .. propertyId .. "|...''încă " .. tostring(hiddenVals) .. "'']]"
table.insert(values, extraSpec)
end
return values and table.concat(values, separator)
end
p.getValueListWithSeparator = function(frame)
local funcArgs = getArgs(frame, {frameOnly = true})
return p._getValueListWithSeparator(funcArgs)
end
p.getValue = function(frame)
local args = getArgs(frame)
return p._getValueListWithSeparator({', ', args[1], mw.wikibase.getEntityIdForCurrentPage()})
end
p._getTimestampedValueListWithSeparator = function(funcArgs)
local separator = funcArgs[1] or ", "
local propertyId = funcArgs[2]
local entityId = funcArgs[3]
local best = funcArgs['best'] == 'y' or funcArgs['best'] == 'yes'
local values = p.getTimestampedValueList(entityId, propertyId, best)
return values and table.concat(values, separator)
end
p.getTimestampedValueListWithSeparator = function(frame)
local funcArgs = getArgs(frame, {frameOnly = true})
return p._getTimestampedValueListWithSeparator(funcArgs)
end
local function extractWikidataIdsFromClaimList(claims)
local rez = {}
if claims and #claims > 0 then
for k, v in pairs(claims) do
if hasValueSnak(v) and v.mainsnak.datavalue.type == 'wikibase-entityid' then
table.insert(rez, v.mainsnak.datavalue.value['numeric-id'])
end
end
end
return rez
end
p.getEntityIdsList = function(entityId, propertyId)
entityId = entityId or mw.wikibase.getEntityIdForCurrentPage()
if propertyId == nil or entityId == nil then return nil end
local claims = nil
if entityId then
claims = mw.wikibase.getAllStatements(entityId, propertyId)
end
return extractWikidataIdsFromClaimList(claims)
end
p.getBestEntityIdsList = function(entityId, propertyId)
local claims = nil
if propertyId == nil then return nil end
if type(entityId) == 'table' then
claims = entityId:getBestStatements(propertyId)
else
if type(entityId) == 'number' then entityId = StringUtils._prependIfMissing({tostring(entityId), 'Q'}) end
if type(propertyId) == 'number' then propertyId = StringUtils._prependIfMissing({tostring(propertyId), 'P'}) end
entityId = entityId or mw.wikibase.getEntityIdForCurrentPage()
if propertyId == nil or entityId == nil then return nil end
claims = mw.wikibase.getBestStatements(entityId, propertyId)
end
if not claims then return nil end
return extractWikidataIdsFromClaimList(claims)
end
local timestampComparator = function(p1, p2)
if p1 and p2 then
local q1 = p1.qualifiers
local q2 = p2.qualifiers
local d1 = nil
local d2 = nil
if q1 and q2 then
if q1['P580'] and q1['P580'][1] and q1['P580'][1].datavalue then
d1 = p.extractDateFromClaim(q1['P580'][1])
end
if q2['P580'] and q2['P580'][1] and q2['P580'][1].datavalue then
d2 = p.extractDateFromClaim(q2['P580'][1])
end
if d1 and d2 then return DateUtils.compare(d1, d2) > 0
elseif d1 then return true
elseif d2 then return false end
elseif q1 then return true
elseif q2 then return false
end
else
if p1 then return true end
if p2 then return false end
end
return false
end
p.findBestClaimsForProperty = function(entity, propertyId)
if propertyId == nil then return nil end
if entity == nil then entity = mw.wikibase.getEntityIdForCurrentPage() end
if type(entity) == 'table' then return entity:getBestStatements(propertyId) end
if type(entity) == 'number' then entity = StringUtils._prependIfMissing({tostring(entity), 'Q'}) end
if entity == nil then return nil end
return mw.wikibase.getBestStatements(entity, propertyId)
end
p.findClaimsForProperty = function(entity, propertyId)
if propertyId == nil then return nil end
if entity == nil then entity = mw.wikibase.getEntityIdForCurrentPage() end
if type(entity) == 'table' and entity.claims then return entity.claims[propertyId] end
if type(entity) == 'number' then entity = StringUtils._prependIfMissing({tostring(entity), 'Q'}) end
if entity == nil then return nil end
return mw.wikibase.getAllStatements(entity, propertyId)
end
p.findClaimsForPropertyByType = function(entity, propertyId, typeIds)
local ret = {}
if propertyId == nil then return nil end
if entity == nil then entity = mw.wikibase.getEntityIdForCurrentPage() end
local claims = {}
if type(entity) == 'table' and entity.claims then
claims = entity.claims[propertyId]
else
if type(entity) == 'number' then entity = StringUtils._prependIfMissing({tostring(entity), 'Q'}) end
if entity == nil then return nil end
claims = mw.wikibase.getBestStatements(entity, propertyId)
end
for k, v in pairs(claims) do
local snak = v.mainsnak
local end_date = p.findQualifierValueListForClaim(v, "P582")
if #end_date == 0 and isValueSnak(snak) and snak.datavalue.type == "wikibase-entityid" then
value = snak.datavalue.value.id
if p.isA(value, typeIds) then
table.insert(ret, v)
end
end
end
return ret
end
p.getClaimsForPropertyByType = function(frame)
local args = getArgs(frame)
local propertyID, entityID, typeId
local raw = false
local ret = {}
propertyID, entityID = propAndEntity(args[1] or '', args[2] or '')
typeId = {args[3]}
if args['raw'] then raw = true end
local entity = nil
if entityID ~= "" then entity = mw.wikibase.getEntityObject(entityID) end
if entity == nil then entity = mw.wikibase.getEntityObject() end
if entity == nil then return "" end
local claims = p.findClaimsForPropertyByType(entity, propertyID, typeId)
if not claims then return "" end
for _,eachClaim in ipairs(claims) do
if hasValueSnak(eachClaim) then
if raw then
table.insert(ret, printRawValue(eachClaim.mainsnak))
else
table.insert(ret, snakToString(eachClaim.mainsnak))
end
end
end
return table.concat(ret, ", ")
end
p.findSortedClaimsForProperty = function(entity, propertyId)
local rawClaims = p.findClaimsForProperty(entity, propertyId)
if rawClaims == nil then return {} end
table.sort(rawClaims, timestampComparator)
return rawClaims
end
p.findQualifierValueListForClaim = function(claim, qualifierId)
if claim == nil or claim.qualifiers == nil or qualifierId == nil then return {} end
local quals = {}
local wikidataQualifiers = claim.qualifiers[qualifierId]
if wikidataQualifiers then
for qualK, qualV in pairs(wikidataQualifiers) do
if isValueSnak(qualV) then
table.insert(quals, snakToString(qualV))
end
end
end
return quals
end
p.getQualifierValue = function(frame)
local propertyID = mw.text.trim(frame.args[1] or "")
local qualifierID = mw.text.trim(frame.args[2] or "")
local entity = mw.wikibase.getEntity()
if entity and entity.claims ~= nil and entity.claims[propertyID] ~= nil then
local out = {}
for k, v in pairs(entity.claims[propertyID]) do
if v.qualifiers and v.qualifiers[qualifierID] then
for k2, v2 in pairs(v.qualifiers[qualifierID]) do
if isValueSnak(v2) == 'value' then
table.insert(out, snakToString(v2))
end
end
end
end
return table.concat(out, ", ")
else
return ""
end
end
-- This is used to get a value like 'male' (for property p21) which won't be linked and numbers without the thousand separators
p.getRawValue = function(frame)
local propertyID = mw.text.trim(frame.args[1] or "")
local input_parm = mw.text.trim(frame.args[2] or "")
local entity = mw.wikibase.getEntityObject()
local claims = nil
if entity and entity.claims then
claims = entity.claims[propertyID]
end
if claims then
local result = entity:formatPropertyValues(propertyID, mw.wikibase.entity.claimRanks).value
-- if number type: remove thousand separators
if (hasValueSnak(claims[1]) and claims[1].mainsnak.datavalue.type == "quantity") then
result = mw.ustring.gsub(result, "(%d),(%d)", "%1%2")
end
return result
else
return ""
end
end
p.getRawQualifierValue = function(frame)
local propertyID = mw.text.trim(frame.args[1] or "")
local qualifierID = mw.text.trim(frame.args[2] or "")
local input_parm = mw.text.trim(frame.args[3] or "")
if input_parm == "FETCH_WIKIDATA" then
local entity = mw.wikibase.getEntity()
if entity.claims[propertyID] ~= nil then
local out = {}
for k, v in pairs(entity.claims[propertyID]) do
for k2, v2 in pairs(v.qualifiers[qualifierID]) do
if isValueSnak(v2) then
if v2.datavalue.value["numeric-id"] then
out[#out + 1] = mw.wikibase.label("Q" .. v2.datavalue.value["numeric-id"])
else
out[#out + 1] = v2.datavalue.value
end
end
end
end
local ret = table.concat(out, ", ")
return string.upper(string.sub(ret, 1, 1)) .. string.sub(ret, 2)
else
return ""
end
else
return input_parm
end
end
p.extractDateFromClaim = function(claimOrSnak)
local claim
if claimOrSnak.mainsnak then claim = claimOrSnak.mainsnak else claim = claimOrSnak end
if claim.datatype == 'time' and isValueSnak(claim) then
local d = {}
local iSOTimeSign = mw.ustring.sub(claim.datavalue.value.time, 1, 1)
d.precision = tonumber(claim.datavalue.value.precision)
d.calendarmodel = claim.datavalue.value.calendarmodel
wdDate = DateUtils.parseWikidataDate(claim.datavalue.value.time, d.precision)
if wdDate ~= nil then
d.month = wdDate.month
d.day = wdDate.day
else
d.month = 1
d.day = 1
end
if d.precision <= 9 then
d.year = tonumber(mw.ustring.match(claim.datavalue.value.time, "%d+"))
if iSOTimeSign == '-' then d.year = -d.year end
elseif wdDate ~= nil then
d.year = wdDate.year
else
d.year = 1
end
d.claim = claimOrSnak
return d
end
return nil
end
p.findDateValues = function(propertyId, entityId)
entityId = entityId or mw.wikibase.getEntityIdForCurrentPage()
if entityId then
local bestclaims = mw.wikibase.getBestStatements(entityId, propertyId)
local bestdates = {}
if bestclaims then for k, v in pairs(bestclaims) do
if hasValueSnak(v) and v.mainsnak.datatype == 'time' then
local d = p.extractDateFromClaim(v)
table.insert(bestdates, d)
elseif hasValueSnak(v) then
local d = {}
d.claim = v
table.insert(bestdates, d)
end
end end
return bestdates
end
end
-- This is used to get a date value for date_of_birth (p569), etc. which won't be linked -- consolidate by testing if entity.claims[propertyID].mainsnak.datavalue.type is "time"
-- Dates are stored as 28 characters if the year >99 -- e.g. +00000002014-01-01T00:00:00Z for 2014
-- Dates are stored as 26 characters if the year =<99 -- e.g. +000000050-01-01T00:00:00Z for 50 CE
p.getDateValue = function(frame)
local args = getArgs(frame, { frameOnly = true })
local propertyId = args[1]
local entityId = args[2] or mw.wikibase.getEntityIdForCurrentPage()
if entityId then
local claims = mw.wikibase.getAllStatements(entityId, propertyId)
local out = {}
if claims then for _,eachClaim in pairs(claims) do
if hasValueSnak(eachClaim) then
local extractedDate = p.extractDateFromClaim(eachClaim)
table.insert(out, GregorianDate.displayDualDateIfInInterval(extractedDate, true))
end
end end
return table.concat(out, ", ")
else
return ""
end
end
p.getQualifierDateValue = function(frame)
local propertyID = mw.text.trim(frame.args[1] or "")
local qualifierID = mw.text.trim(frame.args[2] or "")
local input_parm = mw.text.trim(frame.args[3] or "")
local date_format = mw.text.trim(frame.args[4] or "dmy")
if input_parm == "FETCH_WIKIDATA" then
local entity = mw.wikibase.getEntity()
if entity.claims[propertyID] ~= nil then
local out = {}
local dt = {}
for k, v in pairs(entity.claims[propertyID]) do
for k2, v2 in pairs(v.qualifiers[qualifierID]) do
if isValueSnak(v2) then
local d = v2.datavalue.value.time
if #d > 26 then
dt.year = string.sub(d, 9, 12)
dt.month = string.sub(d, 14, 15)
dt.day = string.sub(d, 17, 18)
else
dt.year = string.sub(d, 9, 10)
dt.month = string.sub(d, 12, 13)
dt.day = string.sub(d, 15, 16)
end
if date_format == "mdy" then
out[#out + 1] = os.date("%B %e, %Y", os.time(dt))
elseif date_format == "my" then
out[#out + 1] = os.date("%B %Y", os.time(dt))
elseif date_format == "y" then
out[#out + 1] = os.date("%Y", os.time(dt))
else
out[#out + 1] = os.date("%e %B %Y", os.time(dt))
end
end
end
end
return table.concat(out, ", ")
else
return ""
end
else
return input_parm
end
end
-- returns the value of the specified qualifier for the specified preferred value of the property of the specified entity (or the current entity)
p.findQualifierForPreferredPropertyValue = function(entityId, propertyId, qualifierId, separator)
entityId = entityId or mw.wikibase.getEntityIdForCurrentPage()
if entityId == nil then return nil end
local claims = mw.wikibase.getAllStatements(entityId, propertyId)
local out = {}
if claims and claims[1] then
for claimK, claimV in pairs(claims) do
if claimV.rank == 'preferred' then
local qual = claimV.qualifiers[qualifierId]
if qual and qual.mainsnak then table.insert(out, snakToString(qual)) end
end
end
end
return table.concat(out, separator)
end
p.getQualifierForPreferredPropertyValue = function(frame)
local args = getArgs(frame)
local entityId = args['entityId'] or args[1]
local propertyId = args['propertyId'] or args[2]
local qualifierId = args['qualifierId'] or args[3]
local separator = args['separator'] or args[4] or ', '
return p.findQualifierForPreferredPropertyValue(entityId, propertyId, qualifierId, separator)
end
-- This is used to get the TA98 (Terminologia Anatomica first edition 1998) values like 'A01.1.00.005' (property P1323)
-- which are then linked to http://www.unifr.ch/ifaa/Public/EntryPage/TA98%20Tree/Entity%20TA98%20EN/01.1.00.005%20Entity%20TA98%20EN.htm
-- uses the newer mw.wikibase calls instead of directly using the snaks
-- formatPropertyValues returns a table with the P1323 values concatenated with ", " so we have to split them out into a table in order to construct the return string
p.getTAValue = function(frame)
local ent = mw.wikibase.getEntityObject()
local props = ent:formatPropertyValues('P1323')
local out = {}
local t = {}
for k, v in pairs(props) do
if k == 'value' then
t = mw.text.split( v, ", ")
for k2, v2 in pairs(t) do
out[#out + 1] = "[http://www.unifr.ch/ifaa/Public/EntryPage/TA98%20Tree/Entity%20TA98%20EN/" .. string.sub(v2, 2) .. "%20Entity%20TA98%20EN.htm " .. v2 .. "]"
end
end
end
ret = table.concat(out, "<br> ")
if #ret == 0 then
ret = "Invalid TA"
end
return ret
end
-- returns the page id (Q...) of the current page or nothing of the page is not connected to Wikidata
p.pageId = p.getEntityId
-- the "qualifiers" and "snaks" field have a respective "qualifiers-order" and "snaks-order" field
-- use these as the second parameter and this function instead of the built-in "pairs" function
-- to iterate over all qualifiers and snaks in the intended order.
local function orderedpairs(array, order)
if not order then return pairs(array) end
-- return iterator function
local i = 0
return function()
i = i + 1
if order[i] then
return order[i], array[order[i]]
end
end
end
-- precision: 0 - billion years, 1 - hundred million years, ..., 6 - millennia, 7 - century, 8 - decade, 9 - year, 10 - month, 11 - day, 12 - hour, 13 - minute, 14 - second
local function normalizeDate(date)
date = mw.text.trim(date, "+")
-- extract year
local yearstr = mw.ustring.match(date, "^\-?%d+")
local year = tonumber(yearstr)
-- remove leading zeros of year
return year .. mw.ustring.sub(date, #yearstr + 1), year
end
function formatDate(indate, precision, timezone)
precision = precision or 11
date, year = normalizeDate(indate)
if year == 0 and precision <= 9 then return "" end
-- precision is 10000 years or more
if precision <= 5 then
local factor = 10 ^ ((5 - precision) + 4)
local y2 = math.ceil(math.abs(year) / factor)
local relative = mw.ustring.gsub(i18n.datetime[precision], "$1", tostring(y2))
if year < 0 then
relative = mw.ustring.gsub(i18n.datetime.beforenow, "$1", relative)
else
relative = mw.ustring.gsub(i18n.datetime.afternow, "$1", relative)
end
return relative
end
-- precision is decades, centuries and millennia
local era
if precision == 6 then era = mw.ustring.gsub(i18n.datetime[6], "$1", tostring(math.floor((math.abs(year) - 1) / 1000) + 1)) end
if era then
if year < 0 then era = mw.ustring.gsub(mw.ustring.gsub(i18n.datetime.bc, '"', ""), "$1", era)
elseif year > 0 then era = mw.ustring.gsub(mw.ustring.gsub(i18n.datetime.ad, '"', ""), "$1", era) end
return era
end
if precision >= 7 then
return DateUtils.formatDate(DateUtils.parseWikidataDate(indate, precision))
end
end
local function printDatavalueEntity(data, parameter)
-- data fields: entity-type [string], numeric-id [int, Wikidata id]
local id = "Q" .. data["numeric-id"]
if parameter then
if parameter == "link" then
return "[[" .. (mw.wikibase.sitelink(id) or (":d:" .. id)) .. "|" .. (mw.wikibase.label(id) or id) .. "]]"
else
return data[parameter]
end
else
if data["entity-type"] == "item" then return mw.wikibase.label("Q" .. data["numeric-id"]) or id else printError("unknown-entity-type") end
end
end
local function printDatavalueTime(data, parameter)
-- data fields: time [ISO 8601 time], timezone [int in minutes], before [int], after [int], precision [int], calendarmodel [wikidata URI]
-- precision: 0 - billion years, 1 - hundred million years, ..., 6 - millennia, 7 - century, 8 - decade, 9 - year, 10 - month, 11 - day, 12 - hour, 13 - minute, 14 - second
-- calendarmodel: e.g. http://www.wikidata.org/entity/Q1985727 for the proleptic Gregorian calendar or http://www.wikidata.org/wiki/Q11184 for the Julian calendar]
if parameter then
if parameter == "calendarmodel" then data.calendarmodel = mw.ustring.match(data.calendarmodel, "Q%d+") -- extract entity id from the calendar model URI
elseif parameter == "time" then data.time = normalizeDate(data.time) end
return data[parameter]
else
return formatDate(data.time, data.precision, data.timezone)
end
end
function findClaims(entity, property)
if not property or not entity or not entity.claims then return end
if mw.ustring.match(property, "^P%d+$") then
-- if the property is given by an id (P..) access the claim list by this id
return entity.claims[property]
else
property = mw.wikibase.resolvePropertyId(property)
if not property then return end
return entity.claims[property]
end
end
function getSnakValue(snak, parameter)
-- snaks have three types: "novalue" for null/nil, "somevalue" for not null/not nil, or "value" for actual data
if snak.snaktype == "novalue" then return i18n["novalue"]
elseif snak.snaktype == "somevalue" then return i18n["somevalue"]
elseif snak.snaktype ~= "value" then return nil, printError("unknown-snak-type")
end
-- call the respective snak parser
if snak.datavalue.type == "string" then return snak.datavalue.value
elseif snak.datavalue.type == "globecoordinate" then return printDatavalueCoordinate(snak.datavalue.value, parameter)
elseif snak.datavalue.type == "quantity" then return printDatavalueQuantity(snak.datavalue.value, parameter)
elseif snak.datavalue.type == "time" then return printDatavalueTime(snak.datavalue.value, parameter)
elseif snak.datavalue.type == "wikibase-entityid" then return printDatavalueEntity(snak.datavalue.value, parameter)
elseif snak.datavalue.type == "monolingualtext" then return printDatavalueMonolingualText(snak.datavalue.value, parameter)
else return nil, printError("unknown-datavalue-type")
end
end
function getQualifierSnak(claim, qualifierId)
-- a "snak" is Wikidata terminology for a typed key/value pair
-- a claim consists of a main snak holding the main information of this claim,
-- as well as a list of attribute snaks and a list of references snaks
if qualifierId then
-- search the attribute snak with the given qualifier as key
if claim.qualifiers then
local qualifier = claim.qualifiers[qualifierId]
if qualifier then return qualifier[1] end
end
return nil, printError("qualifier-not-found")
else
-- otherwise return the main snak
return claim.mainsnak
end
end
function getValueOfClaim(claim, qualifierId, parameter)
local error
local snak
snak, error = getQualifierSnak(claim, qualifierId)
if snak then
return getSnakValue(snak, parameter)
else
return nil, error
end
end
function p.claim(frame)
local property = frame.args[1] or ""
local id = frame.args["id"] -- "id" must be nil, as access to other Wikidata objects is disabled in Mediawiki configuration
local qualifierId = frame.args["qualifier"]
local parameter = frame.args["parameter"]
local list = frame.args["list"]
local references = frame.args["references"]
local showerrors = frame.args["showerrors"]
local default = frame.args["default"]
if default then showerrors = nil end
-- get wikidata entity
local entity = mw.wikibase.getEntityObject(id)
if not entity then
if showerrors then return printError("entity-not-found") else return default end
end
-- fetch the first claim of satisfying the given property
local claims = findClaims(entity, property)
if not claims or not claims[1] then
if showerrors then return printError("property-not-found") else return default end
end
-- get initial sort indices
local sortindices = {}
for idx in pairs(claims) do
sortindices[#sortindices + 1] = idx
end
-- sort by claim rank
local comparator = function(a, b)
local rankmap = { deprecated = 2, normal = 1, preferred = 0 }
local ranka = rankmap[claims[a].rank or "normal"] .. string.format("%08d", a)
local rankb = rankmap[claims[b].rank or "normal"] .. string.format("%08d", b)
return ranka < rankb
end
table.sort(sortindices, comparator)
local result
local error
if list then
local value
-- iterate over all elements and return their value (if existing)
result = {}
for idx in pairs(claims) do
local claim = claims[sortindices[idx]]
value, error = getValueOfClaim(claim, qualifierId, parameter)
if not value and showerrors then value = error end
if value and references then value = value .. p.outputReferences(claim) end
result[#result + 1] = value
end
result = table.concat(result, list)
else
-- return first element
local claim = claims[sortindices[1]]
result, error = getValueOfClaim(claim, qualifierId, parameter)
if result and references then result = result .. p.outputReferences(claim) end
end
if result then return result else
if showerrors then return error else return default end
end
end
p.getPreferredValue = function(frame)
local args = getArgs(frame)
local propertyID = args[1] or args['propertyId'] or args['pid']
local entityID = args[2] or args['entityId'] or args['qid'] or mw.wikibase.getEntityIdForCurrentPage()
if entityID == nil or propertyID == nil then return nil end
local claims = mw.wikibase.getAllStatements(entityID, propertyID)
if claims then
-- if wiki-linked value output as link if possible
if hasValueSnak(claims[1]) then
local out = {}
for k, v in pairs(claims) do
if (v.rank == 'preferred') then
local snakText = snakToString(v.mainsnak) .. p.outputReferences(v)
if snakText ~= "" then
out[#out + 1] = snakText
end
end
end
return table.concat(out, ", ")
end
else
return ""
end
return ""
end
-- look into entity object
function p.ViewSomething(frame)
local data = mw.wikibase.getEntityObject()
if not data then
return nil
end
local f = frame.args[1] and frame or frame:getParent()
local i = 1
while true do
local index = f.args[i]
if not index then
return tostring(data)
end
data = data[index] or data[tonumber(index)]
if not data then
return
end
i = i + 1
end
end
function p.Dump(frame)
local data = mw.wikibase.getEntityObject()
if not data then
return i18n.warnDump
end
local f = frame.args[1] and frame or frame:getParent()
local i = 1
while true do
local index = f.args[i]
if not index then
return "<pre>"..mw.dumpObject(data).."</pre>".. i18n.warnDump
end
data = data[index] or data[tonumber(index)]
if not data then
return i18n.warnDump
end
i = i + 1
end
end
-- Returnează o singură valoare din cele cu rangul cel mai înalt cu referințele corespunzătoare pentru o proprietate specificată
-- De apelat din alte module
function p.findOneValue(propertyID, entity)
local entityId = nil
if type(entity) == 'table' then entityId = entity.id
elseif type(entity) == 'number' then entityId = StringUtils._prependIfMissing({tostring(entity), 'Q'})
elseif type(entity) == 'string' then entityId = entity
end
entityId = entityId or mw.wikibase.getEntityIdForCurrentPage()
if not entityId then return nil end
local claims = mw.wikibase.getBestStatements(entityId, propertyID)
if claims and 0 < #claims then
for _,eachClaim in ipairs(claims) do
if hasValueSnak(eachClaim) then
return snakToString(eachClaim.mainsnak) .. p.outputReferences(eachClaim)
end
end
end
return nil
end
-- Returnează o singură valoare din cele cu rangul cel mai înalt pentru o proprietate specificată
-- De apelat din alte module
function p.findOneValueNoRef(propertyID, entity)
local claims = nil
if type(entity) == 'table' then
claims = entity:getBestStatements(propertyID)
else
if type(entity) == 'number' then entity = 'Q' .. tostring(entity) end
entity = entity or mw.wikibase.getEntityIdForCurrentPage()
if not entity then return nil end
claims = mw.wikibase.getBestStatements(entity, propertyID)
end
if claims and 0 < #claims then
for _,eachClaim in ipairs(claims) do
if hasValueSnak(eachClaim) then
return snakToString(eachClaim.mainsnak)
end
end
end
return nil
end
-- Returnează o singură valoare din cele cu rangul cel mai înalt pentru o proprietate specificată
-- De apelat din formate
p.getOneValueNoRef = function(frame)
local propertyID, entityID
propertyID, entityID = propAndEntity(frame.args[1], frame.args[2])
local entity = nil
if entityID ~= "" then entity = mw.wikibase.getEntityObject(entityID) end
if entity == nil then entity = mw.wikibase.getEntityObject() end
if entity == nil then return nil end
return p.findOneValueNoRef(propertyID, entity)
end
-- Returnează o singură valoare din cele cu rangul cel mai înalt și cu referințele corespunzătoare pentru o proprietate specificată
-- De apelat din formate
p.getOneValue = function(frame)
local args = getArgs(frame)
local propertyID, entityID
propertyID, entityID = propAndEntity(args[1], args[2])
local entity = nil
if entityID ~= "" then entity = mw.wikibase.getEntityObject(entityID) end
if entity == nil then entity = mw.wikibase.getEntityObject() end
if entity == nil then return nil end
return p.findOneValue(propertyID, entity)
end
local function findLatestQualifierValueForOnePropertyOfAnEntity(entity, propertyId, qualifierId)
if entity == nil then
entity = mw.wikibase.getEntityObject()
end
if entity == nil then return '' end
local claims = entity:getBestStatements(propertyId)
if claims then
if claims[1] then
if claims[1].qualifiers then
if claims[1].qualifiers[qualifierId] then
local allQualifiers = {}
for qk, qv in pairs(claims[1].qualifiers[qualifierId]) do
table.insert(allQualifiers, qv)
end
local qIndex = 1
local maxQTime = nil
while maxQTime == nil and qIndex <= #allQualifiers do
if allQualifiers[qIndex].datatype == 'time' then
maxQTime = allQualifiers[qIndex]
end
qIndex = qIndex + 1
end
if maxQTime ~= nil then
for i=qIndex,#allQualifiers do
local msCrtQTime = tonumber(mw.language.new(lang.code):formatDate('U', allQualifiers[i].datavalue.value.time, nil))
local msMaxQTime = tonumber(mw.language.new(lang.code):formatDate('U', maxQTime.datavalue.value.time, nil))
if msCrtQTime > msMaxQTime then
maxQTime = allQualifiers[i]
end
end
if isValueSnak(maxQTime) then
return formatDate(maxQTime.datavalue.value.time, maxQTime.datavalue.value.precision, maxQTime.datavalue.value.timezone)
end
end
return ""
else
return ""
end
else
return ""
end
else
return ""
end
else
return ""
end
end
-- Returnează valoarea cea mai recentă a qualifierului specificat pentru proprietea specificată a entității curente
-- De apelat din alte module
p.getLatestQualifierDateValueForOneProperty = function(frame)
local propertyId = mw.text.trim(frame.args[1] or "")
local qualifierId = mw.text.trim(frame.args[2] or "")
local entity = mw.wikibase.getEntityObject()
return findLatestQualifierValueForOnePropertyOfAnEntity(entity, propertyId, qualifierId)
end
-- Returnează valoarea cea mai recentă a qualifierului specificat pentru proprietea specificată a entității curente
-- De apelat din formate
p.findLatestQualifierDateValueForOneProperty = function(propertyId, qualifierId)
local entity = mw.wikibase.getEntityObject()
return entity ~= nil and findLatestQualifierValueForOnePropertyOfAnEntity(entity, propertyId, qualifierId) or ''
end
-- Returnează un text ce conține referința pentru o proprietate; de apelat din formate
p.getReferenceForOneProperty = function(frame)
local entity = mw.wikibase.getEntityObject()
local propertyId = mw.text.trim(frame.args[1])
local claims = entity:getBestStatements(propertyId)
return p.outputReferences(claims[1])
end
-- Returnează o listă cu obiecte value asociate unei proprietăți a unei entități
-- Creată pentru a obține lista de coordonate a unui oraș în formă pură (listă cu obiectele value asociate)
-- Funcționează pentru: coordonate
-- TODO - de extins la mai multe tipuri de date, de exemplu texte multilingve, date calendaristice, itemuri wikibase
p.findDataValueObjects = function(entityId, propertyId)
if propertyId == nil then return {} end
entityId = entityId or mw.wikibase.getEntityIdForCurrentPage()
if entityId == nil then return {} end
local ret = {}
local claims = mw.wikibase.getAllStatements(entityId, propertyId)
if claims == nil then return ret end
for claimIdx = 1, #claims do
local snak = claims[claimIdx].mainsnak
if isValueSnak(snak) then
if snak.datatype == 'globe-coordinate' then
table.insert(ret, snak.datavalue.value)
end
end
end
return ret
end
p.findRoLabel = function(entityId)
entityId = entityId or mw.wikibase.getEntityIdForCurrentPage()
if entityId then
return mw.wikibase.getLabelByLang(entityId, lang.code)
end
return nil
end
p.getRoLabel = function(frame)
local args = getArgs(frame)
return p.findRoLabel(args[1])
end
-- Returnează labelul unei entități în limba specificată; dacă nu se găsește, atunci se încearcă în limba wikiului și apoi în limba engleză
p.findLabel = function(entityId, languageCode, default)
local entity, ret
if entityId == nil then
entityId = mw.wikibase.getEntityIdForCurrentPage()
if not entityId then return default or '' end
end
if type(entityId) == 'number' then
entityId = 'Q' .. tostring(entityId)
end
if type(entityId) == 'string' then
if languageCode then
ret = mw.wikibase.getLabelByLang(entityId, languageCode)
end
if not ret then
ret = mw.wikibase.getLabel(entityId)
end
return ret or default or mw.wikibase.getLabelByLang(entityId, 'en') or entityId
end
if type(entityId) == 'table' then
local entity = entityId
if not languageCode or languageCode == '' then languageCode = lang.code end
ret = entity:getLabel(languageCode) or entity:getLabel(lang.code) or default or entity:getLabel('en')
return ret
end
return default or ''
end
p.getLabel = function(frame)
local args = getArgs(frame, {frameOnly=true})
local entityId = args[1]
local languageCode = args[2] or lang.code
local default = args['default']
return p.findLabel(entityId, languageCode, default)
end
function formatCoordinates(entityId)
entityId = entityId or mw.wikibase.getEntityIdForCurrentPage()
if entityId == nil then return '' end
local coordClaims = mw.wikibase.getAllStatements(entityId, 'P625')
local formattedCoordsList = {}
if coordClaims and coordClaims[1] then
for coordIdx=1,#coordClaims do
if coordClaims[coordIdx].mainsnak.datatype == 'globe-coordinate' then
local latDir = coordClaims[coordIdx].mainsnak.datavalue.value.latitude < 0 and 'S' or 'N'
local lonDir = coordClaims[coordIdx].mainsnak.datavalue.value.longitude < 0 and 'V' or 'E'
local coordsText = mw.getCurrentFrame():expandTemplate{title='Coord', args={tostring(math.abs(coordClaims[coordIdx].mainsnak.datavalue.value.latitude)), latDir, tostring(math.abs(coordClaims[coordIdx].mainsnak.datavalue.value.longitude)), lonDir}}
table.insert(formattedCoordsList, coordsText)
end
end
end
return table.concat(formattedCoordsList, ', ')
end
p.getFormattedCoordinates = function(frame)
local origArgs = getArgs(frame)
return formatCoordinates(origArgs[1] or origArgs['entityId'])
end
-- Returnează o numărul de valori cu cel mai mare rang pentru o proprietate specificată
-- De apelat din alte module
function p.countBestValues(propertyID, entity)
if type(entity) == 'table' then
entity = entity.id
elseif type(entity) == 'number' then
entity = 'Q' .. tostring(entity)
elseif entity == nil then
entity = mw.wikibase.getEntityIdForCurrentPage()
if entity == nil then return 0 end
end
local claims = mw.wikibase.getBestStatements(entity, propertyID)
local outList = {}
if not claims then return 0 end
return #claims
end
-- Returnează o singură valoare din cele cu rangul cel mai înalt cu referințele corespunzătoare pentru o proprietate specificată
-- De apelat din alte module
function p.findBestValues(propertyID, entity)
if type(entity) == 'table' then
entity = entity.id
elseif type(entity) == 'number' then
entity = 'Q' .. tostring(entity)
end
if entity == nil then
entity = mw.wikibase.getEntityIdForCurrentPage()
if entity == nil then return {} end
end
if not StringUtils._emptyToNil({propertyID}) then return nil end
local claims = mw.wikibase.getBestStatements(entity, propertyID)
local outList = {}
if claims then for claimIdx, actualClaim in pairs(claims) do
if hasValueSnak(actualClaim) then
table.insert(outList, snakToString(actualClaim.mainsnak) .. p.outputReferences(actualClaim))
end
end end
return outList
end
p._getBestValuesWithSeparator = function(entity, propertyID, sep)
if propertyID == nil then return '' end
local valueList = p.findBestValues(propertyID, entity)
return valueList and table.concat(valueList, sep)
end
-- Returnează o listă a valorilor cu rangul cel mai înalt și cu referințele corespunzătoare pentru o proprietate specificată
-- De apelat din formate
p.getBestValuesWithSeparator = function(frame)
local sep = frame.args[1]
if sep == nil or sep == '' then sep = ', ' end
local propertyID = mw.text.trim(frame.args[2] or "")
local entityID = mw.text.trim(frame.args[3] or "")
local entity = nil
if entityID ~= "" then entity = mw.wikibase.getEntityObject(entityID) end
if entity == nil then entity = mw.wikibase.getEntityObject() end
return p._getBestValuesWithSeparator(entity, propertyID, sep)
end
function p.findLanguageText(propertyId, langcode, entityId)
-- return label of a Wikidata entity in the given language or the default language of this Wikipedia site
entityId = entityId or mw.wikibase.getEntityIdForCurrentPage()
if not entityId then return nil end
local returnValue = nil
langcode = langcode or 'ro'
for eachClaimIdx, eachClaim in pairs(mw.wikibase.getAllStatements(entityId, propertyId)) do
if hasValueSnak(eachClaim) and eachClaim.mainsnak.datavalue then
if eachClaim.mainsnak.datavalue.type == 'monolingualtext' then
if eachClaim.mainsnak.datavalue.value.language == langcode then returnValue = eachClaim.mainsnak.datavalue.value.text end
elseif eachClaim.mainsnak.datavalue.type == 'string' then
returnValue = eachClaim.mainsnak.datavalue.value
elseif eachClaim.mainsnak.datavalue.type == 'wikibase-entityid' then
returnValue = p.findLabel(eachClaim.mainsnak.datavalue.value.id, langcode)
end
end
end
return returnValue
end
function p.getLanguageText(frame)
return p.findLanguageText(frame.args[1], frame.args[2] or 'ro', frame.args[3]) or ''
end
function p.findBestValuesForLocalLanguage(propertyId, entityId)
entityId = entityId or mw.wikibase.getEntityIdForCurrentPage()
if not entityId then return nil end
local bestValues = {}
local bestRank = nil
for eachClaimIdx, eachClaim in pairs(mw.wikibase.getAllStatements(entityId, propertyId)) do
if (hasValueSnak(eachClaim) and eachClaim.qualifiers and eachClaim.qualifiers['P407'] and 0 < #(eachClaim.qualifiers['P407'])) then
if hasBetterRank(eachClaim, bestRank) then
for _,eachLangQual in ipairs(eachClaim.qualifiers['P655']) do
if isValueSnak(eachLangQual) and eachLangQual.datavalue.value.id == 'Q7913' then
bestRank = eachLangQual.rank
if not bestRank or mw.wikibase.entity.claimRanks['RANK_' .. mw.ustring.upper(eachClaim.rank)] > mw.wikibase.entity.claimRanks['RANK_' .. mw.ustring.upper(bestRank)] then
bestValues = {}
end
table.insert(bestValues, snakToString(eachClaim.mainsnak))
end
end
end
end
end
return bestValues
end
function p.getBestValuesForLocalLanguageWithSeparator(frame)
return table.concat(p.findBestValuesForLocalLanguage(frame.args[2], frame.args[3]) or {}, frame.args[1])
end
p.findShortestAlias = function(entityId)
return p.findLinkToItem(entityId, false, false, true)
end
p.findImageAndCaption = function(entityId)
local wikidataImages = p.findBestClaimsForProperty(entityId, 'P2716')
if not wikidataImages or #wikidataImages == 0 then
wikidataImages = p.findBestClaimsForProperty(entityId, 'P18')
end
local imageName, imageCaption
if wikidataImages and #wikidataImages > 0 then
local wikidataImage = wikidataImages[1]
if hasValueSnak(wikidataImage) and wikidataImage.mainsnak.datavalue then
imageName = wikidataImage.mainsnak.datavalue.value
local roDescr = ''
if wikidataImage.qualifiers and wikidataImage.qualifiers['P2096'] then
for _,eachImageDescrLangString in pairs(wikidataImage.qualifiers['P2096']) do
if isValueSnak(eachImageDescrLangString) and eachImageDescrLangString.datavalue and eachImageDescrLangString.datavalue.value.language == 'ro' then
roDescr = eachImageDescrLangString.datavalue.value.text or roDescr
end
end
end
imageCaption = roDescr
end
end
return imageName, imageCaption
end
p.findLinkToWikidataItem = function(itemId, prefix)
libraryUtil.checkType('findLinkToWikidataItem', 2, prefix, 'string', false)
local qId = StringUtils._prependIfMissing({itemId, prefix})
local itemLabel = p.findLabel(qId)
return '[[:d:' .. (prefix == 'P' and 'Property:' or '') .. qId .. '|' .. (itemLabel or '') .. ' ' .. tostring(mw.html.create('small'):wikitext('(' .. qId .. ')')) .. ']]'
end
p.getLinkToWikidataItem = function(frame)
local args = getArgs(frame)
local prefix = args['prefix'] or 'Q'
if not args[1] then return "''id de " .. (prefix == 'P' and 'proprietate' or 'item') .. " Wikidata nespecificat''" end
return p.findLinkToWikidataItem(args[1], prefix)
end
p.formatExternalLink = function(pId, qId, text)
local formatterUrl = p.findOneValueNoRef('P1630', pId) or '$1'
local urlComponent = text or p.findOneValueNoRef(pId, qId)
if not urlComponent then return nil end
local formattedLink = mw.ustring.gsub(formatterUrl, '%$1', text or urlComponent)
return formattedLink
end
p.getFormattedExternalLink = function(frame)
local args = getArgs(frame)
local pId = args['pid'] or args[1]
local qId = args['qid'] or args[2]
local text = args['text']
return p.formatExternalLink(pId, qId, text)
end
p.isFemale = function(qId)
local entityId = qId or mw.wikibase.getEntityIdForCurrentPage()
if not entityId then return false end
local genders = mw.wikibase.getBestStatements(entityId, 'P21')
local feminineIds = { 6581072, 1052281, 43445 }
if genders then for genderIdx,eachGender in ipairs(genders) do
if hasValueSnak(eachGender) then for _,eachFemId in ipairs(feminineIds) do
if eachFemId == eachGender.mainsnak.datavalue.value['numeric-id'] then return true end
end end
end end
return false
end
p.findClaimForTimestamp = function(entityId, propertyId, timestamp, lang)
local propClaims = p.findSortedClaimsForProperty(entityId, propertyId)
local bestClaim = nil
if propClaims then for _,eachPropClaim in ipairs(propClaims) do
if hasValueSnak(eachPropClaim) and isClaimTrue(eachPropClaim) then
if eachPropClaim.mainsnak.datavalue.type ~= 'monolingualtext' or StringUtils._substringBefore({eachPropClaim.mainsnak.datavalue.value.language, '-'}) == StringUtils._substringBefore({lang or 'ro', '-'}) then
local before = nil
local after = nil
if eachPropClaim.qualifiers then
if eachPropClaim.qualifiers['P580'] and eachPropClaim.qualifiers['P580'][1] and isValueSnak(eachPropClaim.qualifiers['P580'][1]) then
after = GregorianDate.convertToGregorianIfInInterval(DateUtils.extractDateFromWikidataSnak(eachPropClaim.qualifiers['P580'][1]))
end
if eachPropClaim.qualifiers['P582'] and eachPropClaim.qualifiers['P582'][1] and isValueSnak(eachPropClaim.qualifiers['P582'][1]) then
before = GregorianDate.convertToGregorianIfInInterval(DateUtils.extractDateFromWikidataSnak(eachPropClaim.qualifiers['P582'][1]))
end
end
if timestamp then
--if before and DateUtils.compare(timestamp, before) > 0 then --the claim list is sorted by before
-- break
--else
if after == nil and before and DateUtils.compare(timestamp, before) < 0 then
return eachPropClaim
elseif after and before and DateUtils.compare(timestamp, before) < 0 and DateUtils.compare(timestamp, after) > 0 then
return eachPropClaim
elseif after and before == nil and DateUtils.compare(timestamp, after) > 0 then
return eachPropClaim
end
--end
end
if not before then
if not bestClaim and hasBetterRank(eachPropClaim, 'normal') or (bestClaim and hasBetterRank(eachPropClaim, bestClaim.rank)) then
bestClaim = eachPropClaim
end
end
end
end
end end
if bestClaim then
return bestClaim
else
return nil
end
end
p.formatOnlineLink = function(linkProp, entityId)
local linkId = p.findOneValueNoRef(linkProp, entityId)
if linkId then
local linkFormatter = p.findOneValueNoRef('P1630', linkProp) or '$1'
if linkFormatter then
linkId = mw.ustring.gsub(linkId, '%%', '%%%%')
local link = mw.ustring.gsub(linkFormatter, '$1', linkId)
return link
end
end
return nil
end
p.getFormattedOnlineLink = function(frame)
local args = getArgs(frame)
return p.formatOnlineLink(args[1], args[2] or mw.wikibase.getEntityIdForCurrentPage())
end
p.findOnlineLinks = function(onlinelinksprops, entityId, extraProps)
local onlinelinks = {}
local onlinelinksprops = onlinelinksprops and #onlinelinksprops > 0 and onlinelinksprops or {'P856', 'P1581', 'P2013', 'P2002', 'P2847', 'P345', 'P3265', 'P3579', 'P3435', 'P2003', 'P2471', 'P2397', 'P953', 'P1065', 'P4173', 'P4431', 'P1968', 'P6634', 'P4264', 'P2572', 'P7085', 'P3789'}
if extraProps and type(extraProps) == 'table' then onlinelinksprops = Set.valueUnion(onlinelinksprops, extraProps) end
for _,eachOnlineLinkProp in ipairs(onlinelinksprops) do
local link = p.formatOnlineLink(eachOnlineLinkProp)
if link then
local linkentities = p.getBestEntityIdsList(eachOnlineLinkProp, 'P1629')
if linkentities and #linkentities > 0 then
local linklabel = p.findLabel(StringUtils._prependIfMissing({linkentities[1], 'Q'}))
table.insert(onlinelinks, '[' .. link .. ' ' .. linklabel .. ']')
end
end
end
return onlinelinks
end
p.getOnlineLinks = function(frame)
local args = getArgs(frame)
local _,entityId = propAndEntity(StringUtils._prependIfMissing({args['qid'], 'Q'}))
local extraPropsStr = args['extras']
local extraProps = nil
if extraPropsStr then extraProps = mw.text.split(extraPropsStr, ',', true) end
local onlinelinksprops = {}
local passedProps = TableTools.compressSparseArray(args)
for __,eachProp in ipairs(passedProps) do
if mw.ustring.match(eachProp, 'P%d+') == eachProp then
table.insert(onlinelinksprops, eachProp)
end
end
return table.concat(p.findOnlineLinks(onlinelinksprops, entityId, extraProps), tostring(mw.html.create('br')))
end
p.findLanguageIndexedLabelsFromProperty = function(entityId, propertyId)
local entity = nil
if entityId then
entityId = StringUtils._prependIfMissing({tostring(entityId), 'Q'})
else
entityId = mw.wikibase.getEntityIdForCurrentPage()
end
local titles = {}
for _,eachTitleClaim in ipairs(mw.wikibase.getAllStatements(entityId, propertyId)) do
if hasValueSnak(eachTitleClaim) then
titles[eachTitleClaim.mainsnak.datavalue.value.language] = eachTitleClaim.mainsnak.datavalue.value.text
end
end
return titles
end
p.findTitleOfWork = function(entityId)
local entity = nil
if entityId then
entityId = StringUtils._prependIfMissing({tostring(entityId), 'Q'})
else
entityId = mw.wikibase.getEntityIdForCurrentPage()
end
--- this comes first just for performance reasons
if entityId then
local localLabel, localLang = mw.wikibase.getLabelWithLang(entityId)
if localLabel and localLang == 'ro' then
return localLabel
end
else
return nil
end
local langs = {}
for _,eachProperty in ipairs({'P364', 'P407'}) do
for __,eachLangClaim in ipairs(mw.wikibase.getAllStatements(entityId, eachProperty)) do
if hasValueSnak(eachLangClaim) then
local langEntityId = eachLangClaim.mainsnak.datavalue.value.id
if LangUtils[langEntityId] then
table.insert(langs, { qid = langEntityId, code = LangUtils[langEntityId] })
elseif langEntityId then
for ___,eachLangCodeClaim in ipairs(mw.wikibase.getAllStatements(langEntityId, 'P424')) do
if hasValueSnak(eachLangCodeClaim) and isClaimTrue(eachLangCodeClaim) then
local sanitizedLangCode = StringUtils._substringBefore({eachLangCodeClaim.mainsnak.datavalue.value, '-'})
sanitizedLangCode = StringUtils._substringBefore({sanitizedLangCode, '_'})
table.insert(langs, { qid = langEntityId, code = sanitizedLangCode} )
end
end
end
end
end
end
table.insert(langs, {qid = 'Q1860', code = 'en'})
local titles = p.findLanguageIndexedLabelsFromProperty(entityId, 'P1476')
if titles['ro'] then return titles['ro'] end
local nonLatinLangs = {}
for _,eachlanguage in ipairs(langs) do
local langText = nil
if isWritingSystemLatn(eachlanguage.qid) then
langText = wrapInLangSpan(titles[eachlanguage.code] or mw.wikibase.getLabelByLang(entityId, eachlanguage.code), eachlanguage.code)
elseif Transliteration.isTransliterationSupported(eachlanguage.code) then
langText = wrapInLangSpan(Transliteration.transliterate(titles[eachlanguage.code] or mw.wikibase.getLabelByLang(entityId, eachlanguage.code), eachlanguage.code), eachlanguage.code)
else
table.insert(nonLatinLangs, eachlanguage.code)
end
if langText then return langText end
end
for _,langCode in ipairs(nonLatinLangs) do
langText = wrapInLangSpan(titles[langCode] or mw.wikibase.getLabelByLang(entityId, langCode), langCode)
if langText then return langText end
end
return entityId
end
p.findTitlesOfWorksFromProperty = function(propertyId, entityId, limit)
if limit == nil then limit = 10 end
if entityId then entityId = StringUtils._prependIfMissing({tostring(entityId), 'Q'})
else entityId = mw.wikibase.getEntityIdForCurrentPage() end
if not entityId then return nil end
local ret = {}
local bestWorksClaims = mw.wikibase.getBestStatements(entityId, propertyId)
for workIdx = 1,math.min(limit, #bestWorksClaims) do
local eachWorkClaim = bestWorksClaims[workIdx]
if hasValueSnak(eachWorkClaim) then
local workId = eachWorkClaim.mainsnak.datavalue.value.id
table.insert(ret, computeLinkToItem(workId, true, nil, function() return p.findTitleOfWork(workId) end))
end
end
return ret
end
p.getTitleOfWorkFromPropertyWithSeparator = function(frame)
local args = getArgs(frame)
local sep = args[1]
local propertyId, entityId = propAndEntity(args[2], args[3])
local limitStr = args['limit']
local limit = tonumber(limitStr or '10')
local retListRaw = p.findTitlesOfWorksFromProperty(propertyId, entityId, limit) or {}
local retList = {}
for _,eachRetVal in ipairs(retListRaw) do
table.insert(retList, "''" .. eachRetVal .. "''")
end
return table.concat(retList, sep)
end
p.loadOneValueInChain = function(chain)
local crtChainElementId = mw.wikibase.getEntityIdForCurrentPage()
local crtChainClaim = nil
local crtChainSnak = nil
local coordComponent = nil
local raw = false
local label = false
local ref = false
for _,eachChainRing in ipairs(chain) do
if mw.ustring.match(eachChainRing, 'Q%d+') == eachChainRing then
crtChainElementId = eachChainRing
elseif mw.ustring.match(eachChainRing, '_P%d+') and crtChainSnak then
local qualPropertyId = mw.ustring.sub(eachChainRing, 2, mw.ustring.len(eachChainRing))
if crtChainClaim.qualifiers and crtChainClaim.qualifiers[qualPropertyId] and #(crtChainClaim.qualifiers[qualPropertyId]) > 0 then
local qualIdx = 1
local propertyQuals = crtChainClaim.qualifiers[qualPropertyId]
while qualIdx <= #propertyQuals and not isValueSnak(propertyQuals[qualIdx]) do
qualIdx = qualIdx + 1
end
if qualIdx <= #propertyQuals and isValueSnak(propertyQuals[qualIdx]) then
local firstValueSnakIdx = qualIdx
if propertyQuals[qualIdx].datavalue.type == 'monolingualtext' then
while qualIdx <= #propertyQuals and (not isValueSnak(propertyQuals[qualIdx]) or propertyQuals[qualIdx].datavalue.value.language ~= 'ro') do
qualIdx = qualIdx + 1
end
end
crtChainSnak = qualIdx <= #propertyQuals and isValueSnak(propertyQuals[qualIdx]) and propertyQuals[qualIdx] or propertyQuals[firstValueSnakIdx]
else
return nil
end
else
return nil
end
elseif mw.ustring.match(eachChainRing, 'P%d+') == eachChainRing then
if isValueSnak(crtChainSnak) and crtChainSnak.datavalue.type == 'wikibase-entityid' then
crtChainElementId = crtChainSnak.datavalue.value.id
crtChainClaim = nil
crtChainSnak = nil
end
if crtChainElementId and not crtChainSnak then
local propertyClaims = mw.wikibase.getBestStatements(crtChainElementId, eachChainRing)
if #propertyClaims < 1 then return nil end
local claimIdx = 1
if propertyClaims[claimIdx].mainsnak.datavalue and propertyClaims[claimIdx].mainsnak.datavalue.type == 'monolingualtext' then
while claimIdx <= #propertyClaims and (not hasValueSnak(propertyClaims[claimIdx]) or propertyClaims[claimIdx].mainsnak.datavalue.value.language ~= 'ro') do
claimIdx = claimIdx + 1
end
else
while claimIdx <= #propertyClaims and not hasValueSnak(propertyClaims[claimIdx]) do
claimIdx = claimIdx + 1
end
end
if claimIdx <= #propertyClaims and hasValueSnak(propertyClaims[claimIdx]) then
crtChainClaim = propertyClaims[claimIdx]
crtChainSnak = crtChainClaim.mainsnak
else
return nil
end
end
elseif eachChainRing == 'lat' or eachChainRing == 'long' then
coordComponent = eachChainRing .. 'itude'
elseif eachChainRing == 'raw' then
raw = true
elseif eachChainRing == 'label' then
if crtChainSnak then crtChainElementId = crtChainSnak.datavalue.value.id end
crtChainClaim = nil
crtChainSnak = nil
label = true
elseif eachChainRing == 'ref' then
ref = true
end
end
if ref and crtChainClaim then
return p.outputReferences(crtChainClaim)
end
if crtChainSnak then
if coordComponent and crtChainSnak.datavalue.value[coordComponent] then return crtChainSnak.datavalue.value[coordComponent] end
return raw and printRawValue(crtChainSnak) or snakToString(crtChainSnak)
end
if crtChainElementId then
if raw then return crtChainElementId
elseif label then return p.findLabel(crtChainElementId)
else return p.findLinkToItem(crtChainElementId) end
end
return nil
end
p.getOneValueInChain = function(frame)
local args = getArgs(frame)
return p.loadOneValueInChain(args)
end
local function isA(entityId, typeIds)
local entityTypes = p.findClaimsForProperty(entityId, 'P31')
entityId = type(entityId) == 'number' and ('Q' .. tostring(entityId)) or entityId
if entityTypes then for _,eachEntityType in ipairs(entityTypes) do
if isClaimTrue(eachEntityType) and hasValueSnak(eachEntityType) then
if TableTools.contains(typeIds, eachEntityType.mainsnak.datavalue.value.id) then
return true
end
local recurseSuccess, recursivelyFoundType = pcall(mw.wikibase.getReferencedEntityId, eachEntityType.mainsnak.datavalue.value.id, 'P279', typeIds)
if recurseSuccess and recursivelyFoundType then
return true
end
if not recurseSuccess then
--manually recurse one level
local superTypeClaims = mw.wikibase.getBestStatements(eachEntityType.mainsnak.datavalue.value.id, 'P279')
if superTypeClaims then for __,eachSuperTypeClaim in ipairs(superTypeClaims) do
if hasValueSnak(eachSuperTypeClaim) and TableTools.contains(typeIds, eachSuperTypeClaim.mainsnak.datavalue.value.id) then
mw.logObject(eachSuperTypeClaim)
return true
end
end end
end
end
end end
return false
end
p.isA = isA
p.findAnniversary = function(propertyId, entityId, step)
local _date = p.findDateValues(propertyId, entityId)
if _date and _date[1] then
-- no year 0
if _date[1].year < 0 then _date[1].year = _date[1].year + 1 end
if (os.date("*t").year - _date[1].year) % step == 0 then
return (os.date("*t").year - _date[1].year)
end
else
return 0
end
end
p.getAnniversary = function(frame)
local args = getArgs(frame)
return p.findAnniversary(args[1], args[2], args[3])
end
p.findLocationChain = function(entity)
local q = entity or mw.wikibase.getEntityIdForCurrentPage()
if not q then return nil end
local countryQId = p.loadOneValueInChain({q, 'P17', 'raw'})
local adminUnitQId = p.loadOneValueInChain({q, 'P131', 'raw'})
if not adminUnitQId or adminUnitQId == countryQId then return p.findLinkToItem(countryQId, true, false, false) end
return p.findLinkToItem(adminUnitQId, true, false, false) .. ', ' .. p.findLocationChain(adminUnitQId)
end
p.getLocationChain = function(frame)
local args = getArgs(frame)
return p.findLocationChain(args.q)
end
p.findAddress = function(qId)
local q = qId or mw.wikibase.getEntityIdForCurrentPage()
if not q then return nil,nil end
p159claims = p.findBestClaimsForProperty(q, 'P159')
addrs = {}
if p159claims then for _,eachP159claim in ipairs(p159claims) do
if hasValueSnak(eachP159claim) then
local addrParts = { p.printSnak(eachP159claim.mainsnak) }
if eachP159claim.qualifiers then
for __,qual in ipairs({'P6375', 'P669', 'P670', 'P281', 'P17'}) do
if eachP159claim.qualifiers[qual] then for ___,eachP159ClaimQual in ipairs(eachP159claim.qualifiers[qual]) do
if isValueSnak(eachP159ClaimQual) then
table.insert(addrParts, p.printSnak(eachP159ClaimQual))
end
end end
end
end
table.insert(addrs, table.concat(addrParts, ', '))
end
end end
if #addrs > 0 then
return table.concat(addrs, tostring(mw.html.create('br'))), 'P159'
end
p6375 = p.findOneValue('P6375', q)
if p6375 then return p6375, 'P6375' end
p669claims = p.findBestClaimsForProperty(q, 'P669')
local addrs = {}
if p669claims then for _,eachP669Claim in ipairs(p669claims) do
if hasValueSnak(eachP669Claim) then
local thisAddr = p.printSnak(eachP669Claim.mainsnak)
if eachP669Claim.qualifiers and eachP669Claim.qualifiers['P670'] then
local streetNumbers = {}
for __,eachP669ClaimP670Qual in ipairs(eachP669Claim.qualifiers['P670']) do
if isValueSnak(eachP669ClaimP670Qual) then
table.insert(streetNumbers, eachP669ClaimP670Qual.datavalue.value)
end
end
if #streetNumbers > 0 then
thisAddr = thisAddr .. ' nr. ' .. table.concat(streetNumbers, ', ')
end
end
table.insert(addrs, thisAddr)
end
end end
if #addrs > 0 then
table.insert(addrs, 1, p.findLocationChain(q))
return table.concat(addrs, '; ')
end
local p2795text = p.loadOneValueInChain({'P2795'})
if p2795text then return p2795text end
return nil
end
p.getAddress = function(frame)
local args = getArgs(frame)
local addr, srcProp = p.findAddress(args[1])
return addr
end
p.hasValueSnak = hasValueSnak
return p