Permanently protected module
From Wikipedia, the free encyclopedia


local makePurgeLink = require('Module:Purge')._main

local 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._cfgkey

	if not msg then

		error(string.format("no message found with key '%s'", tostring(key)), 2)

	end

	if select('#', ...) > 0 then

		return mw.message.newRawMessage(msg, ...):plain()

	else

		return msg

	end

end



-------------------------------------------------------------------------------

-- Category class

-------------------------------------------------------------------------------



local Category = {}

Category.__index = Category

Category.message = message



function Category.new(data)

	local self = setmetatable({}, Category)

	self._cfg = data.cfg

	self._whatToCount = data.whatToCount

	self:setCategory(data.category)

	return self

end



function Category:setCategory(category)

	self._category = category

end



function Category:getCategory()

	return self._category

end



function Category:makeCategoryLink(display)

	local cat = self:getCategory()

	display = display or cat

	return string.format('[[:Category:%s|%s]]', cat, display)

end



function Category:getCount()

	if not self._count then

		local counts = mw.site.stats.pagesInCategory(self:getCategory(), '*')

		self._count = countsself._whatToCount or 'pages'

		if not self._count then

			error("the count type must be one of 'pages', 'subcats', 'files' or 'all'")

		end

	end

	return self._count

end



function Category:getFormattedCount()

	return lang:formatNum(self:getCount())

end



function Category:exists()

	return mw.title.makeTitle(14, self:getCategory()).exists

end



-------------------------------------------------------------------------------

-- DatedCategory class

-- Inherits from Category

-------------------------------------------------------------------------------



local DatedCategory = {}

DatedCategory.__index = DatedCategory

setmetatable(DatedCategory, Category)



function DatedCategory.new(data)

	local self = setmetatable(Category.new(data), {__index = DatedCategory})

	self._date = data.date

	self._dateFormat = data.dateFormat or self:message('date-format')

	self._formattedDate = self:formatDate(self._date)

	do

		local 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 whitespace

		self:setCategory(category)

	end

	return self

end



function DatedCategory:formatDate(date)

	return lang:formatDate(self._dateFormat, date)

end



function DatedCategory:getDate()

	return self._date

end



function DatedCategory:getFormattedDate()

	return self._formattedDate

end



-------------------------------------------------------------------------------

-- ProgressBox class

-------------------------------------------------------------------------------



local ProgressBox = {}

ProgressBox.__index = ProgressBox

ProgressBox.message = message



function ProgressBox.new(args, cfg, title)

	local self = setmetatable({}, ProgressBox)



	-- Argument defaults

	args = args or {}

	self._cfg = cfg or mw.loadData(CONFIG_MODULE)

	self._title = title or mw.title.getCurrentTitle()



	-- Set data

	if not args.float or (args.float and (args.float == 'left' or args.float == '')) then

		self._float_class = 'maint-cat-progress-left'

	elseif args.float == 'right' then

		self._float_class = 'maint-cat-progress-right'

	elseif args.float == 'none' then

		-- 'none' is actually 'center'ed

		self._float_class = 'maint-cat-progress-center'

	end

	

	self._header = args1

	self._frame = mw.getCurrentFrame()



	-- Make the base category object

	if not args1 then

		error('no base category specified', 3)

	end

	self._baseCategoryObj = Category.new{

		cfg = self._cfg,

		category = args1],

	}



	-- Make datedCategory objects

	self._datedCategories = {}

	do

		local cfg = self._cfg

		local baseCategory = args2 or self._baseCategoryObj:getCategory()

		local whatToCount = args.count

		local from = args.from or self:message('dated-category-format-from')

		local suffix = args.suffix

		local currentDate = lang:formatDate('Y-m')

		local date = self:findEarliestCategoryDate()

		local dateFormat = self:message('date-format')

		while date <= currentDate do

			local datedCategoryObj = DatedCategory.new{

				cfg = cfg,

				baseCategory = baseCategory,

				whatToCount = whatToCount,

				from = from,

				suffix = suffix,

				date = date,

				dateFormat = dateFormat,

			}

			if datedCategoryObj:getCount() > 0 then

				table.insert(self._datedCategories, datedCategoryObj)

			end

			date = ProgressBox.incrementDate(date)

		end

	end



	-- Make all-article category object

	do

		local allCategory

		if args3 then

			allCategory = args3

		else

			allCategory = self:message(

				'all-articles-category-format',

				self._baseCategoryObj:getCategory()

			)

			allCategory = self._frame:preprocess(allCategory)

		end

		self._allCategoryObj = Category.new{

			cfg = self._cfg,

			category = allCategory,

		}

	end



	return self

end



-- Increments a date in the format YYYY-MM

