Module:Progress box

local makePurgeLink = require('Module:Purge')._mainlocal lang = mw.language.getContentLanguage()local CONFIG_MODULE = 'Module:Progress box/config'--------------------------------------------------------------------------------- Message mixin-- -- This function is mixed into all of the other classes-------------------------------------------------------------------------------local function message(self, key, ...)local msg = self._cfg[key]if not msg thenerror(string.format("no message found with key '%s'", tostring(key)), 2)endif select('#', ...) > 0 thenreturn mw.message.newRawMessage(msg, ...):plain()elsereturn msgendend--------------------------------------------------------------------------------- Category class-------------------------------------------------------------------------------local Category = {}Category.__index = CategoryCategory.message = messagefunction Category.new(data)local self = setmetatable({}, Category)self._cfg = data.cfgself._whatToCount = data.whatToCountself:setCategory(data.category)return selfendfunction Category:setCategory(category)self._category = categoryendfunction Category:getCategory()return self._categoryendfunction Category:makeCategoryLink(display)local cat = self:getCategory()display = display or catreturn string.format('[[:Category:%s|%s]]', cat, display)endfunction Category:getCount()if not self._count thenlocal counts = mw.site.stats.pagesInCategory(self:getCategory(), '*')self._count = counts[self._whatToCount or 'pages']if not self._count thenerror("the count type must be one of 'pages', 'subcats', 'files' or 'all'")endendreturn self._countendfunction Category:getFormattedCount()return lang:formatNum(self:getCount())endfunction Category:exists()return mw.title.makeTitle(14, self:getCategory()).existsend--------------------------------------------------------------------------------- DatedCategory class-- Inherits from Category-------------------------------------------------------------------------------local DatedCategory = {}DatedCategory.__index = DatedCategorysetmetatable(DatedCategory, Category)function DatedCategory.new(data)local self = setmetatable(Category.new(data), {__index = DatedCategory})self._date = data.dateself._dateFormat = data.dateFormat or self:message('date-format')self._formattedDate = self:formatDate(self._date)dolocal category = self:message('dated-category-format',data.baseCategory,self._formattedDate,data.from or self:message('dated-category-format-from'),data.suffix or '')category = category:match('^%s*(.-)%s*$') -- trim whitespaceself:setCategory(category)endreturn selfendfunction DatedCategory:formatDate(date)return lang:formatDate(self._dateFormat, date)endfunction DatedCategory:getDate()return self._dateendfunction DatedCategory:getFormattedDate()return self._formattedDateend--------------------------------------------------------------------------------- ProgressBox class-------------------------------------------------------------------------------local ProgressBox = {}ProgressBox.__index = ProgressBoxProgressBox.message = messagefunction ProgressBox.new(args, cfg, title)local self = setmetatable({}, ProgressBox)-- Argument defaultsargs = args or {}self._cfg = cfg or mw.loadData(CONFIG_MODULE)self._title = title or mw.title.getCurrentTitle()-- Set dataif not args.float or (args.float and (args.float == 'left' or args.float == '')) thenself._float_class = 'maint-cat-progress-left'elseif args.float == 'right' thenself._float_class = 'maint-cat-progress-right'elseif args.float == 'none' then-- 'none' is actually 'center'edself._float_class = 'maint-cat-progress-center'endself._header = args[1]self._frame = mw.getCurrentFrame()-- Make the base category objectif not args[1] thenerror('no base category specified', 3)endself._baseCategoryObj = Category.new{cfg = self._cfg,category = args[1],}-- Make datedCategory objectsself._datedCategories = {}dolocal cfg = self._cfglocal baseCategory = args[2] or self._baseCategoryObj:getCategory()local whatToCount = args.countlocal from = args.from or self:message('dated-category-format-from')local suffix = args.suffixlocal currentDate = lang:formatDate('Y-m')local date = self:findEarliestCategoryDate()local dateFormat = self:message('date-format')while date <= currentDate dolocal datedCategoryObj = DatedCategory.new{cfg = cfg,baseCategory = baseCategory,whatToCount = whatToCount,from = from,suffix = suffix,date = date,dateFormat = dateFormat,}if datedCategoryObj:getCount() > 0 thentable.insert(self._datedCategories, datedCategoryObj)enddate = ProgressBox.incrementDate(date)endend-- Make all-article category objectdolocal allCategoryif args[3] thenallCategory = args[3]elseallCategory = self:message('all-articles-category-format',self._baseCategoryObj:getCategory())allCategory = self._frame:preprocess(allCategory)endself._allCategoryObj = Category.new{cfg = self._cfg,category = allCategory,}endreturn selfend-- Increments a date in the format YYYY-MMfunction ProgressBox.incrementDate(date)local year, month = date:match('^(%d%d%d%d)%-(%d%d)$')year = tonumber(year)month = tonumber(month)if not year or not month thenerror(string.format("error parsing date '%s'", tostring(date)), 2)endmonth = month + 1if month > 12 thenmonth = 1year = year + 1endreturn string.format('%04d-%02d', year, month)endfunction ProgressBox:findEarliestCategoryDate()return self:message('start-date')endfunction ProgressBox:isCollapsed()return self._title.namespace ~= 10 -- is not in template namespaceendfunction ProgressBox:makeTotalLabel()local display = self:message('all-articles-label')if self._allCategoryObj:exists() thenreturn self._allCategoryObj:makeCategoryLink(display)elsereturn displayendendfunction ProgressBox:getTotalCount()local count = 0for i, obj in ipairs(self._datedCategories) docount = count + obj:getCount()endcount = count + self._baseCategoryObj:getCount()return countendfunction ProgressBox:getFormattedTotalCount()return lang:formatNum(self:getTotalCount())endfunction ProgressBox:__tostring()data = data or {}local root = mw.html.create('div')-- Base classes and stylesroot:addClass('maint-cat-progress'):addClass(self._float_class)-- Header rowroot:tag('div'):addClass('maint-cat-progress-header'):wikitext(self._header)-- Refresh rowroot:tag('div'):addClass('maint-cat-progress-refresh'):wikitext(makePurgeLink{self:message('purge-link-display')})-- Subtotalslocal subtotalTable = mw.html.create('table')subtotalTable:addClass('maint-cat-progress-subtotals mw-collapsible'):addClass(self:isCollapsed() and 'mw-collapsed' or nil):tag('caption'):wikitext(self:message('subtotal-heading'))for i, datedCategoryObj in ipairs(self._datedCategories) dosubtotalTable:tag('tr'):tag('td'):wikitext(datedCategoryObj:makeCategoryLink(datedCategoryObj:getFormattedDate())):done():tag('td'):wikitext(datedCategoryObj:getFormattedCount())end-- Undated articlessubtotalTable:tag('tr'):tag('td'):wikitext(self._baseCategoryObj:makeCategoryLink(self:message('undated-articles-label'))):done():tag('td'):wikitext(self._baseCategoryObj:getFormattedCount()):allDone()-- Totalroot:node(subtotalTable):tag('div'):addClass('maint-cat-progress-total-row'):tag('div'):addClass('maint-cat-progress-total-label'):wikitext(self:makeTotalLabel()):done():tag('div'):addClass('maint-cat-progress-total'):wikitext(self:getFormattedTotalCount())return mw.getCurrentFrame():extensionTag{name = 'templatestyles', args = {src = 'Module:Progress box/styles.css'}} .. tostring(root)end--------------------------------------------------------------------------------- Exports-------------------------------------------------------------------------------local p = {}function p._exportClasses()return {Category = Category,DatedCategory = DatedCategory,ProgressBox = ProgressBox,}endfunction p._main(args, cfg, title)return tostring(ProgressBox.new(args, cfg, title))endfunction p.main(frame)local args = require('Module:Arguments').getArgs(frame, {wrappers = 'Template:Progress box'})return p._main(args)endreturn p