Modulo:Criteri cancellazione immediata
Aspetto
	
	
Questo è un modulo scritto in Lua. Le istruzioni che seguono sono contenute nella sottopagina Modulo:Criteri cancellazione immediata/man (modifica · cronologia)
Sandbox: Modulo:Criteri cancellazione immediata/sandbox (modifica · cronologia) · Sottopagine: lista · Test: Modulo:Criteri cancellazione immediata/test (modifica · cronologia · esegui)
Modulo che implementa i template {{Criterio cancellazione immediata}} e {{Criteri cancellazione immediata}}.
Ha una sottopagina di configurazione: Modulo:Criteri cancellazione immediata/Configurazione.json. Il file contiene l'elenco dei criteri di cancellazione immediata identificati dal rispettivo codice (C1, C2, ecc.). Per ciascun criterio si devono impostare le configurazioni di default; tutti i valori si possono poi reimpostare in modo diverso a seconda del namespace. Di seguito un esempio:
"Codice identificativo": {
	"default": {
		"ordine": 1,
		"link": "[[WP:C1|C1]]",
		"testi": {
			"messaggio di sistema": "testo",
			"definizione": "testo"
		},
		"validità": {
			"ns pari": true,
			"ns dispari": false
		}
	},
	"Nome namespace": {
		"testi": {
			"messaggio di sistema": "testo diverso da quello di default"
		}
	},
	"Altro namespace": {
		"validità": false
	}
}
Configurazioni di default
Le proprietà sono:
- ordine
 - Tipo: number
 - Descrizione: è l'ordine del criterio negli elenchi che genera il modulo. Se non diversamente specificato, è 0.
 - link
 - Tipo: string
 - Descrizione: è il link alla linea guida che riporta la definizione del criterio.
 - testi
 - Tipo: object
 - Descrizione: contiene i testi del criterio. Ha due proprietà, ovvero:
- messaggio di sistema
 - Tipo: string
 - Descrizione: è il testo che si può selezionare dall'elenco a discesa di Speciale:Cancella. Deve essere breve.
 - definizione
 - Tipo: string
 - Descrizione: è la definizione generica del criterio. Può essere di qualsiasi lunghezza.
 
 
- validità
 - Tipo: object
 - Descrizione: indica i tipi di namespace per i quali è valido il criterio. Ha due proprietà, ovvero:
- ns pari
 - Tipo: boolean
 - Descrizione: indica se il criterio è valido per i namespace con identificativo pari. Se non diversamente specificato, è true.
 - ns dispari
 - Tipo: boolean
 - Descrizione: indica se il criterio è valido per i namespace con identificativo dispari, ovvero quelli che contengono le pagine di discussione. Se non diversamente specificato, è true.
 
 
Configurazioni per namespace
Le proprietà sono tutte facoltative e sono:
- ordine
 - Tipo: number
 - Descrizione: è l'ordine del criterio negli elenchi che genera il modulo per il namespace.
 - link
 - Tipo: string
 - Descrizione: è il link alla linea guida che riporta la definizione del criterio per il namespace.
 - testi
 - Tipo: object
 - Descrizione: contiene i testi del criterio per il namespace. Ha due proprietà, ovvero:
- messaggio di sistema
 - Tipo: string
 - Descrizione: è il testo che si può selezionare dall'elenco a discesa di Speciale:Cancella per il namespace. Deve essere breve.
 - definizione
 - Tipo: string
 - Descrizione: è la definizione generica del criterio per il namespace. Può essere di qualsiasi lunghezza.
 
 
- validità
 - Tipo: boolean
 - Descrizione: indica se il criterio è valido per il namespace.
 
--[[
* Modulo che implementa i template {{Criterio cancellazione immediata}} e
* {{Criteri cancellazione immediata}}.
]]
require('strict')
-- Legge [[Modulo:Criteri cancellazione immediata/Configurazione.json]]
-- oppure [[Modulo:Criteri cancellazione immediata/sandbox/Configurazione.json]]
local cfg = mw.loadJsonData(mw.getCurrentFrame():getTitle() .. '/Configurazione.json')
local Enum = require('Modulo:Enum')
-- =============================================================================
--                           enum NamespaceType
-- =============================================================================
local NamespaceType = Enum:new('tipo ns', {
	ANY = {
		value = 'any'
	},
	EVEN = {
		value = 'ns pari'
	},
	ODD = {
		value = 'ns dispari'
	}
})
function NamespaceType:findByValue(value)
	return self:findBy('value', value)
