Module:Sandbox/Hike395/Wikidata utils

.mw-parser-output .documentation,.mw-parser-output .documentation-metadata{border:1px solid var(--border-color-base,#a2a9b1);background-color:#ecfcf4;color:inhe

Module:Sandbox/Hike395/Wikidata utils
require('strict')

-- Is the string a valid QID?
local function validQid(qid)
    return qid and mw.ustring.find(qid,"^[Qq]%d+$")
end

-- lookup nestedIndex in outer table
-- Example:  fetchNested(foo,{'bar','baz','quux'}) will return
--     foo.bar and foo.bar.baz and foo.bar.baz.quux
local function fetchNested(outer,nestedIndex)
    if not outer or type(outer) ~= 'table' or not nestedIndex or type(nestedIndex) ~= 'table' then
        return nil
    end
    local current = outer
    for _, indx in ipairs(nestedIndex) do
        current = current[indx]
        if not current then
            return current
        end
    end
    return current
end

-- Mapping from wikidata properties (of a reference or "stated in" entity) to citation parameters
local pid2param = {
    P50 = "author",
    P123 = "publisher",
    P407 = "language",
    P577 = "date",
    P813 = "access-date",
    P854 = "url",
    P856 = "url",
    P953 = "url",
    P1476 = "title",
    P2699 = "url",
}

-- scan through snaks, loading citation args with correct values
local function scanSnaks(args, snaks)
    for pid, data in pairs(snaks) do
        data = fetchNested(data,{1,'mainsnak'}) or data[1] -- handle the case where the snak is buried in the claims
        local param = pid2param[pid]
        if pid == "P248" then  --- "stated in": must look up different entity for data
            local statedId = fetchNested(data,{'datavalue','value','id'})
            local statedEntity = statedId and mw.wikibase.getEntity(statedId)
            local statedClaims = statedEntity and statedEntity.claims
            if statedClaims then
                scanSnaks(args, statedClaims)
            end
            local statedLabel = fetchNested(statedEntity,{'labels','en','value'})
            args.title = args.title or statedLabel
        elseif param then
            local renderedData = data and mw.wikibase.renderSnak(data)
            if param == "title" then
                -- set language from title if not otherwise specified
                args.language = args.language or fetchNested(data,{'datavalue','value','language'})
            end
            if pid == "P856" then --- use official URL only if URL is missing
                args[param] = args[param] or renderedData
            else
                args[param] = renderedData
            end
        end
    end
end

-- function to assemble wikicode to create citation, given reference property
local function citeSource(snaks)
    local args = {}
    args.mode = "cs1"
    scanSnaks(args, snaks)
    -- citation templates are unhappy without a title, so return a wikilink
    if not args.title then  
        return args.url and "["..args.url.."]"
    end
    if not args.url then
        args["access-date"] = nil  -- don't allow access date without url
    end
    local result = '{{'..(args.url and 'cite web' or 'citation')
    for k,v in pairs(args) do
        result = result..'|'..k..'='..v
    end
    result = result..'}}'
    return result
end

-- Core function that looks up value, reference, and data for property
-- Arguments:
--   qid = entity id in Wikidata
--   pid = property id on that entity
--   unit = if non-nil, desired unit for value (expressed as a qid for that unit)
--   asOf = date or partial date string to prefer. If not given, find the latest version
-- Returns table only if Wikidata property is source externally
--   amount = value that is looked up (or nil)
--   source = wiki markup for reference
--   asOf = date that value is valid (if given)
local function getValueAndRef(qid,pid,unit,asOf)
    local results = nil
    local latest = nil
    local statements = mw.wikibase.getAllStatements(qid, pid ) 
    for _, statement in pairs(statements) do
        local amount
        local wrongDate = true
        local value = fetchNested(statement,{'mainsnak','datavalue','value'})
        if value then
            amount = value.amount
        end
        -- check if unit is correct, if given
        if unit then
            local storedUnit = value.unit
            if not storedUnit or not mw.ustring.find(value.unit or '',unit,1,true) then
                amount = nil
            end
        end
        -- check if asOf matches stored date
        -- if asOf not specified, remember stored date
        local storedAsOf = fetchNested(statement,{'qualifiers','P585',1,'datavalue','value','time'})
        local date
        if storedAsOf then
            date = mw.ustring.match(storedAsOf,'^%+(%d+%-%d+%-%d+)')
            local justYear = mw.ustring.match(date,'^(%d+)%-0+%-0+$')
            date = justYear or date
            if asOf then
                wrongDate = date and not mw.ustring.find(date,asOf,1,true)
            end
        end
        -- check to see if this statement is adequately sourced (filter out "imported from" refs)
        local source
        local refs = statement['references']
        if refs then
            for _, ref in pairs(refs) do
                local renderedRef = ref.snaks and mw.wikibase.renderSnaks(ref.snaks)
                if renderedRef and not mw.ustring.find(renderedRef,'Wiki') then
                    source = citeSource(ref.snaks)
                end
            end
        end
        if amount and source then -- yes, it is adequately sourced,
            local theseResults = {}
            theseResults.amount = tonumber(amount)
            theseResults.source = source
            theseResults.asOf = date
            -- if we haven't found the preferred date
            if wrongDate then
                if date and (not latest or date > latest) then -- store latest if dated
                    results = theseResults
                    latest = date
                elseif not date then -- store first if undated
                    results = results or theseResults
                end
            -- here, we found the correct date, so return it
            else
                results = theseResults
                break
            end
        end
    end
    return results
end

return {validQid=validQid, fetchNested=fetchNested, citeSource=citeSource, getValueAndRef=getValueAndRef}

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.