Aller au contenu

Module:Wikidata/sandbox

Une page de Wikipédia, l'encyclopédie libre.
Ceci est une version archivée de cette page, en date du 22 avril 2023 à 02:34 et modifiée en dernier par Od1n (discuter | contributions) (remplacement de require('Module:No globals') par require('strict'), qui est intégré nativement dans l'extension Scribunto (refs T209310) ; déjà appliqué dans la version italienne : 130113881). Elle peut contenir des erreurs, des inexactitudes ou des contenus vandalisés non présents dans la version actuelle.

 Documentation[créer] [purger]
--[[
* Modulo per implementare le funzionalità dei template:
* {{Wikidata}}, {{WikidataQ}}, {{WikidataIdx}}, {{WikidataN}}, {{WikidataLabel}},
* {{WikidataLink}}, {{WikidataId}}, {{WikidataTipo}} e {{WikidataIstanza}}.
* Permette di accedere a Wikidata in modo più avanzato rispetto a {{#property}}.

* Per la maggior parte riscritto e ampliato a partire dalla versione iniziale a:
* http://test2.wikipedia.org/w/index.php?title=Module:Wikidata&oldid=52322
]]

-- =============================================================================
-- Non utilizzare mai mw.wikibase.getEntity, per esempio un solo utilizzo di
-- mw.wikibase.getEntity('Q183') fa aumentare di 7 MB l'utilizzo di memoria
-- per Lua ed è molto lenta se ripetuta (unico utilizzo in getDatatype,
-- solo per proprietà, non essendoci alternative).
-- =============================================================================

require('strict')

local getArgs = require('Module:Arguments').getArgs
local mConvert = require('Module:Conversion2')
local mLanguages = require('Module:Langue')

-- Categoria per le pagine con errori
local errorCategory = '[[Categoria:Voci con errori del modulo Wikidata]]'

-- Messaggi
local i18n = {
    errors = {
        ['entityid-param-not-provided'] = "Parametro ''entityid'' non fornito",
        ['property-param-not-provided'] = "Parametro ''property'' non fornito",
        ['qualifier-param-not-provided'] = "Parametro ''qualifier'' non fornito",
        ['value-param-not-provided'] = "Parametro ''valore'' da ricercare non fornito",
        ['entity-not-found'] = 'Entità non trovata',
        ['unknown-claim-type'] = 'Tipo asserzione sconosciuta',
        ['unknown-snak-type'] = 'Tipo di snak sconosciuto',
        ['unknown-datavalue-type'] = 'Tipo di dato sconosciuto',
        ['unknown-entity-type'] = 'Tipo di entità sconosciuta'
    },
    somevalue = "''valore sconosciuto''",
    novalue = "''nessun valore''",
    datatypes = {
        ['commonsMedia'] = 'file multimediale su Commons',
        ['external-id'] = 'identificativo esterno',
        ['geo-shape'] = 'forma geografica',
        ['globe-coordinate'] = 'coordinate geografiche',
        ['math'] = 'espressione matematica',
        ['monolingualtext'] = 'testo monolingua',
        ['quantity'] = 'quantità',
        ['string'] = 'stringa',
        ['tabular-data'] = 'tabular data',
        ['time'] = 'data e ora',
        ['url'] = 'URL',
        ['wikibase-item'] = 'elemento',
        ['wikibase-property'] = 'proprietà'
    }
}

local p = {}

-------------------------------------------------------------------------------
--                             Formatters
-------------------------------------------------------------------------------

local function errhandler(msg)
    local cat = mw.title.getCurrentTitle().namespace == 0 and errorCategory or ''
    return string.format('<span class="error">%s</span>%s', msg, cat)
end

local function formatList(values, ordered)
    local fmt = ordered and '<ol><li>%s</li></ol>' or '<ul><li>%s</li></ul>'
    return #values > 0 and string.format(fmt, mw.text.listToText(values, '</li><li>', '</li><li>')) or ''
end

local function formatExtLink(url)
    local protocols = { ftp = true, http = true, https = true }

    local success, uri = pcall(function() return mw.uri.new(url) end)
    if success and uri.protocol and protocols[uri.protocol] then
        local dest = tostring(uri)
        return string.format('<div style="word-break: break-all;">[%s %s]</div>', dest, dest:gsub(uri.protocol .. '://', ''))    
    else
        return url
    end
end

local function formatEntityId(entityId)
    local label = mw.wikibase.getLabel(entityId)
    local siteLink = mw.wikibase.getSitelink(entityId)
    local ret
    if siteLink and label then
        ret = mw.getContentLanguage():ucfirst(label) == siteLink and
              string.format('[[%s]]', label) or
              string.format('[[%s|%s]]', siteLink, label)
    elseif siteLink then
        ret = string.format('[[%s]]', siteLink)
    elseif label then
        ret = label
    else
        ret = ''
    end
    return ret
end

local function formatMonolingualtext(value, args)
    local ret = ''
    if not args.includelang or args.includelang:match('%f[a-z]' .. value.language .. '%f[^a-z]') then
        if not args.excludelang or not args.excludelang:match('%f[a-z]' .. value.language .. '%f[^a-z]') then
            ret = value.text
            if args.showlang then
                ret = mLanguages.lingue({ value.language }) .. '&nbsp;' .. ret
            end
        end
    end
    return ret
end

local function formatTimeWithPrecision(time, precision)
    local months = {
        'gennaio', 'febbraio', 'marzo', 'aprile', 'maggio', 'giugno',
        'luglio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dicembre'
    }
    local ret, year, month, day
 
    year, month, day = time:match('(%d+)%-(%d%d)%-(%d%d).+')
    year, month, day = tonumber(year), tonumber(month), tonumber(day)
    if precision == 9 then
        ret = year
    elseif precision == 10 then
        ret = months[month] .. ' ' .. year
    elseif precision == 11 then
        ret = day .. ' ' .. months[month] .. ' ' .. year
        ret = ret:gsub('^1%s', '1º ')
    end
    if precision >= 9 and precision <= 11 then
        ret = ret .. (time:sub(1, 1) == '-' and ' a.C.' or '')
    end

    return ret
end

local function formatTime(value, args)
    local ret
 
    if args.time == 'precision' then
        ret = value.precision
    elseif args.time == 'calendarmodel' then
        ret = value.calendarmodel
    elseif args.time == 'year' and value.precision >= 9 then
        ret = formatTimeWithPrecision(value.time, 9)
    elseif args.time == 'month' and value.precision >= 10 then
        ret = formatTimeWithPrecision(value.time, 10)
    elseif args.time == 'day' and value.precision >= 11 then
        ret = formatTimeWithPrecision(value.time, 11)
    elseif not args.time then
        ret = formatTimeWithPrecision(value.time, value.precision)
    end

    return ret or ''
end

local function formatGlobecoordinate(value, args)
    local ret
    if args.coord == 'latitude' then
        ret = value.latitude
    elseif args.coord == 'longitude' then
        ret = value.longitude
    elseif args.coord == 'globe' then
        ret = value.globe
    else
        ret = string.format('%s, %s', value.latitude, value.longitude)
    end
    return ret
end

local function formatFromPattern(str, args)
    local pattern = args.pattern
    pattern = mw.ustring.gsub(pattern, '\\{', '{')
    pattern = mw.ustring.gsub(pattern, '\\}', '}')
    return mw.getCurrentFrame():preprocess(mw.message.newRawMessage(pattern, str):plain())
end

local function formatUserValue(value, args)
    if args.extlink then
        value = formatExtLink(value)
    end
    return args.pattern and formatFromPattern(value, args) or value
end

local function getEntityIdFromValue(value)
    local prefix = ''
    if value['entity-type'] == 'item' then
        prefix = 'Q'
    elseif value['entity-type'] == 'property' then
        prefix = 'P'
    else
        error(i18n.errors['unknown-entity-type'])
    end
    return prefix .. value['numeric-id']
end

local function formatUnitSymbol(entityId, args)
    local ret
    for _, lang in ipairs({ 'mul', 'it', 'en' }) do
        ret = p._getProperty({ 'P5061', includelang = lang, from = entityId })
        if ret and ret ~= '' then
            break
        else
            ret = nil
        end
    end
    local space = ret == '°' and '' or ' '
    if ret and args.showunitlink then
        local link = mw.wikibase.getSitelink(entityId)
        if link then
            ret = string.format('[[%s|%s]]', link, ret)
        end
    end
    return ret and (space .. ret) or ''
end

-- http://lua-users.org/wiki/SimpleRound
local function round(num, idp)
    local mult = 10 ^ (idp or 0)
    return math.floor(num * mult + 0.5) / mult
end


local function formatQuantity(value, args)
    local ret = tonumber(value.amount)

    if (args.unit or args.showunit) and value.unit ~= '1' then
        local unitId = mw.ustring.match(value.unit, 'Q%d+')
        if args.unit then
            local opts = {
                showunit = args.showunit,
                showunitlink = args.showunitlink,
                formatnum = args.formatnum,
                rounding = args.rounding
            }
            ret = mConvert._main(ret, unitId, args.unit, opts)
        else
            -- se è richiesto solo il simbolo dell'unità
            -- senza la conversione lo ottiene da P5061
            ret = args.rounding and round(ret, args.rounding) or ret
            if args.formatnum then
                ret = mw.language.getContentLanguage():formatNum(ret)
            end
            ret = ret .. formatUnitSymbol(unitId, args)
        end
    elseif args.formatnum then
        ret = args.rounding and round(ret, args.rounding) or ret
        ret = mw.language.getContentLanguage():formatNum(ret)
    elseif args.formatduration and value.unit ~= '1' then
        local unitId = mw.ustring.match(value.unit, 'Q%d+')
        ret = mConvert._main(ret, unitId, 'second')
        ret = ret and mw.language.getContentLanguage()
                :formatDuration(tonumber(ret), { 'days', 'hours', 'minutes', 'seconds' })
    end

    return ret
end

local function formatDatavalue(datavalue, snakdatatype, args)
    local ret

    if datavalue.type == 'wikibase-entityid' then
        local entityId = getEntityIdFromValue(datavalue.value)
        if args.showprop then
            ret = p._getProperty({ args.showprop, n = 1, from = entityId }) or ''
        else
            ret = args.formatting == 'raw' and entityId or formatEntityId(entityId)
        end
    elseif datavalue.type == 'string' then
        ret = datavalue.value
        if args.extlink and snakdatatype == 'url' then
            ret = formatExtLink(ret)
        elseif args.urlencode then
            ret = mw.uri.encode(ret)
        end
    elseif datavalue.type == 'monolingualtext' then
        ret = formatMonolingualtext(datavalue.value, args)
    elseif datavalue.type == 'time' then
        if args.formatting == 'raw' then
            ret = datavalue.value.time
        else
            ret = formatTime(datavalue.value, args)
        end
    elseif datavalue.type == 'globecoordinate' then
        ret = formatGlobecoordinate(datavalue.value, args)
    elseif datavalue.type == 'quantity' then
        ret = formatQuantity(datavalue.value, args)
    else
        error(i18n.errors['unknown-datavalue-type'])
    end

    return ret
end

local function formatSnak(snak, args)
    if snak.snaktype == 'somevalue' then
        return i18n['somevalue']
    elseif snak.snaktype == 'novalue' then
        return i18n['novalue']
    elseif snak.snaktype == 'value' then
        return formatDatavalue(snak.datavalue, snak.datatype, args)
    else
        error(i18n.errors['unknown-snak-type'])
    end
end

-- È al plurale perché anche i qualifier possono avere più di un valore
-- (si ottiene inserendo due volte lo stesso qualifier)
local function formatQualifiers(claim, qualifierId, args, rawTable, retTable)
    local formattedQualifiers = retTable or {}

    if claim.qualifiers and claim.qualifiers[qualifierId] then
        local qualifiers = claim.qualifiers[qualifierId]
        -- con args.nq seleziona solo l'n-esimo qualifier
        if args.nq then
            local n = tonumber(args.nq)
            qualifiers = (n and n <= #qualifiers) and { qualifiers[n] } or {}
        end
        -- qualifiers filtrati per snaktype, default "value"
        args.snaktype = args.snaktype or 'value'
        for _, qualifier in ipairs(qualifiers) do
            if qualifier.snaktype == args.snaktype or args.snaktype == 'all' then
                local formattedQualifier = formatSnak(qualifier, args)
                if formattedQualifier ~= '' then
                    if args.pattern then
                        formattedQualifier = formatFromPattern(formattedQualifier, args)
                        if formattedQualifier ~= '' then
                            table.insert(formattedQualifiers, formattedQualifier)
                        end
                    else
                        table.insert(formattedQualifiers, formattedQualifier)
                    end
                end
            end
        end
    end

    if rawTable then
        return formattedQualifiers
    end

    return #formattedQualifiers > 0 and
           mw.text.listToText(formattedQualifiers, args.separator, args.conjunction) or nil
end

local function appendQualifiers(statement, text, args)
    local formattedQualifiers = {}
    local qualifierIds = mw.text.split(args.showqualifiers, ',')
    for _, qualifierId in ipairs(qualifierIds) do
        if statement.qualifiers[qualifierId] then
            local formattedQualifier = formatQualifiers(statement, qualifierId, args)
            table.insert(formattedQualifiers, formattedQualifier)
        end
    end
    if #formattedQualifiers > 0 then
        text = string.format('%s (%s)', text, mw.text.listToText(formattedQualifiers, ', ', ', '))
    end
    return text
end

local function formatStatement(statement, args)
    if not statement.type or statement.type ~= 'statement' then
        error(i18n.errors['unknown-claim-type'])
    end
 
    local ret = formatSnak(statement.mainsnak, args)
    -- eventuale showqualifiers
    if args.showqualifiers and statement.qualifiers then
        ret = appendQualifiers(statement, ret, args)
    end

    return ret
end

local function formatStatements(claims, args, rawTable)
    local formattedStatements = {}

    for _, claim in ipairs(claims) do
        local formattedStatement = formatStatement(claim, args)
        if formattedStatement ~= '' then
            -- eventuale pattern
            if args.pattern then
                formattedStatement = formatFromPattern(formattedStatement, args)
                if formattedStatement ~= '' then
                    table.insert(formattedStatements, formattedStatement)
                end
            else
                table.insert(formattedStatements, formattedStatement)
            end
        end
    end
    if rawTable then
        return formattedStatements
    end

    return ((args.list or args.orderedlist) and #formattedStatements > 1) and
           formatList(formattedStatements, args.orderedlist ~= nil) or
           mw.text.listToText(formattedStatements, args.separator, args.conjunction)
end

-------------------------------------------------------------------------------
--                      Lettura e selezione statement
-------------------------------------------------------------------------------

-- Restituisce true se lo statement contiene il qualifier richiesto con un dato valore
local function hasQualifierValue(statement, qualifierId, qualifierValue)
    local ret = false
    for _, qualifier in ipairs(statement.qualifiers[qualifierId]) do
        local isItem = qualifier.snaktype == 'value' and
                       qualifier.datavalue.type == 'wikibase-entityid'
        -- per le proprietà di tipo item il confronto è eseguito sull'id
        if formatSnak(qualifier, isItem and { formatting = 'raw' } or {}) == qualifierValue then
            ret = true
            break
        end
    end
    return ret
end

-- Restituisce i claim con il rank richiesto
local function filterRankValue(claims, rank)
    local ret = {}
    for _, claim in ipairs(claims) do
        if claim.rank == rank then
            table.insert(ret, claim)
        end
    end
    return ret
end

-- Restituisce una sequence Lua contenente gli statement per la property richiesta,
-- anche vuota se la proprietà non esiste, o non ci sono valori che soddisfano i criteri
-- ("rank", "qualifier", "qualifiertype", "noqualifier", ...).
-- Restituisce nil solo se la pagina non è collegata a un elemento Wikidata e non è indicato il from.
local function getClaims(propertyId, args)
    local entityId, claims, filteredClaims
    
    entityId = args.from or mw.wikibase.getEntityIdForCurrentPage()
    if not entityId then
        return nil
    end
    
    -- il default rank è 'best'
    args.rank = args.rank or 'best'
    if args.rank == 'best' then
        claims = mw.wikibase.getBestStatements(entityId, propertyId)
    else
        -- statements filtrati per rank
        claims = mw.wikibase.getAllStatements(entityId, propertyId)
        claims = filterRankValue(claims, args.rank)
    end

    -- statements filtrati per snaktype, default "value"
    args.snaktype = args.snaktype or 'value'
    if args.snaktype and args.snaktype ~= 'all' then
        filteredClaims = {}
        for _, claim in ipairs(claims) do
            if claim.mainsnak.snaktype == args.snaktype then
                table.insert(filteredClaims, claim)
            end
        end
        claims = filteredClaims
    end

    -- statements filtrati per qualifier
    if args.qualifier then
        filteredClaims = {}
        for _, claim in ipairs(claims) do
            if claim.qualifiers and claim.qualifiers[args.qualifier] then
                if args.qualifiervalue then
                    if hasQualifierValue(claim, args.qualifier, args.qualifiervalue) then
                        table.insert(filteredClaims, claim)
                    end
                else
                    table.insert(filteredClaims, claim)
                end
            end
        end
        claims = filteredClaims
    end

    -- statements filtrati per essere senza un qualifier
    if args.noqualifier then
        filteredClaims = {}
        for _, claim in ipairs(claims) do
            if not (claim.qualifiers and claim.qualifiers[args.noqualifier]) then
                table.insert(filteredClaims, claim)
            end
        end
        claims = filteredClaims
    end

    -- statements filtrati per non avere un certo valore a un certo qualifier opzionale
    if args.qualifieroptnovalue and args.qualifiervalue then
        filteredClaims = {}
        for _, claim in ipairs(claims) do
            if claim.qualifiers and claim.qualifiers[args.qualifieroptnovalue] then
                if not hasQualifierValue(claim, args.qualifieroptnovalue, args.qualifiervalue) then
                    table.insert(filteredClaims, claim)
                end
            else
                table.insert(filteredClaims, claim)
            end
        end
        claims = filteredClaims
    end

    -- con args.qualifiertype=latest restituisce solo il più recente
    if args.qualifier and args.qualifiertype == 'latest' then
        local latest, latestTime
        for _, claim in ipairs(claims) do
            if claim.qualifiers and claim.qualifiers[args.qualifier] then
                for _, qualifier in ipairs(claim.qualifiers[args.qualifier]) do
                    if qualifier.datavalue.type == 'time' then
                        if not latestTime or qualifier.datavalue.value.time > latestTime then
                            latest = claim
                            latestTime = qualifier.datavalue.value.time
                        end
                    end
                end
            end
        end
        claims = latest and { latest } or {}
    end

    -- con args.n restituisce solo l'n-esimo elemento
    if args.n then
        local n = tonumber(args.n)
        claims = (n and n <= #claims) and { claims[n] } or {}
    end

    return claims
end

-------------------------------------------------------------------------------
--                  Funzioni esportate per altri moduli
-------------------------------------------------------------------------------

function p._getClaims(propertyId, args)
    return getClaims(propertyId, args or {})
end

function p._formatStatement(statement, args)
    return formatStatement(statement, args or {})
end

function p._formatQualifiers(claim, qualifierId, args, rawTable, retTable)
    return formatQualifiers(claim, qualifierId, args or {}, rawTable, retTable)
end

-- Restituisce il valore di una proprietà di Wikidata oppure nil se l'entity o
-- la proprietà non esistono, o se per parametri di selezione gli statement sono zero.
function p._getProperty(args, rawTable)
    local propertyId, value, claims, ret

    -- parametri posizionali
    propertyId = args[1] and string.upper(args[1])
    if not propertyId then
        error(i18n.errors['property-param-not-provided'], 2)
    end
    value = args[2]
    -- fix uppercase
    args.qualifier = args.qualifier and string.upper(args.qualifier)

    if value then
        ret = formatUserValue(value, args)
    elseif args.wd ~= 'no' then
        claims = getClaims(propertyId, args)
        ret = (claims and #claims > 0) and formatStatements(claims, args, rawTable) or nil
    end

    return ret
end

-- Restituisce il valore di un qualifier di una proprietà di Wikidata,
-- o nil se l'entity o la proprietà non esistono, o se per parametri di selezione non ci sono risultati.
function p._getQualifier(args)
    local propertyId, qualifierId, value, claims, ret

    -- parametri posizionali
    propertyId = args[1] and string.upper(args[1])
    if not propertyId then
        error(i18n.errors['property-param-not-provided'], 2)
    end
    qualifierId = args[2] and string.upper(args[2])
    if not qualifierId then
        error(i18n.errors['qualifier-param-not-provided'], 2)
    end
    value = args[3]

    if value then
        ret = formatUserValue(value, args)
    elseif args.wd ~= 'no' then
        claims = getClaims(propertyId, args)
        if claims and #claims > 0 then
            local formattedQualifiers = {}
            for _, claim in ipairs(claims) do
                formattedQualifiers = formatQualifiers(claim, qualifierId, args, true, formattedQualifiers)
            end
            ret = #formattedQualifiers > 0 and
                  mw.text.listToText(formattedQualifiers, args.separator, args.conjunction) or nil
        end
    end

    return ret
end

-- Restituisce l'indice dello statement con il valore richiesto, o nil se non trovato.
function p._indexOf(args)
    local ret, propertyId, value, claims

    -- parametri posizionali
    propertyId = args[1] and string.upper(args[1])
    if not propertyId then
        error(i18n.errors['property-param-not-provided'], 2)
    end
    value = args[2]
    if not value then
        error(i18n.errors['value-param-not-provided'], 2)
    end

    claims = getClaims(propertyId, args)
    if claims and #claims > 0 then
        args.formatting = 'raw'
        for i, claim in ipairs(claims) do
            if formatStatement(claim, args) == value then
                ret = i
                break
            end
        end
    end

    return ret
end

-- Restituisce il numero di statement di una proprietà di Wikidata.
function p._N(args)
    local propertyId, claims

    -- parametri posizionali
    propertyId = args[1] and string.upper(args[1])
    if not propertyId then
        error(i18n.errors['property-param-not-provided'], 2)
    end
    -- get claims
    claims = getClaims(propertyId, args)

    return claims and #claims or 0
end

-- Restituisce true se la propriertà specificata ha come valore
-- almeno uno tra gli entityId passati come argomento.
function p._propertyHasEntity(propertyId, args)
    local statements = p._getProperty({ propertyId, from = args.from, formatting = 'raw' }, true)
    if statements then
        for _, statement in ipairs(statements) do
            for _, entityId in ipairs(args) do
                if statement == entityId then
                    return true
                end
            end
        end
    end

    return false
end

-- Restituisce true se la proprietà P31 (instance of) ha come valore almeno uno tra gli entityId specificati
function p._instanceOf(args)
    return p._propertyHasEntity('P31', args)
end

-- Restituisce true se la proprietà P279 (subclass of) ha come valore almeno uno tra gli entityId specificati
function p._subclassOf(args)
    return p._propertyHasEntity('P279', args)
end

-- Restituisce l'etichetta di un item o di una proprietà Wikidata.
function p._getLabel(args)
    local entityId = args[1] and string.upper(args[1])
    local ret
    if args[2] then
        ret = mw.wikibase.getLabelByLang(entityId, args[2])
    else
        ret = mw.wikibase.getLabel(entityId)
    end
    return ret
end

-- Restituisce il titolo della pagina collegata a un dato item Wikidata.
function p._getLink(args)
    -- parametri posizionali
    local entityId = args[1] and string.upper(args[1])
    if not entityId then
        error(i18n.errors['entityid-param-not-provided'], 2)
    end
    
    return entityId:sub(1, 1) == 'Q' and formatEntityId(entityId) or nil
end

-- Restituisce il datatype di una proprietà Wikidata.
function p._getDatatype(args)
    local propertyId, entity

    -- parametri posizionali
    propertyId = args[1] and string.upper(args[1])
    if not propertyId then
        error(i18n.errors['property-param-not-provided'], 2)
    end

    entity = mw.wikibase.getEntity(propertyId)
    if not entity then
        error(i18n.errors['entity-not-found'], 2)
    end

    if not i18n.datatypes[entity.datatype] then
        error(i18n.errors['unknown-datavalue-type'], 2)
    end

    return i18n.datatypes[entity.datatype]
end

-- Restituisce l'ID dell'item Wikidata collegato alla pagina corrente o a una pagina specificata
-- (nota: segue i redirect fermandosi al primo redirect collegato a un elemento)
function p._getId(args)
    local ret
    if args[1] then
        local title = mw.title.new(args[1])
        while title do
            local id = mw.wikibase.getEntityIdForTitle(title.prefixedText)
            if id then
                ret = id
                break
            else
                title = title.redirectTarget
            end
        end
    else
        ret = mw.wikibase.getEntityIdForCurrentPage()
    end
    return ret
end

-------------------------------------------------------------------------------
--                  Funzioni esportate per i template
-------------------------------------------------------------------------------

-- Funzione per il template {{Wikidata}}
function p.getProperty(frame)
    return select(2, xpcall(function()
        return p._getProperty(getArgs(frame, { parentOnly = true }))
    end, errhandler))
end

-- Funzione per il template {{WikidataQ}}
function p.getQualifier(frame)
    return select(2, xpcall(function()
        return p._getQualifier(getArgs(frame, { parentOnly = true }))
    end, errhandler))
end

-- Funzione per il template {{WikidataIdx}}
function p.indexOf(frame)
    return select(2, xpcall(function()
        return p._indexOf(getArgs(frame, { parentOnly = true }))
    end, errhandler))
end

-- Funzione per il template {{WikidataN}}
function p.N(frame)
    return select(2, xpcall(function()
        return p._N(getArgs(frame, { parentOnly = true }))
    end, errhandler))
end

-- Funzione per il template {{WikidataLabel}}
function p.getLabel(frame)
    return select(2, xpcall(function()
        return p._getLabel(getArgs(frame, { parentOnly = true }))
    end, errhandler))
end

-- Funzione per il template {{WikidataLink}}
function p.getLink(frame)
    return select(2, xpcall(function()
        return p._getLink(getArgs(frame, { parentOnly = true }))
    end, errhandler))
end

-- Funzione per il template {{WikidataIstanza}}
function p.instanceOf(frame)
    return select(2, xpcall(function()
        return p._instanceOf(getArgs(frame, { parentOnly = true })) and 1 or ''
    end, errhandler))
end

-- Funzione per il template {{WikidataTipo}}
function p.getDatatype(frame)
    return select(2, xpcall(function()
        return p._getDatatype(getArgs(frame, { parentOnly = true }))
    end, errhandler))
end

-- Funzione per il template {{WikidataId}}
function p.getId(frame)
    return select(2, xpcall(function()
        return p._getId(getArgs(frame, { parentOnly = true }))
    end, errhandler))
end

-- Funzione per il template {{WikidataValido}}
function p.checkProperty(frame)
    return select(2, xpcall(function()
        return p._N(getArgs(frame, { parentOnly = true })) > 0 and 1 or ''
    end, errhandler))
end

return p