Modul:Wikidata
Aceasta este pagina de documentație pentru Modul:Wikidata. Pagina descrie modul de folosire al formatului și conține categoriile de care acesta aparține, precum și orice altceva ce nu face parte din formatul propriu-zis. Ea poate fi editată modificând pagina Modul:Wikidata/doc |
Acest modul folosește pentru accesarea datelor din structurile de la Wikidata. Desigur, există {{#property:}} cu care se poate accesa o proprietate a itemului curent, dar de cele mai multe ori este nevoie de acțiuni mai complexe.
Convenții
Funcțiile al căror nume începe cu get sunt dedicate formatelor și paginilor, și primesc ca argument un frame (care se transmite automat la apelul din pagini sau formate). Cele al căror nume începe cu find sunt dedicate celorlalte module, și primesc ca argumente direct valorile necesare. De regulă, cele din urmă doar extrag argumentele, apoi le apelează pe cele dintâi cu argumentele extrase.
Modificatori de formatare
Anumite funcții apelate din formate permit următorii parametri ce modifică formatarea rezultatelor:
- ill: înlocuiește formatarea legăturilor către Wikidata folosită în infocasete cu folosirea formatului {{ill-wd}}.
- si: convertește „snak”-urile de tip cantitate la o unitate a Sistemului Internațional echivalentă.
Toți acești parametri pot avea orice valoare.
Funcții exportate
Funcție | Argumente | Comportament | |
---|---|---|---|
descriptionIn |
frame cuprinzând ca argumente:
|
Extrage descrierea unui item într-o limbă. Limba este specificată de primul argument și poate lipsi, caz în care se folosește limba wikiului; id-ul itemului poate lipsi, caz în care se folosește itemul asociat paginii curente. | |
labelIn |
frame cuprinzând ca argumente:
|
Extrage eticheta unui item într-o limbă. Limba este specificată de primul argument și poate lipsi, caz în care se folosește limba wikiului; id-ul itemului poate lipsi, caz în care se folosește itemul asociat paginii curente. | |
getEntityId | Extrage id-ul entității curente. | ||
findLinkToItem |
|
Creează un link către articolul despre o altă entitate decât cea în pagina în care ne aflăm. Se poate cere scrierea etichetei linkului cu inițială majusculă (dacă regulile gramaticale o impun — cazul în care linkul se pune la începutul unui titlu sau al unei fraze); în forma de feminin (de exemplu, pentru meserii, dacă ele sunt referite ca practicate de o femeie); sau cu cea mai scurtă variantă posibilă (dacă se dorește o abreviere). Oricare din ultimele trei flaguri poate lipsi, caz în care ele sunt considerate a avea valoarea false. | |
findLinkToItemWithLabelFromClaim |
|
Ca și findLinkToItem, doar că generalizează modul de obținere a etichetei: se poate preciza o proprietate a entității de la care se va obține eticheta | |
findLinkToItemWithLabelFromAnyClaim |
|
Ca și findLinkToItemWithLabelFromClaim, doar că generalizează și mai mult modul de obținere a etichetei: se poate preciza o listă de proprietăți ale entității care sunt verificate pe rând până se găsește una care are o valoare | |
printSnak |
|
Afișează un „snak” (element polimorf din structura de date de la Wikidata). Este utilă atunci când într-un modul se procesează date preluate în mod direct din structurile de date de la Wikidata. Acest snak poate fi o dată calendaristică, id-ul unui alt item Wikidata, un șir de caractere etc. Funcția ia decizia a ce afișează în funcție de tipul snakului. | |
outputReferences | Creează note de subsol conținând referințele bibliografice asociate unei afirmații. Notele de subsol sunt evitate dacă referința este către un alt proiect Wikipedia. Numele refului se calculează automat pentru a putea fi reutilizat de la o instanță la alta. | ||
getValueList |
|
Întoarce un table format din toate valorile cu rang de la normal în sus pentru proprietatea și entitatea specificată. | |
getValueListLimited |
|
Întoarce un table cu cel mult limitVal elemente format din valori cu rang de la normal în sus pentru proprietatea și entitatea specificată și un int ce reprezintă numărul total de valori ce ar fi fost întoarse dacă nu exista limitVal | |
printTimestampForClaim | Întoarce, între paranteze, datele temporale asociate afirmației:
| ||
getTimestampedValueList |
|
Întoarce un table format din valorile pe care le-ar returna funcția getValueList, fiecare urmată de valoarea pe care ar returna-o, pentru fiecare, funcția printTimestampForClaim apelată cu claimul asociat fiecăreia. | |
findValueListWithQualifiersInBrackets |
|
Întoarce un table format din valorile pe care le-ar returna funcția getValueList, fiecare urmată de o paranteză conținând calificativele sale de la Wikidata formatate după template-ul specificat ca al patrulea parametru. | |
getValueListWithSeparator |
|
Returnează o listă ale cărei elemente sunt separate prin separatorul specificat, elementele fiind valorile pe care le-ar returna funcția getValueList apelată cu id-urile de proprietate și entitate specificate. | |
_getValueListWithSeparator | Ca și getValueListWithSeparator, doar că primește direct table-ul de argumente, nu frame-ul | Ca și getValueListWithSeparator. | |
getTimestampedValueListWithSeparator | Un frame, având pe prima poziție separatorul, pe a doua id-ul de proprietate și pe a treia id-ul de entitate | Returnează o listă ale cărei elemente sunt separate prin separatorul specificat, elementele fiind valorile pe care le-ar returna funcția getTimestampedValueList apelată cu id-urile de proprietate și entitate specificate. | |
_getTimestampedValueListWithSeparator | Ca și getTimestampedValueListWithSeparator, doar că primește direct table-ul de argumente, nu frame-ul | Ca și getTimestampedValueListWithSeparator. | |
getEntityIdsList |
|
Întoarce un table conținând id-urile de entitate, cu rank cel puțin normal, către care trimite proprietatea specificată a entității specificate. | |
getBestEntityIdsList |
|
Întoarce un table conținând id-urile de entitate, cu rank cel mai mare, către care trimite proprietatea specificată a entității specificate. | |
findClaimsForProperty |
|
Întoarce un table conținând claimurile pure ce reprezintă afirmațiile asociate proprietății specificate a entității specificate. | |
findBestClaimsForProperty |
|
Întoarce un table conținând claimurile pure ce reprezintă afirmațiile cu cel mai bun rang, asociate proprietății specificate a entității specificate. | |
findSortedClaimsForProperty |
|
Întoarce un table conținând claimurile pure ce reprezintă afirmațiile asociate proprietății specificate a entității specificate, sortate în funcție de calificatorul start time (P580) asociat lor. | |
findQualifierValueListForClaim |
|
Întoarce un table conținând reprezentarea valorilor asociate calificatorului specificat pentru claimul specificat. | |
getQualifierValue | Un frame conținând în tabelul args, în ordine, id-ul proprietății și id-ul calificatorului | Întoarce reprezentarea tuturor calificatorilor cu id-ul specificat pentru proprietatea cu id-ul specificat a entității curente. Calificatoarele sunt separate prin virgulă și spațiu. | |
getRawValue | Un frame având pe prima poziție a tabelului args valoare id-ului proprietății. | Întoarce reprezentarea dată de funcția formatPropertyValues a entitătii curente, apelată cu id-ul de proprietate specificat. | |
getRawQualifierValue | Un frame având pe prima poziție a tabelului args valoare id-ului proprietății și pe a doua id-ul unui calificator. | Întoarce reprezentarea simplă a valorii (dacă valoarea este id-ul unui alt element, aceasta este labelul acelui element) tuturor calificatoarelor cu id-ul specificat ale id-ului proprietății cu id-ul specificat a entității curente. Reprezentările sunt separate prin virgulă. | |
findDateValues |
|
Întoarce un table ale cărui elemente sunt la rândul lor table-uri reprezentând datele cu rangul cel mai bun asociate proprietății cu id-ul specificat al entității cu id-ul specificat. Proprietățile fiecărui element din table-ul ce reprezintă data sunt:
| |
getDateValue | Un frame conținând în tabelul args pe prima poziție id-ul de proprietate, pe a doua id-ul de entitate (nil înseamnă entitatea curentă), pe a treia un format de dată (implicit dmy) și pe a patra un sufix pentru datele dinaintea erei noastre | Întoarce o listă a datelor cu rang cel puțin normal asociate id-ului de proprietate și id-ului de entitate specificate, formatate după cum specifică formatul de dată și sufixul, separate prin virgulă și spațiu. | |
pageId | Întoarce id-ul din Wikidata al elementului asociat paginii curente | ||
getPreferredValue | Un frame conținând în tabelul args pe prima poziție id-ul de proprietate și pe a doua id-ul de entitate (nil înseamnă entitatea curentă) | Întoarce, separate prin virgulă, valorile cu rang preferred pentru entitatea și proprietatea specificate. | |
ViewSomething | Un frame conținând în tabelul args o serie de elemente care împreună constituie o cale de urmat prin modelul de date de la Wikidata | Întoarce data existentă pe calea specificată. | |
Dump | Un frame conținând în tabelul args o serie de elemente care împreună constituie o cale de urmat prin modelul de date de la Wikidata | Întoarce datele existente pe calea specificată; dacă datele sunt un tabel, el se expandează și se afișează toate datele din el. Funcția este de folosit pentru debug și pentru analiză | |
findOneValue |
|
Returnează o singură valoare din cele cu rangul cel mai înalt cu referințele corespunzătoare pentru o proprietate specificată, împreună cu note de subsol care reprezintă referințele bibliografice. Se apelează din alte module. | |
findOneValueNoRef |
|
Același lucru ca findOneValue, dar fără referințe bibliografice. | |
getOneValue |
|
Returnează o singură valoare din cele cu rangul cel mai înalt cu referințele corespunzătoare pentru o proprietate specificată, împreună cu note de subsol care reprezintă referințele bibliografice. | |
getOneValueNoRef | Un frame conținând în tabelul args pe prima poziție id-ul de proprietate și pe a doua id-ul de entitate (nil înseamnă entitatea curentă) | Același lucru ca getOneValue, dar fără referințe bibliografice. | |
getLatestQualifierDateValueForOneProperty | Un frame conținând în tabelul args pe prima poziție id-ul de proprietate și pe a doua id-ul qualifierului | Returnează valoarea cea mai recentă a qualifierului specificat pentru proprietea specificată a entității curente | |
findLatestQualifierDateValueForOneProperty |
|
Același lucru ca și getLatestQualifierDateValueForOneProperty, doar că de apelat din alte module | |
getReferenceForOneProperty | Un frame conținând în tabelul args pe prima poziție id-ul proprietății | Returnează un text ce conține referința pentru o proprietate a entității curente; de apelat din formate | |
findLabel |
|
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ă | |
getLabel | Un frame conținând în tabelul args pe prima poziție id-ul de entitate (nil înseamnă entitatea curentă) și pe a doua codul limbii | Ca și findLabel, dar apelabil din formate sau pagini | |
findBestValues |
|
Returnează o listă a valorilor cu rangul cel mai înalt cu referințele corespunzătoare pentru o proprietate specificată. Apelabil din module. | |
getBestValuesWithSeparator | Un frame conținând în tabelul args pe prima poziție un separator, pe a doua id-ul proprietății și pe a treia id-ul de entitate (nil înseamnă entitatea curentă). | Returnează valorile cu rangul cel mai înalt și cu referințele corespunzătoare pentru o proprietate specificată, despărțite prin separatorul specificat | |
findLanguageText |
|
Întoarce labelul unei entități asociate proprietății specificate a entității specificate, în limba specificată; dacă nu se specifică entityId, se folosește entitatea curentă; dacă nu se specifică langcode, se caută întâi în limba wikiului și apoi în limba engleză | |
getLanguageText | Un frame conținând în tabelul args pe prima poziție id-ul de proprietate, pe a doua codul limbii și pe a treia id-ul de entitate | Același lucru ca și findLanguageText, doar că apelabilă din formate și pagini | |
findClaimForTimestamp |
|
Claimul din entitatea specificată, corespunzător proprietății specificate, cu valori ale calificatorilor pentru proprietățile start time și end time care cuprind între ele data specificată de timestamp. Dacă timestamp lipsește, se returnează primul claim întâlnit cu rangul cel mai mare. | |
findOnlineLinks |
|
Un table ce conține legăturile web formatate cu tot cu titlu, pentru entitatea specificată | |
getOnlineLinks | Un frame ce conține pe pozițiile numerice valorile proprietăților de căutat, iar pe poziția qid ID-ul entității asociate; dacă nu este precizat, se consideră entitatea asociată paginii curente | Ca și findOnlineLinks, doar că lista este concatenată cu fiecare link pe câte o linie. | |
findTitleOfWork | entityId - id-ul entității | Titlul unei opere așa cum ar trebui afișat aici. Se caută, în ordine: eticheta în română, titlul în română, titlul în limba originară, eticheta în limba originară, eticheta în engleză | |
findTitlesOfWorksFromProperty |
|
Caută cu ajutorul funcției findTitleOfWork de mai sus titlurile unor opere listate în proprietatea specificată a entității specificate și le returnează ca intrări într-un table; titlurile sunt linkuri trimit spre articolul sau itemul wikidata corespunzător operei; | |
findBestValuesForLocalLanguage |
|
Returnează o listă a valorilor de cel mai mare rang asociate limbii române prin intermediul unui calificator cu proprietatea limba operei sau a denumirii (P407). | |
getBestValuesForLocalLanguageWithSeparator |
|
ca mai sus, doar că apelabilă din format; primește mai întâi un separator și apoi id-urile | |
getTitleOfWorkFromPropertyWithSeparator | Un frame ce conține următoarele argumente:
|
Ca și findTitlesOfWorksFromProperty, dar primește frame, returnează lista serializată cu separatori și cu titlurile italicizate | |
loadOneValueInChain | Un număr teoretic nelimitat de argumente înlănțuite care descriu o cale prin structurile Wikidata. Implicit, punctul de început este elementul Wikidata asociat paginii curente. Dacă un argument este un ID de element Wikidata, atunci acela este stabilit ca punct de început. Dacă este un ID de proprietate, atunci se trece la valoarea proprietății respective pentru elementul curent. Dacă este un ID de proprietate precedat de _ atunci se trece la calificatorul asociat proprietății respective asociate snakului curent. În cele două cazuri din urmă se folosește la fiecare pas doar un singur snak, de rangul cel mai mare. Vezi și {{Date înlănțuite de la Wikidata}}. | Forma textuală a snakului final de pe lanț; nil dacă nu există date sau lanțul nu poate fi parcurs până la destinație | |
getOneValueInChain | Ca și mai sus, doar că apelabil cu un frame | Ca și mai sus | |
isA |
|
true dacă entitatea cu id-ul entityId are unul din tipurile cu ID-ul din colecția typeIds sau unul din subtipurile directe sau indirecte ale acestuia; false altfel | |
formatExternalLink | Formatează o proprietate a cărei valoare este un link extern |
|
|
getFormattedExternalLink | Ca și mai sus, apelabilă cu un frame | Ca și mai sus, apelabilă cu un frame; pId poate fi dat ca primul parametru fără nume; qId poate fi dat ca al doilea parametru fără nume | |
findAnniversary |
|
Întoarce numărul de ani trecuți de la evenimentul descris în proprietate dacă acesta este multiplu de step, 0 altfel | |
getAnniversary | Ca și mai sus, doar că apelabil cu un frame | Ca și mai sus | |
getLocationChain |
|
Întoarce o listă de locații în care se află entitatea curentă |
local getArgs = require('Module:Arguments').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')
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)
labelLang = eachLang
end
if label then break end
end
if label then
if labelLang and labelLang ~= 'ro' 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 invisibleLinkTrail(label, description, out)
if mw.isSubsting() then return "" end
return mw.getCurrentFrame():preprocess("{{invizibil|1=[[" .. label .." " .. description .. "|​]]}}") .. out
end
local function computeWikidataLinkText(qIfiedEntityId, label, description, out)
return "[[:d:" .. qIfiedEntityId .. "|" .. label .. "]]<abbr title='Articolul încă nu există în acest wiki'>[*]</abbr>" .. invisibleLinkTrail(label, description, out)
end
local function computeWikidataLinkWithIll(qIfiedEntityId, label, description, out)
return mw.getCurrentFrame():preprocess("{{ill-wd|" .. qIfiedEntityId .. "||3=" .. label .. "}}") .. invisibleLinkTrail(label, description, out)
end
-- Handle unit snaks by possibly converting to SI
-- return multiplier, unitQ
local function computeUnitInfo(unit)
return 1, mw.ustring.match(unit, 'Q%d+')
end
-- return the SI conversion and unit corresponding to the unit
local function computeSIUnitInfo(unit)
local unitQ = mw.ustring.match(unit, 'Q%d+')
if unitQ ~= nil then
claims = mw.wikibase.getBestStatements(unitQ, 'P2370')
if claims and 0 < #claims then
for _,eachClaim in ipairs(claims) do
if hasValueSnak(eachClaim) and eachClaim.mainsnak.datavalue.type == "quantity" and mw.ustring.match(eachClaim.mainsnak.datavalue.value.unit, 'Q%d+') ~= nil then
return eachClaim.mainsnak.datavalue.value.amount, mw.ustring.match(eachClaim.mainsnak.datavalue.value.unit, 'Q%d+')
end
end
end
end
return 1, unitQ
end
local function parseTopLevelArgs(args)
if args['ill'] ~= nil then computeWikidataLinkText = computeWikidataLinkWithIll end
if args['si'] ~= nil then computeUnitInfo = computeSIUnitInfo 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 = "[[Categorie:Articole cu legături către elemente fără etichetă]]"
elseif labelLang ~= 'ro' then
out = "[[Categorie:Articole cu legături către elemente fără etichetă în limba română]]"
end
description = description or ""
if sitelink then
return "[[:" .. sitelink .. "|" .. label .. "]]" .. out
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 computeWikidataLinkText(qIfiedEntityId, label, description, out)
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 = { ["ro"] = 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 == 'ro' and hasBetterRank(shortNameClaim, bestRanks["ro"]) then
returnedAlias = shortNameClaim.mainsnak.datavalue.value.text
bestRanks["ro"] = shortNameClaim.rank
end
end
if returnedAlias then
returnedLang = 'ro'
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 == 'ro' 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
-- 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
local function formatDate(indate, precision, timezone)
precision = precision or 11
local 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 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 multiplier, unitQ = computeUnitInfo(snak.datavalue.value.unit)
if unitQ ~= nil then
-- possible conversion
amount = amount * multiplier
-- rounding
-- local iamount = math.floor(amount)
-- if math.abs(amount - iamount) < 0.5 then amount = iamount else amount = iamount + 1 end
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.getReferences = function(claim)
local refMapping = {}
local authorityPropertiesMap = {}
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"
refMapping["P291"] = "location"
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 refs = {}
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)
refs[tostring(citationHash)] = citationArguments
end
end
end
return refs
end
p.printReference = function(citationHash, citationArguments)
local frame = mw.getCurrentFrame()
local out = ""
if wdReferences[citationHash] then
out = out .. frame:extensionTag{name="ref", args={name = citationHash}}
else
local refText = ""
local tstyle = ""
-- when substituting, use the wikitext template
if mw.isSubsting() then
refText = Citation.citationTemplateFromArgs(citationArguments)
citationHash = citationHash .. '-subst'
else
refText, tstyle = Citation.citationFromArgs(citationArguments, {CitationClass = 'citation'}, false)
end
out = out .. frame:extensionTag("ref", refText, { name = citationHash }) .. tstyle
wdReferences[citationHash] = true
end
return out
end
p.printFirstReferences = function(refs, limit)
local referencesCount = 0
local out = ""
for hash,cargs in pairs(refs) do
out = out .. p.printReference(hash, cargs)
referencesCount = referencesCount + 1
if referencesCount > limit then break end
end
return out
end
p.outputReferences = function (claim)
local refs = p.getReferences(claim)
return p.printFirstReferences(refs, 4)
end
p.getValueListLimited = function(entityId, propertyId, limitVal, best)
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 = best and mw.wikibase.getBestStatements(entityId, propertyId) or 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) and hasRankAtLeastNormal(v) then
count = count+1
if count <= 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 = ''
local crtProp = nil
if tbl then
if tbl['P585'] then
crtEntry = crtEntry .. snakToString(tbl['P585'][1].mainsnak or tbl['P585'][1])
crtProp = 'P585'
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
crtProp = 'P582'
else
crtEntry = crtEntry .. 'din ' .. snakToString(tbl['P580'][1].mainsnak or tbl['P580'][1])
crtProp = 'P580'
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
crtProp = 'P582'
end
end
return crtEntry, crtProp
end
p.printTimestampForClaim = function(claim)
if claim and claim.qualifiers then
local tblTimestamp = findTimestampInTable(claim.qualifiers)
return tostring(mw.html.create('small'):wikitext(' (' .. tblTimestamp .. ')'))
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
local tblTstamp, tblProp = findTimestampInTable(tbl)
return tblTstamp, tblProp
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, {wrappers = {'Format:Listă decorată de la Wikidata'}, frameOnly = false, parentOnly = false})
local entityId = args['q'] or mw.wikibase.getEntityIdForCurrentPage()
local propertyId = args['p']
local best = (args['best'] ~= nil)
local bracketTemplates = nil
local limitVal = args['limit'] and tonumber(args['limit']) or -1
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, rezCount = p.findValueListWithDecoratedQualifiers(entityId, propertyId, best, bracketTemplates, seps, pictureProp, pictureSize, limitVal)
if 0 < limitVal and rezCount > limitVal + 1 then
local hiddenVals = rezCount - limitVal
extraSpec = '[[:d:' .. entityId .. '#' .. propertyId .. "|...''încă " .. tostring(hiddenVals) .. "'']]"
table.insert(rezList, extraSpec)
end
return table.concat(rezList or {}, tostring(mw.html.create('br')))
end
p.getValueListWithQualifiersInBrackets = p.getValueListWithDecoratedQualifiers
p.findValueListWithDecoratedQualifiers = function(entityId, propertyId, best, bracketTemplates, seps, pictureProp, pictureSize, limit)
entityId = entityId or mw.wikibase.getEntityIdForCurrentPage()
if not limit or type(limit) ~= 'number' then limit = -1 end
if (type(bracketTemplates) == 'string') then
bracketTemplates = { bracketTemplates }
elseif not bracketTemplates then
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 = {}
local allcount = 0
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
allcount = #rawclaims
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
if mw.ustring.len(bracketText) > 0 then
crtEntry = StringUtils._appendToString({crtEntry, tostring(mw.html.create('small'):wikitext(StringUtils._encloseString({bracketText, ' (', ')'})))})
end
end
crtEntry = crtEntry .. p.outputReferences(v)
if 0 < limit and limit <= #rez then
break
end
table.insert(rez, crtEntry)
end
end
return rez, allcount
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(...)
if arg.n == 0 then return nil end
local funcArgs = type(arg[1]) == 'table' and arg[1] or arg
local separator = ", "
if funcArgs[1] ~= nil then separator = mw.text.trim(funcArgs[1]) end
local conjunction = separator
if funcArgs['conj'] ~= nil then conjunction = ' ' .. mw.text.trim(funcArgs['conj']) .. ' ' end
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 best = funcArgs[5] or funcArgs['best']
if not best or best == 'false' or best == 'no' then best = false else best = true end
local limitVal = 0
if limit and (limit == mw.ustring.match(limit, '%d+') or type(limit) == 'number') then
limitVal = tonumber(limit)
end
local values, vcount = p.getValueListLimited(entityId, propertyId, limitVal, best)
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 > 0 and mw.text.listToText(values, separator, conjunction) or nil
end
p.getValueListWithSeparator = function(frame)
local funcArgs = getArgs(frame, {frameOnly = true})
parseTopLevelArgs(funcArgs)
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
local trueClaims = {}
for _,claim in ipairs(claims) do
if hasRankAtLeastNormal(claim) then table.insert(trueClaims, claim) end
end
return extractWikidataIdsFromClaimList(trueClaims)
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])
elseif q1['P585'] and q1['P585'][1] and q1['P585'][1].datavalue then
d1 = p.extractDateFromClaim(q1['P585'][1])
end
if q2['P580'] and q2['P580'][1] and q2['P580'][1].datavalue then
d2 = p.extractDateFromClaim(q2['P580'][1])
elseif q2['P585'] and q2['P585'][1] and q2['P585'][1].datavalue then
d2 = p.extractDateFromClaim(q2['P585'][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 entityID = mw.wikibase.getEntityIdForCurrentPage()
if entityID then
local claims = mw.wikibase.getBestStatements(entityID, propertyID)
local out = {}
if claims and #claims > 0 then
for k, v in pairs(claims) do
if p.isValueSnak(v.mainsnak) then
if v.qualifiers and v.qualifiers[qualifierID] then
for k2, v2 in pairs(v.qualifiers[qualifierID]) do
if p.isValueSnak(v2) then
table.insert(out, snakToString(v2))
end
end
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
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
local 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
local 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
local 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
local 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
p.claim = function(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
p.ViewSomething = function(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
p.Dump = function(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
p.findOneValue = function(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
p.findOneValueNoRef = function(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)
parseTopLevelArgs(args)
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
local function formatCoordinates(entityId, args)
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' and
coordClaims[coordIdx].mainsnak.datavalue ~= nil 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 coordArgs = {tostring(math.abs(coordClaims[coordIdx].mainsnak.datavalue.value.latitude)), latDir, tostring(math.abs(coordClaims[coordIdx].mainsnak.datavalue.value.longitude)), lonDir}
if args['display'] ~= nul then coordArgs['display'] = args['display'] end
if args['format'] ~= nul then coordArgs['format'] = args['format'] end
local coordsText = mw.getCurrentFrame():expandTemplate{title='Coord', args=coordArgs}
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'], origArgs)
end
-- Returnează o numărul de valori cu cel mai mare rang pentru o proprietate specificată
-- De apelat din alte module
p.countBestValues = function(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
p.getBestValuesCount = function(frame)
local origArgs = getArgs(frame)
local entity = mw.wikibase.getEntityObject()
return p.countBestValues(origArgs[1], entity)
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
p.findBestValues = function(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
p.findLanguageText = function(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
p.getLanguageText = function(frame)
return p.findLanguageText(frame.args[1], frame.args[2] or 'ro', frame.args[3]) or ''
end
p.findBestValuesForLocalLanguage = function(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'] or {}) 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
p.getBestValuesForLocalLanguageWithSeparator = function(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, props)
local wikidataImages = nil
props = props or {'P2716', 'P18', 'P10'}
-- order is important, we will only retrieve one property
for _,prop in ipairs(props) do
wikidataImages = p.findBestClaimsForProperty(entityId, prop)
-- stop on the first match
if wikidataImages and #wikidataImages > 0 then break end
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', 'P11245'}
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(...)
local chain = arg.n == 0 and {} or type(arg[1]) == 'table' and arg[1] or arg
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+') ~= nil then
local pid = mw.ustring.match(eachChainRing, 'P%d+')
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 = nil
-- get latest property
if mw.ustring.match(eachChainRing, '@P%d+') == eachChainRing then
propertyClaims = p.findSortedClaimsForProperty(crtChainElementId, pid)
-- get one random property
elseif mw.ustring.match(eachChainRing, 'P%d+') == eachChainRing then
propertyClaims = mw.wikibase.getBestStatements(crtChainElementId, eachChainRing)
else
return nil;
end
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)
parseTopLevelArgs(args)
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
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)
parseTopLevelArgs(args)
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