Modulo:Common
La documentazione per questo modulo può essere creata in Modulo:Common/man
--modulo contenente funzioni di utilità generale
local p = {}
local item = mw.wikibase.getEntityObject()
local lang = mw.getContentLanguage()
function p.setItem(newItem)
item = newItem
end
function p.getItem()
return item
end
--ritorna true se l'item che stiamo usando e' quello collegato alla pagina attuale
function p.isOwnItem()
return mw.wikibase.getEntityObject().id == item.id
end
function p.getEntityIdForTitle(frame)
return mw.wikibase.getEntityIdForTitle(frame.args[1])
end
-- *** FUNZIONI DI UTILITA' PER LE TABELLE **
-- numero di elementi in tabella
function p.size(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
-- la tabella è vuota?
function p.empty(T)
return T == nil or next(T) == nil
end
function p.first(T)
if not p.empty(T) then return T[1] end
end
-- la tabella contiene il dato elemento?
function p.contains(T, el)
for key, value in pairs(T) do
if value == el then return true end
end
return false
end
function p.set(list)
local s = {}
for _, l in ipairs(list) do s[l] = true end
return s
end
-- stampa la tabella (per i log)
function p.printTable(T, depth)
depth = depth or 0
local out = ''
for k, v in pairs(T) do
out = out ..'\n' .. string.rep(' ', depth) .. k .. ' = ' .. p.printElement(v, depth)
end
return out
end
-- stampa un elemento qualunque
function p.printElement(el, depth)
depth = depth or 0
if (type(el) == "table") then return '{'..p.printTable(el, depth+1)..'}'
else return tostring(el)
end
end
--copia profonda di una tabella
function p.deepcopy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[p.deepcopy(orig_key)] = p.deepcopy(orig_value)
end
setmetatable(copy, p.deepcopy(getmetatable(orig)))
else -- number, string, boolean, etc
copy = orig
end
return copy
end
--fonde due tabelle in una terza (aggiungendo alle chiavi un diverso prefisso, se specificato)
function p.mergeTables(T1, T2, prefix1, prefix2)
local T = {}
prefix1 = prefix1 or ''
prefix2 = prefix2 or ''
for k, v in pairs(T1) do T[prefix1..k] = v end
for k, v in pairs(T2) do T[prefix2..k] = v end
return T
end
--sottrae dalla T1 gli elementi di T2
function p.subtractTable(T1, T2)
for j, a in pairs(T2 or {}) do
for k, v in pairs(T1) do
if p.equalsIgnoreCase(a, v) then table.remove(T1, k) end
end
end
end
--inverte l'ordine degli elementi nella tabella
function p.reverseTable(t)
local reversedTable = {}
local itemCount = #t
for k, v in ipairs(t) do
reversedTable[itemCount + 1 - k] = v
end
return reversedTable
end
function p.sublist(t, i, j)
local result = {}
for k, v in ipairs(t) do
if k >= i and k <= j then
table.insert(result, v)
end
end
return result
end
-- *** FUNZIONI DI UTILITA' PER LE STRINGHE **
function p.notEmpty(String)
return String and mw.text.trim(String) ~= ''
end
function p.startsWith(String,Start)
return string.sub(String,1, string.len(Start))==Start
end
function p.endsWith(String,End)
return End=='' or string.sub(String, -string.len(End))==End
end
function p.equalsIgnoreCase(str1, str2)
return str1 and str2 and str1:lower() == str2:lower()
end
function p.replace()
frame = mw.getCurrentFrame()
str = frame.args[1]
fnd = frame.args[2]
res = string.gsub(str, fnd:gsub("[%(%)%.%%%+%-%*%?%[%^%$%]]", "%%%1"), "")
return res
end
--concatena la lista di stringhe fornita
function p.concat(list, separator, lastSeparator)
separator = separator or ', '
lastSeparator = lastSeparator or separator
return mw.text.listToText(list or {}, separator, lastSeparator)
end
-- *** FUNZIONI DI UTILITA' PER WIKISOURCE **
-- nome della pagina corrente
function p.getFullName()
return mw.title.getCurrentTitle().text
end
--ritorna il namespace corrente
function p.getNamespace()
return mw.title.getCurrentTitle().nsText
end
--true se siamo nel ns 0
function p.isNS0()
return mw.title.getCurrentTitle().namespace == 0
end
--true se siamo nel ns Autore
function p.isNSAutore()
return p.getNamespace() == 'Autore'
end
--true se siamo in Opera
function p.isNSOpera()
return p.getNamespace() == 'Opera'
end
--true se siamo in una sottopagina
function p.isSubpage()
return mw.title.getCurrentTitle().isSubpage
end
--costruisce una categoria (o un link ad essa se link = true)
function p.category(name, label, link)
label = label and '|'..label or '' --default: stringa vuota
link = (link and ':') or '' --default: stringa vuota
return '[['..link..mw.site.namespaces[14].name..':'..name..label..']]'
end
--costruisce un wikilink
function p.link(name, label, site)
label = label or name
site = site and ':'..site..':' or ''
return '[['..site..name..'|'..label..']]'
end
--splitta un wikilink
function p.splitLink(str)
str = mw.text.trim(str)
if str and p.startsWith(str, '[[') then
local s = mw.text.split(str:gsub('%[%[', ''):gsub('%]%]', ''), '|')
local link = s[1]
local label = link
if p.size(s) > 1 then
label = s[2]
end
return mw.text.trim(link), mw.text.trim(label)
else
return str, str
end
end
--conta il numero di pagine in una data categoria
function p.pagesInCat(cat)
return mw.site.stats.pagesInCategory(cat, 'pages')
end
-- richiama il template richiesto
function p.template(title, args)
--bonifichiamo gli argomenti (se expandTemplate riceve una table, si spacca)
cleanArgs = {}
for i, v in pairs(args or {}) do
if type(v) ~= "table" then cleanArgs[i] = v end
end
return mw.getCurrentFrame():expandTemplate{ title = title, args = cleanArgs }
end
--recupera i parametri passati al template che ha invocato questo modulo
function p.getParameters(frame)
args = {}
for k, v in pairs(frame:getParent().args) do
if v and mw.text.trim(v) ~= '' then
args[k] = mw.text.trim(v)
end
end
return args
end
-- *** FUNZIONI SPECIFICHE PER WIKIDATA **
--ritorna la label per l'item corrente
function p.getLabel()
if item and item.labels and item.labels.it then
return item.labels.it.value
end
end
--ritorna la lista degli alias per l'item corrente
function p.getAliases()
local aliasList = {}
if item and item.aliases and item.aliases.it then
for k, v in pairs(item.aliases.it) do
if v and v.value then table.insert(aliasList, v.value) end
end
end
return aliasList
end
--ritorna la label e tutti gli alias dell'item corrente
function p.getLabelAndAliases()
local aliases = p.getAliases()
if item then
table.insert(aliases, 1, (item:getLabel()))
end
return aliases
end
--ritorna il valore del claim escludendo i valori sconsigliati
function p.getClaimValue(claim)
if claim and claim.mainsnak and claim.mainsnak.datavalue and claim.rank ~= 'deprecated' then
dv = claim.mainsnak.datavalue
v = dv.value
if v then
if dv.type == 'monolingualtext' then
return v.text
else
return v
end
end
end
end
--filtra i claims ritornando solo i "preferred" se ce ne sono, oppure solo i "normal", scartando in ogni caso i "deprecated"
function p.filterClaims(claims)
local preferred = {}
local normal = {}
for index, claim in pairs(claims or {}) do
if claim.rank == 'preferred' then
table.insert(preferred, claim)
elseif claim.rank == 'normal' then
table.insert(normal, claim)
end
end
if p.empty(preferred) then return normal
else return preferred end
end
--ordina i claim per data (ascendente/discendente)
function p.sortClaimsByDate(claims, order)
order = order or 'asc' --asc/desc
sortedClaims = {}
while p.size(claims) > 0 do
firstIndex = 1
for index, claim in pairs(claims or {}) do
thisTime = p.getClaimValue(claim)
firstTime = p.getClaimValue(claims[firstIndex])
if thisTime and thisTime.time and firstTime and firstTime.time then
thisTimeAC = (thisTime.time:sub(1, 1) == '-')
firstTimeAC = (thisTime.time:sub(1, 1) == '-')
if order == 'asc' then
if (not thisTimeAC and not firstTimeAC and thisTime.time < firstTime.time)
or (thisTimeAC and firstTimeAC and thisTime.time > firstTime.time)
or (not thisTimeAC and firstTimeAC) then
firstIndex = index
end
else
if (not thisTimeAC and not firstTimeAC and thisTime.time > firstTime.time)
or (thisTimeAC and firstTimeAC and thisTime.time < firstTime.time)
or (thisTimeAC and not firstTimeAC) then
firstIndex = index
end
end
end
end
table.insert(sortedClaims, claims[firstIndex])
table.remove(claims, firstIndex)
end
return sortedClaims
end
-- ritorna i claim presenti per la property fornita
function p.getClaimsByProperty(property)
if item and item.claims and item.claims[property] and #item.claims[property] >= 1 then
return p.filterClaims(item.claims[property])
end
end
-- ritorna il primo claim trovato per la property fornita
function p.getSingleClaimByProperty(property)
return p.first(p.getClaimsByProperty(property))
end
-- ritorna il valore del primo claim trovato per la property fornita
function p.getSingleClaimValueByProperty(property)
return p.getClaimValue(p.getSingleClaimByProperty(property))
end
--data una property e l'item id di un elemento, ritorna il claim di quella property che ha come valore quell'elemento
function p.getClaimByPropertyAndValue(property, itemId)
claims = p.getClaimsByProperty(property) or {}
for i, claim in pairs(claims) do
if 'Q'..claim.mainsnak.datavalue.value['numeric-id'] == itemId then
return claim
end
end
end
--recupera il valore di un qualificatore da un claim
function p.getQualifierValueFromClaim(claim, qid)
if claim and claim.qualifiers then
qualifiers = claim.qualifiers[qid]
if qualifiers and #qualifiers >= 1 then
return qualifiers[1].datavalue.value
end
end
end
--ritorna l'etichetta di un valore
function p.getLabelFromValue(value)
if value and value["numeric-id"] then return mw.wikibase.label('Q'..value["numeric-id"]) end
end
--ritorna il sitelink di un valore
function p.getLinkFromValue(value, defaultLink)
if value and value['numeric-id'] then return mw.wikibase.sitelink('Q'..value['numeric-id']) or defaultLink end
end
--ritorna la lista dei valori della property fornita
function p.getClaimValuesByProperty(property)
claims = p.getClaimsByProperty(property) or {}
values = {}
for k, claim in pairs(claims) do
value = p.getClaimValue(claim)
if value then table.insert(values, value) end
end
return values
end
--ritorna la lista delle etichette dei valori della property fornita
function p.getLabelsFromPropertyValues(property)
claims = p.getClaimsByProperty(property) or {}
labels = {}
for k, claim in pairs(claims) do
label = p.getLabelFromValue(p.getClaimValue(claim))
if label then table.insert(labels, label) end
end
return labels
end
--dal valore fornito, recupera sitelink e label e crea un link alla pagina
function p.getWikiLinkFromValue(value, defaultLink)
local link = p.getLinkFromValue(value, defaultLink)
local nome = p.getLabelFromValue(value) or link
if link then return p.link(link, nome)
else return nome or '' end
end
--data una lista di item autori, ritorna i link alle loro pagine separati da virgola
function p.getLinksAutori(autori)
autoriLinkList = {}
for k, autore in pairs(autori) do
autoreNome = p.getLabelFromValue(autore)
if autoreNome ~= nil and autoreNome ~= 'autore anonimo' then
autoreNome = lang:ucfirst(autoreNome)
else
autoreNome = "Anonimo"
end
autoreLink = p.getLinkFromValue(autore, 'Autore:'..autoreNome)
table.insert(autoriLinkList, p.link(autoreLink, autoreNome))
end
return p.concat(autoriLinkList, ', ')
end
--data una lista di item opere di cui altre opere sono parte, ritorna i link alle loro pagine separati da virgola
function p.getLinksParteOpere(ParteOpere)
ParteOpereLinkList = {}
for k, ParteOpera in pairs(ParteOpere) do
ParteOperaNome = p.getLabelFromValue(ParteOpera)
ParteOperaLink = p.getLinkFromValue(ParteOpera, 'Opera:'..ParteOperaNome)
table.insert(ParteOpereLinkList, p.link(ParteOperaLink, ParteOperaNome))
end
return p.concat(ParteOpereLinkList, ', ')
end
--data una lista di item, ritorna i link alle loro pagine separati da virgola
function p.getLinks(items, defaultNS, separator)
local list = {}
defaultNS = (defaultNS and (defaultNS .. ':')) or ''
for k, v in pairs(items) do
local label = p.getLabelFromValue(v)
local link = p.getLinkFromValue(v, defaultNS..label)
table.insert(list, p.link(link, label))
end
return p.concat(list, separator)
end
--data una lista di item autori, ritorna l'elenco dei loro nomi
function p.getListaAutori(autori)
autoriList = {}
for k, autore in pairs(autori) do
autoreNome = p.getLabelFromValue(autore)
if autoreNome ~= nil and autoreNome ~= 'autore anonimo' then
autoreNome = lang:ucfirst(autoreNome)
else
autoreNome = "Anonimo"
end
table.insert(autoriList, autoreNome)
end
return autoriList
end
--data una lista di item, ritorna la lista delle loro etichette
function p.getLabelsList(items)
local list = {}
for k, v in pairs(items) do
table.insert(list, p.getLabelFromValue(v))
end
return list
end
--true se questo elemento è un'istanza di arg
function p.instanceof(arg)
claims = p.getClaimsByProperty('P31') or {}
for index, claim in pairs(claims) do
local val = p.getClaimValue(claim)
if val and val['numeric-id'] and arg == val['numeric-id'] then
return true
end
end
return false
end
-- Restituisce il collegamento corrispondente al codice fornito
function p.sitelink(dbname)
if item then
return item:getSitelink(dbname)
end
end
-- collegamento a Wikipedia in italiano (o nelle lingue di fallback)
function p.wikipedia()
local linkLang = nil
local fallbackChain = {
{'it', 'itwiki'},
{'en', 'enwiki'},
{'fr', 'frwiki'},
{'de', 'dewiki'},
{'es', 'eswiki'},
{'pt', 'ptwiki'},
{'ru', 'ruwiki'},
{'el', 'elwiki'},
{'nl', 'nlwiki'},
{'rm', 'rmwiki'},
{'ca', 'cawiki'},
{'eml', 'emlwiki'},
{'fur', 'furwiki'},
{'lij', 'lijwiki'},
{'lld', 'lldwiki'},
{'lmo', 'lmowiki'},
{'nap', 'napwiki'},
{'pms', 'pmswiki'},
{'roa-tara', 'roa_tarawiki'},
{'sc', 'scwiki'},
{'scn', 'scnwiki'},
{'vec', 'vecwiki'}
}
for _, site in pairs(fallbackChain) do
local sitelink = p.sitelink(site[2])
if sitelink then
return site[1], sitelink
end
end
end
-- collegamento a Wikiquote in italiano
function p.wikiquote()
return p.sitelink('itwikiquote')
end
-- collegamento a Wikibooks
function p.wikibooks()
return p.sitelink('itwikibooks')
end
-- collegamento a Wikinotizie
function p.wikinews()
return p.sitelink('itwikinews')
end
-- collegamento a Wikizionario
function p.wiktionary()
return p.sitelink('itwiktionary')
end
-- collegamento a Wikiversità
function p.wikiversity()
return p.sitelink('itwikiversity')
end
-- collegamento a Wikivoyage
function p.wikivoyage()
return p.sitelink('itwikivoyage')
end
-- collegamento a Wikispecies
function p.wikispecies()
return p.sitelink('specieswiki')
end
-- collegamento a Commons (per gallerie)
function p.commons()
return p.sitelink('commonswiki')
end
-- collegamento a Commons (categorie)
function p.commonscat()
return p.getSingleClaimValueByProperty('P373')
end
-- *** FUNZIONI VARIE **
--converte il numero dato a numero romano
function p.toRoman(num)
local t = {
{1000, "M"},
{900, "CM"}, {500, "D"}, {400, "CD"}, {100, "C"},
{90, "XC"}, {50, "L"}, {40, "XL"}, {10, "X"},
{9, "IX"}, {5, "V"}, {4, "IV"}, {1, "I"}
}
local ret = {}
for _, v in ipairs(t) do
local val, letter = unpack(v)
while num >= val do
num = num - val
table.insert(ret, letter)
end
end
return table.concat(ret), num
end
--fa il parsing di una data per ottenere le sue componenti
--formati di input possibili:
--1° gennaio 2017
--25 dicembre 96 a.C.
--1877/1878
--format: anno, secolo, giornoMese
function p.parseDate(frame)
date = frame.args[1]
retFormat = frame.args[2]
num = frame.args[3]
return p.parseDateInternal(date, retFormat, num)
end
function p.parseDateInternal(date, retFormat, num)
date = date:gsub(" %- ", "/"):gsub("%-", "/")
if num then
index = 1
for part in date:gmatch("[^/]+") do
if index == tonumber(num) then
return p.parseDateInternal(part, retFormat)
end
index = index + 1
end
end
day, month, year = date:match("([%d]+.*) (%w+) (%d+.*)")
if not day then
year = date:match("(%d+.*)")
end
if year then
yearDigits, yearBC = year:match("(%d+)(.*)")
century = p.toRoman(math.ceil(yearDigits / 100)) .. ' secolo' .. yearBC
if retFormat == 'anno' then
return year
elseif retFormat == 'secolo' then
return century
elseif retFormat == 'giornoMese' and day and month then
return day .. ' ' .. month
end
end
return date
end
--per stripAccents()
local tableAccents = {}
tableAccents["à"] = "a"
tableAccents["á"] = "a"
tableAccents["â"] = "a"
tableAccents["ã"] = "a"
tableAccents["ä"] = "a"
tableAccents["ç"] = "c"
tableAccents["è"] = "e"
tableAccents["é"] = "e"
tableAccents["ê"] = "e"
tableAccents["ë"] = "e"
tableAccents["ì"] = "i"
tableAccents["í"] = "i"
tableAccents["î"] = "i"
tableAccents["ï"] = "i"
tableAccents["ñ"] = "n"
tableAccents["ò"] = "o"
tableAccents["ó"] = "o"
tableAccents["ô"] = "o"
tableAccents["õ"] = "o"
tableAccents["ö"] = "o"
tableAccents["ø"] = "o"
tableAccents["ù"] = "u"
tableAccents["ú"] = "u"
tableAccents["û"] = "u"
tableAccents["ü"] = "u"
tableAccents["ý"] = "y"
tableAccents["ÿ"] = "y"
tableAccents["À"] = "A"
tableAccents["Á"] = "A"
tableAccents["Â"] = "A"
tableAccents["Ã"] = "A"
tableAccents["Ä"] = "A"
tableAccents["Č"] = "C"
tableAccents["Ç"] = "C"
tableAccents["Ć"] = "C"
tableAccents["È"] = "E"
tableAccents["É"] = "E"
tableAccents["Ê"] = "E"
tableAccents["Ë"] = "E"
tableAccents["Ì"] = "I"
tableAccents["Í"] = "I"
tableAccents["Î"] = "I"
tableAccents["Ï"] = "I"
tableAccents["Ñ"] = "N"
tableAccents["Ò"] = "O"
tableAccents["Ó"] = "O"
tableAccents["Ô"] = "O"
tableAccents["Õ"] = "O"
tableAccents["Ö"] = "O"
tableAccents["Ø"] = "O"
tableAccents["Ś"] = "S"
tableAccents["Ù"] = "U"
tableAccents["Ú"] = "U"
tableAccents["Û"] = "U"
tableAccents["Ü"] = "U"
tableAccents["Ý"] = "Y"
-- Strip accents from a string
function p.stripAccents(str)
local normalizedString = ""
for strChar in string.gfind(str, "([%z\1-\127\194-\244][\128-\191]*)") do
normalizedString = normalizedString .. (tableAccents[strChar] or strChar)
end
return normalizedString
end
--dato il PID di una proprietà Wikidata, mostra un link ad essa e l'etichetta associata
function p.propertyDetails(frame)
pid = frame:getParent().args[1]
item = mw.wikibase.getEntity(pid)
label = ''
if item and item.labels and item.labels.it then
label = ' ("'..item.labels.it.value..'")'
end
return '[[:d:Property:'..pid..'|'..pid..']]'..label
end
-- rimuovi eventuali parentesi dal titolo
function p.stripTitolo2(titolo)
titolo = titolo:gsub(".*/", ""):gsub("_", " ")
-- mantieni la parentesi se seguita da una lettera minuscola
:gsub("%((%l)", "_%1")
:gsub(" %(.*%)", "")
:gsub("_", "(")
return titolo
end
function p.stripTitolo(frame)
return p.stripTitolo2(frame:getParent().args[1])
end
return p