Vorlagenprogrammierung Diskussionen Lua Unterseiten
Modul Deutsch English


--[=[ 2014-12-18
CatUtil
* count()
* countYears()
]=]



-- table for export
local CatUtil = {}
-- limitation with some leeway
local MaxQueries = 400



local function fault( alert, frame )
    -- Format message with class="error"
    --     alert  -- string, with message
    --     frame  -- object
    -- Returns message with markup
    local r = alert
    if frame then
        r = string.format( "%s * %s", frame:getTitle(), r )
    end
    r = string.format( "<span class=\"error\">ERROR * %s</span>", r )
    return r
end -- fault()



local function figure( achieve, alike, about )
    -- Count items in categories
    --     achieve  -- table, with category titles
    --     alike    -- string, with type, or nil
    --                 all pages files subcats
    --     about    -- string, with name of calling function
    -- Returns number
    local n = #achieve
    local r = 0
    local scope
    if alike then
        local support = "|all|pages|files|subcats|"
        local seek
        scope = alike:lower()
        seek  = string.format( "|%s|", scope )
        if not support:find( seek, 1, true ) then
            n = -1
            r = string.format( "CatUtil::%s scope='%s'",
                               about, alike )
            r = fault( r )
        end
    else
        scope = "pages"
    end
    for i = 1, n do
        r = r + mw.site.stats.pagesInCategory( achieve[ i ], scope )
    end -- for i
    return r
end -- figure()



local function format( achieve, args, about )
    -- Evaluate and format result
    --     achieve  -- table, with category titles
    --     args     -- table, with options
    --     about    -- string, with name of calling function
    -- Returns number or string
    local r
    if #achieve > MaxQueries then
        r = string.format( "CatUtil:: max cat: %d > %d",
                           #titles, MaxQueries )
    else
        r = figure( achieve, args.scope, about )
        if type( r ) == "number" then
            if r == 0 then
                if args.show0 then
                    r = args.show0
                end
            elseif args.showN or args.show1 then
                if r == 1 and args.show1 then
                    r = args.show1
                elseif args.showN:find( "%d", 1, true ) then
                    r = string.format( args.showN, r )
                else
                    r = args.showN
                end
            end
        end
    end
    return r
end -- format()



CatUtil.count = function ( args )
    local support = "|scope|show0|show1|showN|"
    local titles  = { }
    local r, seek, unknown
    for k, v in pairs( args ) do
        if type( k ) == "number" then
            table.insert( titles, v )
        else
            seek = string.format( "|%s|", k )
            if not support:find( seek, 1, true ) then
                if not unknown then
                    unknown = { }
                end
                table.insert( unknown,  k .. "=" )
            end
        end
    end -- for k, v
    if unknown then
        r = string.format( "'<code>%s</code>' in CatUtil::count",
                           table.concat( unknown, " " ) )
        r = fault( r )
    else
        r = format( titles, args, "count" )
    end
    return r
end -- .count()



CatUtil.countYears = function ( args )
    local support = "|scope|serial|show0|show1|showN|since|stop|"
    local r, seek, unknown
    for k, v in pairs( args ) do
        if type( k ) == "number" then
            k = tostring( k )
        end
        seek = string.format( "|%s|", k )
        if not support:find( seek, 1, true ) then
            if not unknown then
                unknown = { }
            end
            table.insert( unknown,  k .. "=" )
        end
    end -- for k, v
    if unknown then
        r = string.format( "'<code>%s</code>' in CatUtil::countYears",
                           table.concat( unknown, " " ) )
        r = fault( r )
    else
        local min, max
        if args.serial then
            if args.serial:find( "%d", 1, true ) then
                if args.since then
                    if args.since:match( "^%d+$" ) then
                        local jump
                        min = tonumber( args.since )
                        if args.stop then
                            if args.stop:match( "^%d+$" ) then
                                max = args.stop
                            elseif args.stop:match( "^[%+%-]%d+$" ) then
                                jump = tonumber( args.stop )
                            else
                                r = string.format( "stop=???%s???",
                                                   args.stop )
                            end
                        end
                        if not r then
                            if not max then
                                max = os.date( "%Y" )
                            end
                            max = tonumber( max )
                            if jump then
                                max = max + jump
                            end
                            if min >= max then
                                r = string.format( "%s %d < %d",
                                                   "stop > since !!",
                                                   min, max )
                            elseif max - min  >  MaxQueries then
                                r = string.format( ">max: %d-%d > %d",
                                                   max, min, MaxQueries )
                            end
                        end
                    else
                        r = string.format( "since=???%s???",
                                           args.since )
                    end
                else
                    r = "since=???"
                end
            else
                r = "serial=...'&#37;d'"
            end
        else
            r = "serial=???"
        end
        if r then
            r = string.format( "CatUtil::countYears %s", r )
            r = fault( r )
        else
            local titles  = { }
            for i = min, max do
                table.insert( titles,
                              string.format( args.serial, i ) )
            end -- for i
            r = format( titles, args, "countYears" )
        end
    end
    return r
end -- .countYears()



-- Export
local p = { }

p.execute = function ( activate, args )
    local r
    if CatUtil[ activate ] then
        local lucky
        lucky, r = pcall( CatUtil[ activate ], args )
    else
        r = "ERROR  CatUtil::execute() activate=" .. tostring( activate )
    end
    return r
end

p.count = function ( frame )
    local lucky, r = pcall( CatUtil.count, frame:getParent().args )
    if not lucky then
        r = fault( r, frame )
    end
    return r
end

p.countYears = function ( frame )
    local lucky, r = pcall( CatUtil.countYears, frame:getParent().args )
    if not lucky then
        r = fault( r, frame )
    end
    return r
end

function p.CatUtil()
    return CatUtil
end

return p