Vorlagenprogrammierung Diskussionen Lua Test Unterseiten
Modul Deutsch English

Modul: Dokumentation

Diese Seite enthält Code in der Programmiersprache Lua. Einbindungszahl Cirrus

Dies ist die (produktive) Mutterversion eines global benutzten Lua-Moduls.
Wenn die serial-Information nicht übereinstimmt, müsste eine Kopie hiervon in das lokale Wiki geschrieben werden.
Versionsbezeichnung auf WikiData: 2019-10-14

local ISO3166 = { suite    = "ISO3166",
                  serial   = "2019-10-14",
                  item     = 69799761 }
--[=[
Retrieve ISO 3166 data and convert codes
require()
]=]
local Failsafe = ISO3166
ISO3166.pats = { A2  = "^%u%u$",
                 A3  = "^%u%u%u$",
                 A4  = "^%u%u%u%u$",
                 NUM = "^%d%d%d$" }



local find = function ( a2, ancient )
    -- Retrieve aliases table
    -- Precondition:
    --     a2       -- string, with A2 key
    --     ancient  -- true, if not redirecting old code to new country
    -- Returns  table of strings, or false
    local r, store
    if type( ISO3166.resolve ) ~= "table" then
        ISO3166.resolve = { }
    end
    if ancient then
        store = a2 .. "_"
    else
        store = a2
    end
    if type( ISO3166.resolve[ store ] ) ~= "nil" then
        r = ISO3166.resolve[ store ]
    else
        local set = ISO3166.codes[ a2 ]
        if type( set ) == "string" then
            local s
            r = mw.text.split( set, "%s+" )
            s = r[ 1 ]
            if s  and  s ~= a2 then
                if #s == 2  and  not ancient then
                    set = ISO3166.codes[ s ]
                    if type( set ) == "string" then
                        r = mw.text.split( set, "%s+" )
                    end
                end
                table.insert( r, 1, a2 )
            end
        end
        ISO3166.resolve[ store ] = ( r or false )
    end
    return r
end -- find()



ISO3166.fetch = function ( alert )
    -- Retrieve data
    -- Precondition:
    --     alert  -- true, for throwing error on data problem
    -- Postcondition:
    --     Library is extended, if necessary
    if not ( ISO3166.codes and ISO3166.reverse ) then
        local sub     = "loadData"
        local storage = string.format( "Module:%s/%s",
                                       ISO3166.suite, sub )
        local lucky, data = pcall( mw.loadData, storage )
        if not lucky then
            if not ISO3166.suited  and
               type( ISO3166.item ) == "number" then
                local suited = string.format( "Q%d", ISO3166.item )
                ISO3166.suited = mw.wikibase.getSitelink( suited )
            end
            if type( ISO3166.suited ) == "string" then
                storage = string.format( "%s/%s", ISO3166.suited, sub )
                lucky, data = pcall( mw.loadData, storage )
            end
        end
        if type( data ) == "table" then
            if type( data.codes ) == "table" and
               type( data.reverse ) == "table" then
                ISO3166.codes   = data.codes
                ISO3166.reverse = data.reverse
            elseif alert then
                error( "Invalid table (codes/reverse)", 0 )
            end
        elseif alert then
            error( "Missing page: " .. storage, 0 )
        end
        ISO3166.codes   = ISO3166.codes   or { }
        ISO3166.reverse = ISO3166.reverse or { }
    end
end -- ISO3166.fetch()



ISO3166.f = function ( access, alter, ancient )
    -- Retrieve preferred code
    -- Precondition:
    --     access   -- string, with key as A2, A3, NUM, A4
    --     alter    -- string, optional, with one of A2, A3, NUM (A3)
    --     ancient  -- true, if not redirecting old code to new country
    -- Returns  string  -- with converted code
    --          false   -- if unknown
    local r
    if type( access ) == "string" then
        local seek = access:upper()
        local entry, suitable
        if type( alter ) == "string" then
            suitable = alter:upper()
            if suitable == "A4" then
                ancient = true
            end
        else
            suitable = "A3"
        end
        ISO3166.fetch()
        seek = ISO3166.reverse[ seek ]
        if seek then
            entry = find( seek, ancient )
            if entry then
                suitable = ISO3166.pats[ suitable ]
                if not suitable then
                    suitable = ISO3166.pats.A3
                end
                if suitable then
                    local s
                    for i = 1, #entry do
                        s = entry[ i ]
                        if s:match( suitable ) then
                            r = s
                            break -- for i
                        end
                    end -- for i
                    if not r  and  #entry == 1 then
                        -- "EU" fallback
                        r = entry[ 1 ]
                    end
                end
            end
        end
    end
    return r  or  false
end -- ISO3166.f()



Failsafe.failsafe = function ( atleast )
    -- Retrieve versioning and check for compliance
    -- Precondition:
    --     atleast  -- string, with required version or "wikidata" or "~"
    --                 or false
    -- Postcondition:
    --     Returns  string  -- with queried version, also if problem
    --              false   -- if appropriate
    local last  = ( atleast == "~" )
    local since = atleast
    local r
    if last  or  since == "wikidata" then
        local item = Failsafe.item
        since = false
        if type( item ) == "number"  and  item > 0 then
            local entity = mw.wikibase.getEntity( string.format( "Q%d",
                                                                 item ) )
            if type( entity ) == "table" then
                local vsn = entity:formatPropertyValues( "P348" )
                if type( vsn ) == "table"  and
                   type( vsn.value ) == "string"  and
                   vsn.value ~= "" then
                    if last  and  vsn.value == Failsafe.serial then
                        r = false
                    else
                        r = vsn.value
                    end
                end
            end
        end
    end
    if type( r ) == "nil" then
        if not since  or  since <= Failsafe.serial then
            r = Failsafe.serial
        else
            r = false
        end
    end
    return r
end -- Failsafe.failsafe()



-- Export
local p = { }

function p.f( frame )
    local seek = frame.args[ 1 ]
    local r
    if seek then
        seek = mw.text.trim( seek )
        if seek ~= "" then
            local shift = frame.args[ 2 ]
            local stop  = frame.args[ 3 ]
            local lazy
            if shift then
                shift = mw.text.trim( shift )
                if shift == "" then
                    shift = false
                end
            end
            if stop then
                lazy =(  mw.text.trim( stop )  ==  "1" )
            end
            r = ISO3166.f( seek, shift, lazy )
        end
    end
    return r  or  ""
end -- p.f



p.failsafe = function ( frame )
    -- Versioning interface
    local s = type( frame )
    local since
    if s == "table" then
        since = frame.args[ 1 ]
    elseif s == "string" then
        since = frame
    end
    if since then
        since = mw.text.trim( since )
        if since == "" then
            since = false
        end
    end
    return Failsafe.failsafe( since )  or  ""
end -- p.failsafe



p.ISO3166 = function ()
    return ISO3166
end -- p.ISO3166()

return p