Module:Figurines: Difference between revisions

From Zelda Wiki, the Zelda encyclopedia
Jump to navigation Jump to search
No edit summary
No edit summary
Line 180: Line 180:
})
})
subjectsWithFigurines = utilsTable.map(subjectsWithFigurines, "subjects")
subjectsWithFigurines = utilsTable.map(subjectsWithFigurines, "subjects")
subjectsWithFigurines = utilsTable.filter(subjectsWithFigurines, utilsString.notBlank)
subjectsWithFigurines = utilsTable.flatMap(subjectsWithFigurines, utilsString.split)
subjectsWithFigurines = utilsTable.flatMap(subjectsWithFigurines, utilsString.split)

Revision as of 21:33, 26 November 2022

This is the main module for the following templates:
local p = {}
local h = {}

local DataTable = require("Module:Data Table")
local Franchise = require("Module:Franchise")
local TransclusionArguments = require("Module:Transclusion Arguments")
local utilsArg = require("Module:UtilsArg")
local utilsCargo = require("Module:UtilsCargo")
local utilsString = require("Module:UtilsString")
local utilsTable = require("Module:UtilsTable")

local CARGO_TABLE = "Figurines"
local CATEGORY_INVALID_ARGS = require("Module:Constants/category/invalidArgs")
local STORING_PAGE_FORMAT = "Figurines in %"
local COLUMN_DESCRIPTION = "Description"
local COLUMN_FIGURINE = "Figurine"
local COLUMN_NUMBER = "Number"
local COLUMN_SUBJECTS = "Subject(s)"

local GAMES = {
	["TWW"] = {
		gallery = "Nintendo Gallery",
		columns = {"Figurine", "Description"},
	},
	["TMC"] = {
		gallery = "Figurine Gallery",
		columns = {"Figurine", "Number", "Description"},
	},
}

function h.warn(msg, ...)
	local utilsError = require("Module:UtilsError")
	msg = string.format(msg, ...)
	utilsError.warn(msg)
end
function h.warnEmpty(column, rowIndex)
	h.warn("The value for column <code>%s</code> in row %d should not be empty.", column, rowIndex)
	return "[[Category:"..CATEGORY_INVALID_ARGS.."]]"
end

function p.Main(frame)
	local args, err = utilsArg.parse(frame:getParent().args, p.Templates["Figurines"])
	local categories = err and err.categoryText or ""
	
	if err then
		return "", categories
	end
	TransclusionArguments.store({
		module = "Module:Figurines",
		isValid = true,
		args = {args.game}
	})
	
	local page = args.page or mw.title.getCurrentTitle().subpageText
	local queryResults = utilsCargo.query(CARGO_TABLE, "figurine, name, number, description", {
		where = utilsCargo.allOf(
			{ game = args.game },
			string.format("_pageName LIKE '%s'", STORING_PAGE_FORMAT),
			utilsCargo.holdsAny("subjects", {page})
		),
		orderBy = "number, name, _ID" -- sort by ID so that figurines with the same name are listed in the order stored (see Silver Darknut)
	})
	if #queryResults == 0 then
		h.warn("No figurines found for subject <code>%s</code> in game <code>%s</code>.", page, args.game)
		categories = categories.."[[Category:"..CATEGORY_INVALID_ARGS.."]]"
		return "", categories
	end
	
	local gameData = GAMES[args.game] or {}
	
	local columnHeaders = gameData.columns or {"Figurine", "Description"}
	local dataRows = {}
	for i, figurine in ipairs(queryResults) do
		local row = {
			cells = {}
		}
		table.insert(row.cells, {
			sortValue = figurine.name,
			content = figurine.figurine,
		})
		if args.game == "TMC" then
			table.insert(row.cells, {
				content = figurine.number,
			})
		end
		table.insert(row.cells, {
			content = mw.text.killMarkers(figurine.description),
		})
		table.insert(dataRows, row)
	end
	local dataTable = DataTable.printTable({
		headers = columnHeaders, 
		rows = dataRows, 
		sortable = false,
	})
	local header
	local collapsible = frame:expandTemplate({
		title = "Collapsible",
		args = {
			header = gameData.gallery or #dataRows > 1 and "Figurines" or "Figurine",
			frame = "true",
			collapse = #dataRows > 1 and "true" or "false",
			content = dataTable,
		}
	})
	return collapsible, categories
end

local storeCategories = ""
function p.DataTable(frame)
	local dataTable, dataTableCategories = DataTable.Main(frame, h.store)
	return dataTable, storeCategories..dataTableCategories