function 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 then

		error(string.format("error parsing date '%s'", tostring(date)), 2)

	end

	month = month + 1

	if month > 12 then

		month = 1

		year = year + 1

	end

	return string.format('%04d-%02d', year, month)

end



function ProgressBox:findEarliestCategoryDate()

	return self:message('start-date')

end



function ProgressBox:isCollapsed()

	return self._title.namespace ~= 10 -- is not in template namespace

end



function ProgressBox:makeTotalLabel()

	local display = self:message('all-articles-label')

	if self._allCategoryObj:exists() then

		return self._allCategoryObj:makeCategoryLink(display)

	else

		return display

	end

end



function ProgressBox:getTotalCount()

	local count = 0

	for i, obj in ipairs(self._datedCategories) do

		count = count + obj:getCount()

	end

	count = count + self._baseCategoryObj:getCount()

	return count

end



function ProgressBox:getFormattedTotalCount()

	return lang:formatNum(self:getTotalCount())

end



function ProgressBox:__tostring()

	data = data or {}

	local root = mw.html.create('div')

	

	-- Base classes and styles

	root

		:addClass('maint-cat-progress')

		:addClass(self._float_class)



	-- Header row

	root:tag('div')

		:addClass('maint-cat-progress-header')

		:wikitext(self._header)



	-- Refresh row

	root:tag('div')

		:addClass('maint-cat-progress-refresh')

		:wikitext(makePurgeLink{self:message('purge-link-display')})



	-- Subtotals

	local 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) do

		subtotalTable

			:tag('tr')

				:tag('td')

					:wikitext(datedCategoryObj:makeCategoryLink(

						datedCategoryObj:getFormattedDate()

					))

					:done()

				:tag('td')

					:wikitext(datedCategoryObj:getFormattedCount())

	end



	-- Undated articles

	subtotalTable

		:tag('tr')

			:tag('td')

				:wikitext(self._baseCategoryObj:makeCategoryLink(

					self:message('undated-articles-label')

				))

				:done()

			:tag('td')

				:wikitext(self._baseCategoryObj:getFormattedCount())

				:allDone()



	-- Total

	root

		: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,

	}

end



function p._main(args, cfg, title)

	return tostring(ProgressBox.new(args, cfg, title))

end



function p.main(frame)

	local args = require('Module:Arguments').getArgs(frame, {

		wrappers = 'Template:Progress box'

	})

	return p._main(args)

end



return p
Permanently protected module
From Wikipedia, the free encyclopedia


local makePurgeLink = require('Module:Purge')._main

local 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._cfgkey

	if not msg then

		error(string.format("no message found with key '%s'", tostring(key)), 2)

	end

	if select('#', ...) > 0 then

		return mw.message.newRawMessage(msg, ...):plain()

	else

		return msg

	end

end



-------------------------------------------------------------------------------

-- Category class

-------------------------------------------------------------------------------



local Category = {}

Category.__index = Category

Category.message = message



function Category.new(data)

	local self = setmetatable({}, Category)

	self._cfg = data.cfg

	self._whatToCount = data.whatToCount

	self:setCategory(data.category)

	return self

end



function Category:setCategory(category)

	self._category = category

end



function Category:getCategory()

	return self._category

end



function Category:makeCategoryLink(display)

	local cat = self:getCategory()

	display = display or cat

	return string.format('[[:Category:%s|%s]]', cat, display)

end



function Category:getCount()

	if not self._count then

		local counts = mw.site.stats.pagesInCategory(self:getCategory(), '*')

		self._count = countsself._whatToCount or 'pages'

		if not self._count then

			error("the count type must be one of 'pages', 'subcats', 'files' or 'all'")

		end

	end

	return self._count

end



function Category:getFormattedCount()

	return lang:formatNum(self:getCount())

end



function Category:exists()

	return mw.title.makeTitle(14, self:getCategory()).exists

end



-------------------------------------------------------------------------------

-- DatedCategory class

-- Inherits from Category

-------------------------------------------------------------------------------



local DatedCategory = {}

DatedCategory.__index = DatedCategory

setmetatable(DatedCategory, Category)



function DatedCategory.new(data)

	local self = setmetatable(Category.new(data), {__index = DatedCategory})

	self._date = data.date

	self._dateFormat = data.dateFormat or self:message('date-format')

	self._formattedDate = self:formatDate(self._date)

	do

		local 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 whitespace

		self:setCategory(category)

	end

	return self

end



function DatedCategory:formatDate(date)

	return lang:formatDate(self._dateFormat, date)

end



function DatedCategory:getDate()

	return self._date

end



function DatedCategory:getFormattedDate()

	return self._formattedDate

end



-------------------------------------------------------------------------------

-- ProgressBox class

-------------------------------------------------------------------------------



local ProgressBox = {}

ProgressBox.__index = ProgressBox

ProgressBox.message = message



