Module:RecursiveSelectiveList

Revision as of 17:49, 22 December 2024 by EnWikiAdmin (talk | contribs)

Documentation for this module may be created at Module:RecursiveSelectiveList/doc

local p = {}

-- Helper function to format numbers with commas
local function formatNumber(num)
    if not num then return "0" end
    local formatted = tostring(num)
    local k
    while true do  
        formatted, k = formatted:gsub("^(-?%d+)(%d%d%d)", '%1,%2')
        if k == 0 then break end
    end
    return formatted
end

-- Helper function to format dates
local function formatDate(timestamp)
    -- Convert ISO 8601 to a more readable format
    return mw.language.formatDate(timestamp, '%Y-%m-%d %H:%M:%S')
end

-- Function to retrieve category statistics
function p.getCategoryStats(frame)
    local categoryName = frame.args.categoryName -- Pass the category name as an argument

    if not categoryName or categoryName == "" then
        return "'''Error:''' No category name provided."
    end

    local stats = mw.site.stats.pagesInCategory(categoryName, "*")
    if not stats then
        return "'''Error:''' Unable to retrieve statistics for the category."
    end

    -- Calculate percentages
    local total = stats.all
    local pagesPercent = total > 0 and string.format("%.2f%%", (stats.pages / total) * 100) or "0%"
    local subcatsPercent = total > 0 and string.format("%.2f%%", (stats.subcats / total) * 100) or "0%"
    local filesPercent = total > 0 and string.format("%.2f%%", (stats.files / total) * 100) or "0%"

    -- Create a link to the category
    local categoryLink = "[[Category:" .. mw.text.encode(categoryName) .. "|" .. mw.text.encode(categoryName) .. "]]"

    -- Build the wikitext table for category stats
    local result = {}
    table.insert(result, '{| class="wikitable sortable" style="width:50%; margin:auto;"')
    table.insert(result, '! colspan="3" style="text-align:center; font-size:150%;" ' .. categoryLink)
    table.insert(result, '|-')
    table.insert(result, '! Statistic !! Count !! Percentage')
    table.insert(result, '|-')
    table.insert(result, '| Total items || ' .. formatNumber(stats.all) .. ' || 100%')
    table.insert(result, '|-')
    table.insert(result, '| Pages || ' .. formatNumber(stats.pages) .. ' || ' .. pagesPercent)
    table.insert(result, '|-')
    table.insert(result, '| Subcategories || ' .. formatNumber(stats.subcats) .. ' || ' .. subcatsPercent)
    table.insert(result, '|-')
    table.insert(result, '| Files || ' .. formatNumber(stats.files) .. ' || ' .. filesPercent)
    table.insert(result, '|}')

    return table.concat(result, "\n")
end

-- Function to list revision dates for pages in the category
function p.listRevisionDates(frame)
    local categoryName = frame.args.categoryName -- Pass the category name as an argument

    if not categoryName or categoryName == "" then
        return "'''Error:''' No category name provided."
    end

    -- Retrieve pages in the category
    local pages = mw.site.getCategoryMembers(categoryName, "page", 50) -- Limit to 50 pages for demo
    if not pages or #pages == 0 then
        return "'''Error:''' No pages found in the category."
    end

    -- Initialize the table for revision data
    local result = {}
    table.insert(result, "<h2>Latest Revisions for Pages in [[" .. mw.text.encode(categoryName) .. "]]</h2>")
    table.insert(result, '{| class="wikitable sortable" style="width:80%; margin:auto;"')
    table.insert(result, '! Page !! Latest Edit Date !! Edited By')

    for _, page in ipairs(pages) do
        local pageTitle = page.title
        local title = mw.title.new(pageTitle)
        if title and title.exists then
            local revision = title:getLatestRevision()
            if revision then
                local timestamp = revision:getTimestamp()
                local formattedTime = formatDate(timestamp)
                local user = revision:getUser()
                table.insert(result, string.format("|-\n| [[%s]] || %s UTC || [[User:%s|%s]]", 
                    mw.text.encode(pageTitle), 
                    formattedTime, 
                    mw.text.encode(user), 
                    mw.text.encode(user)
                ))
            else
                table.insert(result, string.format("|-\n| [[%s]] || N/A || N/A", mw.text.encode(pageTitle)))
            end
        else
            table.insert(result, string.format("|-\n| [[%s]] || Page does not exist || N/A", mw.text.encode(pageTitle)))
        end
    end

    table.insert(result, '|}')
    
    return table.concat(result, "\n")
end

-- Function to get the latest revision date of a single page (optional)
function p.getLatestEditDate(frame)
    local pageName = frame.args.pageName
    if not pageName or pageName == "" then
        return "'''Error:''' No page name provided."
    end

    local title = mw.title.new(pageName)
    if not title or not title.exists then
        return "'''Error:''' Invalid or non-existent page title."
    end

    local revision = title:getLatestRevision()
    if not revision then
        return "'''Error:''' Unable to retrieve the latest revision."
    end

    local timestamp = revision:getTimestamp()
    local formattedTime = formatDate(timestamp)
    local user = revision:getUser()

    return string.format("**Latest Edit Date for [[%s]]:** %s UTC by [[User:%s|%s]]", 
        mw.text.encode(pageName), 
        formattedTime, 
        mw.text.encode(user), 
        mw.text.encode(user)
    )
end

-- Main function to orchestrate the output
function p.main(frame)
    local categoryStats = p.getCategoryStats(frame)
    local revisionData = p.listRevisionDates(frame)
    local singlePageRevision = p.getLatestEditDate(frame) -- Example of single page revision

    -- Optionally, you can include the single page revision by passing a specific page name
    -- For demo purposes, you can set a default page or allow it via frame.args

    -- Add a separator between sections
    local separator = "\n\n"

    -- Combine all parts
    local output = table.concat({categoryStats, separator, revisionData, separator, singlePageRevision}, "\n")

    -- Optionally, add a timestamp of when the data was retrieved
    local timestamp = os.date("Retrieved on %Y-%m-%d at %H:%M:%S UTC")
    output = output .. '\n<div style="text-align:center; font-size:small; color:gray;">' .. timestamp .. '</div>'

    return output
end

return p