end
function h.store(args)
	local requiredColumns = {COLUMN_DESCRIPTION, COLUMN_FIGURINE, COLUMN_SUBJECTS}
	local missingColumns = utilsTable.difference(requiredColumns, args.headers)
	if #missingColumns > 0 then
		local utilsMarkup = require("Module:UtilsMarkup")
		missingColumns = utilsTable.map(missingColumns, utilsMarkup.code)
		h.warn("Columns %s are required.", mw.text.listToText(missingColumns))
		storeCategories = storeCategories.."[[Category:"..CATEGORY_INVALID_ARGS.."]]"
	end
	for i, row in ipairs(args.rows) do
		local cellsByColumn = utilsTable.keyBy(row.cells, "columnHeader")
		local figurineCell = cellsByColumn[COLUMN_FIGURINE] or {}
		local subjectsCell = cellsByColumn[COLUMN_SUBJECTS] or {}
		local descriptionCell = cellsByColumn[COLUMN_DESCRIPTION] or {}
		local numberCell = cellsByColumn[COLUMN_NUMBER] or {}
		
		if figurineCell.raw == nil or figurineCell.raw == "" then
			storeCategories = storeCategories..h.warnEmpty(COLUMN_FIGURINE, i)
		end
		if descriptionCell.raw == nil or descriptionCell.raw == "" then
			storeCategories = storeCategories..h.warnEmpty(COLUMN_DESCRIPTION, i)
		end
		if mw.title.getCurrentTitle().nsText ~= "Template" then
			local figurineName = figurineCell.raw 
			figurineName = figurineName and string.gsub(figurineName, "%[Player Name%]", "Link")
			figurineName = figurineName and string.gsub(figurineName, "%s%[[%d]%]", "")
			
			mw.getCurrentFrame():expandTemplate({
				title = "Figurines/Store",
				args = {
					game = Franchise.baseGame(args.game) or args.game,
					number = numberCell.raw,
					name = figurineName,
					subjects = subjectsCell.raw,
					figurine = figurineCell.storedContent or figurineCell.content,
					description = descriptionCell.content,
				}
			})
		end
	end
end

function p.Report(frame)
	local report = ""
	report = report..h.report("TWW")
	report = report..h.report("TMC")
	if report == "" then
		report = "{{Good}} No issues detected—All subjects which have figurines in [[Figurines in The Wind Waker|TWW]] or [[Figurines in The Minish Cap|TMC]] have this template on their respective articles."
	elseif mw.title.getCurrentTitle().subpageText ~= "Documentation" then
		report = report.."[[Category:Templates Needing Attention]]"
	end
	return frame:preprocess(report)
end
function h.report(game)
	local utilsMarkup = require("Module:UtilsMarkup")
	local report = ""

	local articlesWithFigurines = TransclusionArguments.query({
		template = "Template:Figurines",
		parameter = "1",
		argument = game,
	})
	articlesWithFigurines = utilsTable.map(articlesWithFigurines, "_pageName")
	
	local subjectsWithFigurines = utilsCargo.query("Figurines", "subjects", {
		where = string.format("game = '%s'", game)
	})
	subjectsWithFigurines = utilsTable.map(subjectsWithFigurines, "subjects")
	subjectsWithFigurines = utilsTable.filter(subjectsWithFigurines, utilsString.notBlank)
	subjectsWithFigurines = utilsTable.flatMap(subjectsWithFigurines, utilsString.split)
	
	local articlesMissingFigurines = utilsTable.difference(subjectsWithFigurines, articlesWithFigurines)
	
	if #articlesMissingFigurines > 0 then
		local listArticles = utilsTable.map(articlesMissingFigurines, utilsMarkup.link)
		listArticles = utilsMarkup.bulletList(listArticles)
		report = report..string.format("{{Template|Figurines|%s}} should be added to the following articles as they have [[Figurines in %s|Figurines in %s]]:", game, Franchise.shortName(game), Franchise.display(game))
		report = report..listArticles
	end
	return report
end

p.Templates = {
	["Figurines"] = {
		purpose = "Displays the figurines of a particular subject by retrieving data stored at [[Figurines in The Wind Waker]] or [[Figurines in The Minish Cap]].",
		usesData = true,
		categories = {"Comment Templates"},
		params = {
			[1] = {
				name = "game",
				desc = "A game code.",
				enum = utilsTable.keys(GAMES),
				required = true,
			},
			[2] = {
				name = "page",
				type = "wiki-page-name",
				desc = "A wiki page name. Should usually be left blank, in which case it default to the current page.",
				trim = true,
				nilIfEmpty = true,
			},
		},
		examples = {
			vertical = true,
			{"TWW", "Link"},
			{
				desc = "Collapsed by default when there is more than one figurine.",
				args = {"TMC", "Vaati"},
			},
			{
				desc = "Different figurines can have the same name.",
				args = {"TWW", "Silver Darknut"},
			},
			{
				desc = "Error handling",
				args = {"TWW", "Not a Page"},
			},
			{
				args = {"Not a Game"},
			},
		},
	},
	["Data Table/Figurines"] = {
		purpose = string.format("An extension of [[Template:Data Table]] for [[Figurine]] listings. Data is stored in the [[Special:CargoTables/%s|%s]] Cargo table for retrieval by [[Template:Figurines]].", CARGO_TABLE, CARGO_TABLE),
		usage = "See [[Template:Data Table]] for more information",
		format = "block",
		paramOrder = {"name", "game", "columns", "..."},
		params = {
			name = {
				type = "string",
				required = true,
				desc = "See the <code>name</code> parameter of [[Template:Data Table]].",
			},
			game = {
				type = "string",
				required = true,
				desc = "See the <code>game</code> parameter of [[Template:Data Table]].",
			},
			columns = {
				type = "string",
				desc = string.format("See the <code>columns</code> parameter of [[Template:Data Table]].<p>For [[Template:Figurines]] to function correctly, there must be columns named <code>%s</code>, <code>%s</code>, and <code>%s</code>.</p>", COLUMN_FIGURINE, COLUMN_SUBJECTS, COLUMN_DESCRIPTION),
			},
			["..."] = {
				name = "cells",
				placeholder = "cell",
				desc = "See the <code>cells</code> parameter of [[Template:Data Table]].",
			},
		}
	},
}

return p