Module:History

local cargo = mw.ext.cargo

local h = {} -- h for helper, just a non-exported table of functions so i can call a function before i actually define it

function h.doQuery(args) --this is all your code, i just put it in its own function for clarity local fieldstable = { "Versions.Version=Version", "Versions.ReleaseDate=ReleaseDate", "Versions._pageName=VPageName", "History.Patch=Patch", "History.Rev=Rev", "History._pageName=HPageName", }	local tables = 'Versions, History' local fields = table.concat(fieldstable,",") -- optional parameters are grouped in one table -- you can omit any or all of them, except joinOn if you use more than one table local cargoquery = { where = args.where, join='History.Patch = Versions.Version', orderBy='Versions.ReleaseDate DESC', }	return cargo.query( tables, fields, cargoquery ) end

function h.processResult(result) -- here we take the cargo data and process it to something usable -- we're gonna make an "ordered dictionary" - lua doesn't technically have this but we can -- approximate with something like -- {		val1, val2, val3, val4,		val1 = {},		val2 = {},		val3 = {},		val4 = {},		etc	} -- so we can do ipairs on val1, val2, etc (the values with integer indices) & then look up	-- data belonging to them when the value is the key -- obviously this breaks if one of the values is itself an integer but in this case we're fine local resultByPatches = {} -- resultByPatches is our ordered dict -- normally i would just call resultByPatches 'patches' but this seems clearer i guess for _, row in ipairs(result) do -- iterate through the result -- we only want one entry in resultByPatches per patch, so first check if we actually need to make anything new if not resultByPatches[row.Version] then -- if we do need something new, then we need to do two things -- first, append the patch in order -- second, create the table resultByPatches[row.Version] = { Patch = h.processPatch(row) } -- the structure of the table for each patch that I decided on is: -- {				changes1, changes2, changes3, etc,				Patch = display patch stuff			} -- this way we can later table.concat the changes into a single line resultByPatches[#resultByPatches+1] = row.Version -- and now we append the version to the order part end -- so now we KNOW that resultByPatches[row.Version] exists, and we can add the Rev data to it               local data = { revs = {}, xtable = {} } local revs = data.revs revs[#revs+1] = row.Rev resultByPatches[row.Version][#resultByPatches[row.Version]+1] = data end return resultByPatches end

function h.processPatch(row) -- i just made this its own function for clarity return ('%s %s'):format(row.VPageName, row.Version, row.ReleaseDate) end

function h.printTable(columns, resultByPatches) -- print the table local tbl = mw.html.create('table'):addClass('wikitable sortable mw-datatable') -- make header local tr = tbl:tag('tr') for _, v in ipairs(columns) do		if v then tbl:tag('th'):wikitext(v) end end --Construct the rows in the table for k, patch in ipairs(resultByPatches) do		-- this part is kinda sketch - we are technically processing the data in the printing part -- but i didn't want to iterate through the entire table another time prior to here -- just to construct this. that said, if this code gets ANY more complicated -- there should be another function h.processPatchesToOutput or something -- and we take care of this alongside anything else resultByPatches[patch].Changes = table.concat(resultByPatches[patch].data.revs, ' ') tr = tbl:tag("tr") -- make a new table row for _, v in ipairs(columns) do -- print each thing if v then -- but only if we actually want the column in question tbl:tag('td'):wikitext(resultByPatches[patch][v]) end end end return tbl -- yay we are done end

local p = {} function p.main( frame ) local args = frame.args -- you want your main function to be very barebones for a few reasons: -- * this makes it easier to read your code -- * this forces good design principles on you by forcing you to do your processing in order --  because otherwise you would have to return a billion different values & also send --  a billion different values to each function -- * modular design is super important to make code both clear & also maintainable local result = h.doQuery(args) if not next(result) then return args.default end -- this is a list of the columns you want in your table -- normally i would make this list then remove all empty entries in it in order to avoid -- using if statements in the table printing, but this wiki doesnt have all my util functions -- and im lazy local columns = { args.Patch ~= 'hide' and 'Patch', args.Changes ~= 'hide' and 'Changes' } local resultByPatches = h.processResult(result) return h.printTable(columns, resultByPatches) end return p