end
-- =============================================================================
--                           enum Namespace
-- =============================================================================
local Namespace = Enum:new('ns', {
	DEFAULT = {
		id = 'default',
		type = NamespaceType.ANY,
		name = 'default'
	},
	PRINCIPALE = {
		id = 0,
		type = NamespaceType.EVEN,
		name = 'Principale'
	}
})
for _, ns in pairs(mw.site.namespaces) do
	if ns.id ~= 0 then
		rawset(Namespace, ns.name:gsub(' ', '_'):upper(), {
			id = ns.id,
			type = ns.id % 2 == 0 and NamespaceType.EVEN or NamespaceType.ODD,
			name = ns.name
		})
	end
end
function Namespace:findById(id)
	return self:findBy('id', tonumber(id))
end
function Namespace:findByName(name)
	return self:findBy('name', name)
end
-- =============================================================================
--                           enum ListType
-- =============================================================================
local ListType = Enum:new('tipo elenco', {
	DROPDOWN_LIST = {
		arg = 'a discesa',
		prefix = '**',
		section = setmetatable({
			[6] = '* Motivi comuni di cancellazione'
		}, {
			__index = function (t, key)
				return '* Cancellazione immediata'
			end
		})
	},
	BULLETED_LIST = {
		arg = 'puntato',
		prefix = '*',
		section = setmetatable({}, {
			__index = function (t, key)
				return ''
			end
		})
	}
})
function ListType:findByArg(arg)
	return self:findBy('arg', arg)
end
function ListType:getDefault()
	return self.DROPDOWN_LIST
end
-- =============================================================================
--                           enum TextType
-- =============================================================================
local TextType = Enum:new('tipo testo', {
	SYSTEM_MESSAGE = {
		arg = 'messaggio di sistema',
		get = 'getSystemMessage',
		set = 'setSystemMessage'
	},
	DEFINITION = {
		arg = 'definizione',
		get = 'getDefinition',
		set = 'setDefinition'
	}
})
function TextType:findByArg(arg)
	return self:findBy('arg', arg)
end
function TextType:getDefault()
	return self.SYSTEM_MESSAGE
end
-- =============================================================================
--                           classe Criterion
-- =============================================================================
local Criterion = {}
-- Costruttore della classe Criterion
function Criterion:new(code)
	local self = {}
	setmetatable(self, { __index = Criterion })
	self.code = code
	self.current_ns = Namespace.DEFAULT
	self.order = { default = 0 }
	self.add_link = false
	self.link = { default = string.format('[[WP:IMMEDIATA|%s]]', code) }
	self.system_message = { default = '' }
	self.definition = { default = '' }
	self.validity = { default = true }
	return self
end
function Criterion:getCode()
	return self.code
end
function Criterion:getOrder()
	return self.order[self.current_ns.id] or self.order.default
end
function Criterion:getLink()
	return self.link[self.current_ns.id] or self.link.default
end
function Criterion:getSystemMessage()
	return string.format('(%s) %s',
		self.add_link and self:getLink() or self:getCode(),
		self.system_message[self.current_ns.id] or self.system_message.default)
end
function Criterion:getDefinition()
	return string.format('(%s) %s',
		self.add_link and self:getLink() or self:getCode(),
		self.definition[self.current_ns.id] or self.definition.default)
end
function Criterion:isValid()
	if self.validity[self.current_ns.id] ~= nil then
		return self.validity[self.current_ns.id]
	elseif self.validity[self.current_ns.type.value] ~= nil then
		return self.validity[self.current_ns.type.value]
	else
		return self.validity.default
	end
end
function Criterion:setCurrentNs(ns)
	self.current_ns = ns
	return self
end
function Criterion:setOrder(order)
	self.order[self.current_ns.id] = order
	return self
end
function Criterion:setAddLink(add_link)
	self.add_link = add_link
	return self
end
function Criterion:setLink(link)
	self.link[self.current_ns.id] = link
	return self
end
function Criterion:setSystemMessage(text)
	self.system_message[self.current_ns.id] = text
	return self
end
function Criterion:setDefinition(text)
	self.definition[self.current_ns.id] = text
	return self
end
function Criterion:setValid(valid)
	self.validity[self.current_ns.id] = valid
	return self
end
function Criterion:setValidForNsType(valid, ns_type)
	self.validity[ns_type.value] = valid
	return self