function ProgressBox.new(args, cfg, title)

	local self = setmetatable({}, ProgressBox)



	-- Argument defaults

	args = args or {}

	self._cfg = cfg or mw.loadData(CONFIG_MODULE)

	self._title = title or mw.title.getCurrentTitle()



	-- Set data

	if not args.float or (args.float and (args.float == 'left' or args.float == '')) then

		self._float_class = 'maint-cat-progress-left'

	elseif args.float == 'right' then

		self._float_class = 'maint-cat-progress-right'

	elseif args.float == 'none' then

		-- 'none' is actually 'center'ed

		self._float_class = 'maint-cat-progress-center'

	end

	

	self._header = args1

	self._frame = mw.getCurrentFrame()



	-- Make the base category object

	if not args1 then

		error('no base category specified', 3)

	end

	self._baseCategoryObj = Category.new{

		cfg = self._cfg,

		category = args1],

	}



	-- Make datedCategory objects

	self._datedCategories = {}

	do

		local cfg = self._cfg

		local baseCategory = args2 or self._baseCategoryObj:getCategory()

		local whatToCount = args.count

		local from = args.from or self:message('dated-category-format-from')

		local suffix = args.suffix

		local currentDate = lang:formatDate('Y-m')

		local date = self:findEarliestCategoryDate()

		local dateFormat = self:message('date-format')

		while date <= currentDate do

			local datedCategoryObj = DatedCategory.new{

				cfg = cfg,

				baseCategory = baseCategory,

				whatToCount = whatToCount,

				from = from,

				suffix = suffix,

				date = date,

				dateFormat = dateFormat,

			}

			if datedCategoryObj:getCount() > 0 then

				table.insert(self._datedCategories, datedCategoryObj)

			end

			date = ProgressBox.incrementDate(date)

		end

	end



	-- Make all-article category object

	do

		local allCategory

		if args3 then

			allCategory = args3

		else

			allCategory = self:message(

				'all-articles-category-format',

				self._baseCategoryObj:getCategory()

			)

			allCategory = self._frame:preprocess(allCategory)

		end

		self._allCategoryObj = Category.new{

			cfg = self._cfg,

			category = allCategory,

		}

	end



	return self

end



-- Increments a date in the format YYYY-MM

function 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 then

		error(string.format("error parsing date '%s'", tostring(date)), 2)

	end

	month = month + 1

	if month > 12 then

		month = 1

		year = year + 1

	end

	return string.format('%04d-%02d', year, month)

end



function ProgressBox:findEarliestCategoryDate()

	return self:message('start-date')

end



function ProgressBox:isCollapsed()

	return self._title.namespace ~= 10 -- is not in template namespace

end



function ProgressBox:makeTotalLabel()

	local display = self:message('all-articles-label')

	if self._allCategoryObj:exists() then

		return self._allCategoryObj:makeCategoryLink(display)

	else

		return display

	end

end



function ProgressBox:getTotalCount()

	local count = 0

	for i, obj in ipairs(self._datedCategories) do

		count = count + obj:getCount()

	end

	count = count + self._baseCategoryObj:getCount()

	return count

end



function ProgressBox:getFormattedTotalCount()

	return lang:formatNum(self:getTotalCount())

end



function ProgressBox:__tostring()

	data = data or {}

	local root = mw.html.create('div')

	

	-- Base classes and styles

	root

		:addClass('maint-cat-progress')

		:addClass(self._float_class)



	-- Header row

	root:tag('div')

		:addClass('maint-cat-progress-header')

		:wikitext(self._header)



	-- Refresh row

	root:tag('div')

		:addClass('maint-cat-progress-refresh')

		:wikitext(makePurgeLink{self:message('purge-link-display')})



	-- Subtotals

	local 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) do

		subtotalTable

			:tag('tr')

				:tag('td')

					:wikitext(datedCategoryObj:makeCategoryLink(

						datedCategoryObj:getFormattedDate()

					))

					:done()

				:tag('td')

					:wikitext(datedCategoryObj:getFormattedCount())

	end



	-- Undated articles

	subtotalTable

		:tag('tr')

			:tag('td')

				:wikitext(self._baseCategoryObj:makeCategoryLink(

					self:message('undated-articles-label')

				))

				:done()

			:tag('td')

				:wikitext(self._baseCategoryObj:getFormattedCount())

				:allDone()



	-- Total

	root

		: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,

	}

end



function p._main(args, cfg, title)

	return tostring(ProgressBox.new(args, cfg, title))

end



function p.main(frame)

	local args = require('Module:Arguments').getArgs(frame, {

		wrappers = 'Template:Progress box'

	})

	return p._main(args)

end



return p

Videos

Youtube | Vimeo | Bing

Websites

Google | Yahoo | Bing

Encyclopedia

Google | Yahoo | Bing

Facebook