Module:Library classification navigation

From Wikimedia Commons, the free media repository
Jump to navigation Jump to search
Lua
CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules

Documentation for this module may be created at Module:Library classification navigation/doc

Code

-- Introduction:
-- This Lua module, named Module:Library classification navigation, is designed for facilitating navigation within book classification categories on Wikimedia Commons. It includes functions to search for values in nested dictionaries, retrieve keys from tables, check if a table is an array, check if a value is in an array, and perform category and display name lookups. The main module utilizes these functions to generate a formatted category link based on a given classification structure.

-- Function to search for a value in a nested dictionary
function searchNestedDict(dictionary, searchValue, currentPath)
    currentPath = currentPath or {}  -- Set default value for currentPath
    for key, value in pairs(dictionary) do
        local path = {unpack(currentPath)}  -- Create a copy of currentPath
        table.insert(path, {[key] = getKeys(dictionary)})  -- Add the current key and its keys to the path
        if key == searchValue then 
            -- Immediate child level
            local childValue=getKeysOrValues(value)
            if type(value) == "table" and #childValue~=0 then
                table.insert(path, {[key] = childValue})
            end
            return path  
        elseif type(value) == "table" and not isArray(value) then
            local result = searchNestedDict(value, searchValue, path)  -- Recursive call for nested tables
            if result then
                return result
            end
        elseif isArray(value) and inArray(searchValue, value) then
            table.insert(path, {[searchValue] = value})  -- Add the searchValue and its array to the path
            return path
        end
    end
    return nil  -- Return nil if searchValue is not found
end

-- Function to get keys from a table
function getKeys(t)
    local keySet = {}
    for k, v in pairs(t) do
        table.insert(keySet, k)
    end
    return keySet
end

function getKeysOrValues(t)
    local keySet = {}
    for k, v in pairs(t) do
        if type(k) == "number" then
            table.insert(keySet, v)
        else
            table.insert(keySet, k)
        end
    end
    return keySet
end
-- Function to check if a table is an array
function isArray(t)
    local i = 0
    for _ in pairs(t) do
        i = i + 1
        if t[i] == nil then return false end
    end
    return true
end

-- Function to check if a value is in an array
function inArray(val, arr)
    for _, v in ipairs(arr) do
        if v == val then
            return true
        end
    end
    return false
end

-- Function to look up a category name in a table
function categoryNameLookup(table, targetKey)
    local value = table[targetKey]
    return value or targetKey
end

-- Function to look up a display name in a table based on language preference
function displayNameLookup(table, key)
    local langTable = table[key] or {}
    local value = langTable[myLang] or langTable["en"] or langTable["ja"] or langTable["zh"] or ""
    return value
end

-- Function to generate a formatted category link
function showCatLink(sisterCat, currentCat)
    local result
    local displayName = displayNameLookup(DisplayNameTable, sisterCat)
    -- show class number or not
    if showClass == true then
        classText = sisterCat .. " "
    else
        classText = ""
    end
    local showName = displayName ~= "" and classText .. displayName or sisterCat
    if sisterCat == currentCat then
        result = "'''[[:Category:"..classification.." " .. categoryNameLookup(CategoryNameTable, sisterCat) .. "|" .. showName  .. "]]'''"
    else
        result = "[[:Category:"..classification.." " .. categoryNameLookup(CategoryNameTable, sisterCat) .. "|" .. showName  .. "]]"
    end
    return result
end

-- Main module
local p = {}

function p.main(frame)
    myLang = frame:preprocess('{{Int:Lang}}')  -- Get language preference from the frame
    myLang = string.gsub(myLang, "zh.+", "zh")
    local pageTitle = mw.title.getCurrentTitle().text  -- Get the current page title
    local parts = {}
    for part in pageTitle:gmatch("%S+") do
        table.insert(parts, part)  -- Split the page title into parts
    end
    classification = parts[1]
    local class = parts[2]

    -- Load required tables based on classification
    
    StructureTable = mw.loadJsonData("Module:Library classification navigation/"..classification.."/StructureTable.json")
    CategoryNameTable = mw.loadJsonData("Module:Library classification navigation/"..classification.."/CategoryTitleTable.json")
    DisplayNameTable = mw.loadJsonData("Module:Library classification navigation/"..classification.."/DisplayNameTable.json")
    --title bug (https://phabricator.wikimedia.org/T355763) temporary solution start: prepended "test" in keys and remove here before use.
    function removeTestFromKeys(t)
        local newTable = {}
        for k, v in pairs(t) do
            local newKey = k
            if type(k) == 'string' then
                newKey = k:gsub("^test", "")
            end
            if type(v) == 'table' then
                newTable[newKey] = removeTestFromKeys(v)
            else
                newTable[newKey] = v
            end
        end
        return newTable
    end
    if classification:sub(1, 3) == "NDC" then
        StructureTable = removeTestFromKeys(StructureTable)
        CategoryNameTable = removeTestFromKeys(CategoryNameTable)
        DisplayNameTable = removeTestFromKeys(DisplayNameTable)
    end
    --title bug temporary solution end.
    local result = searchNestedDict(StructureTable, class)  -- Search for the class in the structure table
    local hr = "<hr style='border-width: 2px; margin: 2px 0;' />"
    local classificationName = displayNameLookup(DisplayNameTable, "title")  
    local showName = classificationName ~= "" and classificationName or classification
    local output = "'''[[:Category:"..CategoryNameTable["title"].."|"..showName.."]]'''" .. hr
    if DisplayNameTable["showClass"] == nil then
        showClass = true
    else
    	showClass = false
    end
    local resultCount = #result
    for i, value in pairs(result) do
        for currentCat, v in pairs(value) do
            local sortedV = {}
            for _, sisterCat in pairs(v) do
                table.insert(sortedV, sisterCat)  -- Create a sorted array of sister categories. In Lua, tables are inherently unordered collections. However, if you want to create a sorted representation of the values in a table, you can achieve this by creating a separate array and sorting it. 
            end
            table.sort(sortedV)

            for i, sisterCat in ipairs(sortedV) do
                output = output .. showCatLink(sisterCat, currentCat)  -- Add formatted category links to the output
                if i < #sortedV then
                    output = output .. " · "
                end
            end

            if i < resultCount or next(result, i) ~= nil then
                output = output .. hr  -- Add horizontal rule if not the last iteration
            end
        end
    end

    return output  -- Return the final output
end

return p  -- Return the module

--code for debug:
--classification = "SIBU"
--local class = "經部-易類"
--local result = searchNestedDict(StructureTable, class)
--print(mw.dumpObject(result ))