end
-- =============================================================================
--                            Funzioni di utilità
-- =============================================================================
local function to_criterion(criterion_code, criterion_cfg)
	local criterion = Criterion:new(criterion_code)
	for ns, props in pairs(criterion_cfg) do
		ns = Namespace:findByName(ns)
		if ns and type(props) == 'table' then
			criterion:setCurrentNs(ns)
			if type(props.ordine) == 'number' then
				criterion:setOrder(props.ordine)
			end
			if type(props.link) == 'string' then
				criterion:setLink(props.link)
			end
			if type(props.testi) == 'table' then
				for text_type, text in pairs(props.testi) do
					text_type = TextType:findByArg(text_type)
					if text_type then
						criterion[text_type.set](criterion, text)
					end
				end
			end
			if ns == Namespace.DEFAULT then
				if type(props['validità']) == 'table' then
					for ns_type, valid in pairs(props['validità']) do
						ns_type = NamespaceType:findByValue(ns_type)
						if ns_type and type(valid) == 'boolean' then
							criterion:setValidForNsType(valid, ns_type)
						end
					end
				end
			elseif type(props['validità']) == 'boolean' then
				criterion:setValid(props['validità'])
			end
		end
	end
	return criterion
end
local function compare_criteria(a, b)
	if a:getOrder() == b:getOrder() then
		return a:getCode() < b:getCode()
	else
		return a:getOrder() < b:getOrder()
	end
end
local function get_suppressed_criteria(arg)
	local suppressed_criteria = setmetatable({}, {
		__index = function (t, key)
			return false
		end
	})
	if arg then
		for criterion_code in string.gmatch(arg, '[%s,]*([^,]*[^%s,])') do
			suppressed_criteria[criterion_code] = true
		end
	end
	return suppressed_criteria
end
local function get_args(frame)
	local args = require('Module:Arguments').getArgs(frame, { parentOnly = true })
	if args[1] and args.criterio == nil then
		args.criterio, args[1] = args[1], nil
	end
	args.ns = Namespace:findByName(args.ns) or Namespace:findById(args.ns) or Namespace.DEFAULT
	args['tipo elenco'] = ListType:findByArg(args['tipo elenco']) or ListType:getDefault()
	args['tipo testo'] = TextType:findByArg(args['tipo testo']) or TextType:getDefault()
	args.link = args.link ~= 'no' and true or false
	args.ancore = (args.ancore == 'sì' or args.ancore == 'si') and true or false
	args['escludi criteri'] = get_suppressed_criteria(args['escludi criteri'])
	return args
end
-- =============================================================================
--                            Funzioni esportate
-- =============================================================================
local p = {}
function p.get_default_value(frame)
	local param = mw.text.trim(frame.args[1] or '')
	if Enum[param] and Enum[param].getDefault and Enum[param]:getDefault().arg then
		return string.format('"%s"', Enum[param]:getDefault().arg)
	end
end
function p.list_possible_values(frame)
	local param = mw.text.trim(frame.args[1] or '')
	local possible_values = {}
	if Enum[param] then
		for _, constant in pairs(Enum[param]) do
			if constant.arg then
				table.insert(possible_values, string.format('"%s"', constant.arg))
			end
		end
	end
	return table.concat(possible_values, ', ')
end
function p.get_criterion(frame)
	local args = get_args(frame)
	local text_type = args['tipo testo']
	local ns, criterion_code, add_link = args.ns, args.criterio, args.link
	if criterion_code and cfg[criterion_code] then
		local criterion = to_criterion(criterion_code, cfg[criterion_code])
		criterion:setCurrentNs(ns):setAddLink(add_link)
		if criterion:isValid() then
			return criterion[text_type.get](criterion)
		end
	end
end
function p.list_criteria(frame)
	local args = get_args(frame)
	local list_type, text_type = args['tipo elenco'], args['tipo testo']
	local ns, add_anchor, add_link = args.ns, args.ancore, args.link
	local suppressed_criteria = args['escludi criteri']
	local list = list_type.section[ns.id]
	local valid_criteria = {}
	for criterion_code, criterion_cfg in pairs(cfg) do
		local criterion = to_criterion(criterion_code, criterion_cfg)
		criterion:setCurrentNs(ns):setAddLink(add_link)
		if criterion:isValid() and suppressed_criteria[criterion:getCode()] == false then
			table.insert(valid_criteria, criterion)
		end
	end
	table.sort(valid_criteria, compare_criteria)
	for _, criterion in ipairs(valid_criteria) do
		list = string.format('%s\n%s ', list, list_type.prefix)
		if add_anchor then
			list = string.format('%s<span id=%s></span>', list, criterion:getCode())
		end
		list = list .. criterion[text_type.get](criterion)
	end
	return mw.text.trim(list)
end
return p