Modulo:Bozza: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
m correggo
Etichetta: Annullato
codice riscritto e documentato
 
(24 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1:
--[[
require('Modulo:No globals')
* Modulo che implementa il template Bozza.
*
* Legge i template Richiesta revisione bozza presenti nel wikitesto della pagina e
* determina quali argomenti passare al sottotemplate Bozza/avviso.
]]
 
require('strict')
 
local p = {}
local getArgs = require('Module:Arguments').getArgs
 
-- =============================================================================
local function replace(str, pattern, replace)
-- Funzioni di utilità
local i, j = str:find(pattern, 1, true)
-- =============================================================================
str = str:sub(0, i - 1) .. replace .. str:sub(j + 1)
return str
end
 
local function getSubmissions(stored_submissions, text)
local new_text = text
 
for tmp in text:gmatch('%{(%b{})%}') do
local old_tmp = tmp
stored_submissions, tmp = getSubmissions(stored_submissions, tmp)
new_text = replace(new_text, old_tmp, tmp)
 
if tmp:find('^%{ *[Rr]ichiesta *revisione *bozza *[%|%}]') then
local submission = string.format('{%s}', tmp)
new_text = replace(new_text, submission, '')
tmp = tmp:gsub('%{%b{}%}', '{{')
 
-- Verifica se una data stringa contiene categorie da disabilitare e in tal caso
local ts = tmp:match('%| *ts *= *(%d%d%d%d%d%d%d%d%d%d%d%d%d%d) *[%|%}]')
-- restituisce la categoria di servizio pertinente in cui va inserita la pagina.
local key = tmp:find('%| *esito *= *[^%s%|%}]') and 'old' or 'current'
--
-- @param {string} str
-- @return {string}
local function checkForCategories(str)
for colonprefix
in str:gmatch('%[%[ *([Cc][Aa][Tt][Ee][Gg][Oo][Rr][YyIi][Aa]?) *: *[^%s][^\n]-%]%]')
do
local ns = mw.site.namespaces[colonprefix]
 
if type(stored_submissions[key][ts])ns and ns.canonicalName == 'tableCategory' then
return '[[Categoria:Bozze con categorie da disabilitare]]'
table.insert(stored_submissions[key][ts], submission)
else
stored_submissions[key][ts] = { submission }
end
end
end
 
return stored_submissions, new_text''
end
 
-- Restituisce un iteratore che consente di accedere agli elementi di una data
-- tabella in ordine decrescente delle sue chiavi.
-- Si assume che le chiavi della tabella siano valori timestamp.
--
-- @param {table} t
-- @return {function}
local function pairsByTimestamp(t)
local a = {}
local i = 0
local comp = function comp(ts1, ts2)
return ts1 > ts2
end
Line 50 ⟶ 52:
table.sort(a, comp)
 
returnlocal iter = function ()
i = i + 1
if not a[i] then
return
else
return a[i], t[a[i]], i
end
end
end
 
return iter
end
 
-- Restituisce una data stringa dopo aver rimosso i commenti <!-- ... -->,
function p.main(frame)
-- le porzioni di testo fra i tag nowiki e i template Categorie bozza.
local current_title = mw.title.getCurrentTitle()
--
-- @param {string} str
-- @return {string}
local function removeFalsePositives(str)
return str
:gsub('<!%-%-.-%-%->', '')
:gsub('<nowiki>.-</nowiki>', '')
:gsub('%{%{ *[Cc]ategorie *bozza *%|.-%}%}', '')
end
 
-- =============================================================================
if current_title.namespace == 0 then
-- classe Submission
return '[[Categoria:Rimuovere template Bozza]]'
-- =============================================================================
 
local Submission = {}
 
-- Costruttore della classe Submission.
--
-- @param {string} wikitext Wikitesto del template Richiesta revisione bozza
-- @return {table} self
function Submission:new(wikitext)
local self = {}
setmetatable(self, { __index = Submission })
 
-- elenco degli attributi privati
self._formattedDate = nil
self._reviewer = nil
self._status = nil
self._submitter = nil
self._ts = nil
self._wikitext = wikitext
 
return self
end
 
-- Espande il template Richiesta revisione bozza se la richiesta è stata già
-- evasa e restituisce il testo espanso.
--
-- @param {boolean} showInfoButton Determina se mostrare il pulsante
-- 'Chiedi chiarimenti' accanto all'esito dell'ultima richiesta di revisione
-- @return {string}
function Submission:expand(showInfoButton)
if self:getStatus() == 'pending' then return '' end
local wikitext = self._wikitext:gsub('%}%}$', '|mostra esito=x}}')
if showInfoButton then
wikitext = wikitext:gsub('%}%}$', '|mostra pulsante=x}}')
end
return mw.getCurrentFrame():preprocess(wikitext)
end
 
-- Restituisce la data formattata della richiesta di revisione.
local text = current_title:getContent()
--
-- @return {string}
function Submission:getFormattedDate()
if self:getTimestamp() and not self._formattedDate then
local lang = mw.language.getContentLanguage()
local success, jFY = pcall(lang.formatDate, lang, 'j F Y', self:getTimestamp())
if success then
self._formattedDate = jFY
end
end
return self._formattedDate
end
 
-- Restituisce il nome dell'utente che ha pubblicato l'esito.
if not text then return end
--
-- @return {string}
function Submission:getReviewer()
self._reviewer = self._reviewer or self:_parseArg('revisore', '.-') or
self:_parseArg('utente', '.-') -- temporaneo per rinomina parametro
return self._reviewer
end
 
-- Restituisce lo stato della richiesta di revisione (evasa o in sospeso).
text = text
--
:gsub('<!%-%-.-%-%->', '')
-- @return {string}
:gsub('<nowiki>.-</nowiki>', '')
function Submission:getStatus()
:gsub('%f[%{]%{%f[^%{]', '\r')
self._status = self._status or
:gsub('%{%{ *[Cc]ategorie *bozza *%|.-%}%}', '')
self._wikitext:find('%| *esito *= *[^%s%|%}]') and 'old' or 'pending'
return self._status
end
 
-- Restituisce il nome dell'utente che ha avanzato la richiesta di revisione.
local args = getArgs(frame, { parentOnly = true })
--
local lang = mw.language.getContentLanguage()
-- @return {string}
local state = lang:ucfirst(args[1] or '')
function Submission:getSubmitter()
local submissions = getSubmissions({ current = {}, old = {} }, text)
self._submitter = self._submitter or self:_parseArg('richiedente', '.-')
return self._submitter
end
 
-- Restituisce il timestamp della richiesta di revisione.
if state ~= 'S' then
--
if next(submissions.current) then
-- @return {string}
state = 'R'
function Submission:getTimestamp()
elseif next(submissions.old) and state ~= 'A' then
self._ts = self._ts or self:_parseArg('ts', '%d%d%d%d%d%d%d%d%d%d%d%d%d%d')
state = 'N'
return self._ts
end
 
-- Determina se la richiesta di revisione è valida.
--
-- @return {boolean}
function Submission:getValidity()
return self:getFormattedDate() and true or false
end
 
-- Parsifica un dato parametro del template Richiesta revisione bozza e
-- ne restituisce il valore.
--
-- @return {string}
function Submission:_parseArg(arg, subpattern)
local pattern = '%| *' .. arg .. ' *= *(' .. subpattern .. ') *[%|%}]'
return self._wikitext:match(pattern)
end
 
-- =============================================================================
-- classe SubmissionHistory
-- =============================================================================
 
local SubmissionHistory = {}
 
-- Costruttore della classe SubmissionHistory.
--
-- @param {table} submissions Array contenente tutte le richieste di revisione
-- della bozza già evase
-- @param {boolean} hideLastSubmission Determina se inserire anche l'esito dell'ultima
-- richiesta di revisione nel div compresso che contiene le richieste più vecchie
-- @param {boolean} showInfoButton Determina se mostrare il pulsante
-- 'Chiedi chiarimenti' accanto all'esito dell'ultima richiesta di revisione
-- @return {table} self
function SubmissionHistory:new(submissions, hideLastSubmission, showInfoButton)
local self = {}
setmetatable(self, { __index = SubmissionHistory })
 
-- elenco degli attributi privati
self._collapsedDiv = nil
self._header = nil
self._hideLastSubmission = hideLastSubmission
self._root = nil
self._showInfoButton = showInfoButton
self._submissionRows = {}
self._submissions = submissions
 
return self
end
 
-- Costruisce la cronologia di tutte le richieste di revisione della bozza già
-- evase e ne restituisce il codice HTML.
--
-- @return {string}
function SubmissionHistory:getHTML()
self
:_buildRoot()
:_buildHeader()
:_buildSubmissionRows()
:_buildCollapsedDiv()
:_appendChildNodes()
 
return tostring(self._root)
end
 
-- Appende tutti gli elementi della cronologia ai rispettivi elementi padre.
--
-- @return {table} self
function SubmissionHistory:_appendChildNodes()
if self._hideLastSubmission then
self._collapsedDiv:node(self._header)
else
self._root:node(self._header)
end
 
for i, row in ipairs(self._submissionRows) do
if i > (self._hideLastSubmission and 0 or 1) then
self._collapsedDiv:node(row)
else
self._root:node(row)
end
end
 
if self._collapsedDiv then
local history_table
self._root:node(self._collapsedDiv)
end
 
return self
if next(submissions.old) then
end
local styles = frame:extensionTag{
name = 'templatestyles',
args = { src = 'Modulo:Bozza/styles.css' }
}
 
-- Crea l'elemento div che mostra le richieste di revisione più vecchie,
history_table = mw.html.create('div')
-- qualora ve ne siano. È compresso di default.
:addClass('bozza-history')
--
:tag('div')
-- @return {table} self
:addClass('nomobile bozza-history-row bozza-history-header')
function SubmissionHistory:_buildCollapsedDiv()
:tag('div')
if #self._submissionRows >= (self._hideLastSubmission and 1 or 2) then
:wikitext('Data richiesta')
self._collapsedDiv = mw.html.create('div')
:done()
:addClass('nomobile mw-collapsible mw-collapsed')
:tag('div')
:attr('data-expandtext', 'mostra richieste precedenti')
:wikitext('Esito revisione')
:attr('data-collapsetext', 'nascondi richieste precedenti')
:done()
end
:done()
return self
end
 
-- Crea l'elemento div che costituisce l'header della cronologia.
local i = 0
--
local root = history_table
-- @return {table} self
function SubmissionHistory:_buildHeader()
self._header = mw.html.create('div')
:addClass('bozza-history-row nomobile bozza-history-header')
:tag('div')
:wikitext('Data richiesta')
:done()
:tag('div')
:wikitext('Esito revisione')
:done()
:done()
return self
end
 
-- Crea l'elemento div che costituisce la radice HTML della cronologia.
for ts, a in pairsByTimestamp(submissions.old) do
--
local success, jFY = pcall(lang.formatDate, lang, 'j F Y', ts)
-- @return {table} self
function SubmissionHistory:_buildRoot()
self._root = mw.html.create('div'):addClass('bozza-history')
return self
end
 
-- Crea un elemento div per ciascuna richiesta di revisione da inserire
if success then
-- nella cronologia.
i = i + 1
--
-- @return {table} self
function SubmissionHistory:_buildSubmissionRows()
for ts, submission, i in pairsByTimestamp(self._submissions) do
local row = mw.html.create('div')
:addClass('bozza-history-row')
:tag('div')
:wikitext(submission:getFormattedDate())
:done()
:tag('div')
:wikitext(submission:expand(i == 1 and self._showInfoButton))
:done()
:done()
table.insert(self._submissionRows, row)
end
return self
end
 
-- =============================================================================
if i == 2 then
-- Funzioni esportate
root = mw.html.create('div')
-- =============================================================================
:addClass('nomobile mw-collapsible mw-collapsed')
:attr('data-expandtext', 'mostra richieste precedenti')
:attr('data-collapsetext', 'nascondi richieste precedenti')
 
local p = {}
history_table:node(root)
end
 
-- Funzione per il template {{Bozza}}.
for _, submission in ipairs(a) do
function p.main(frame)
submission = submission:gsub('%}%}$', '|mostra esito=x}}')
local currentTitle = mw.title.getCurrentTitle()
local ns = currentTitle.namespace
local text = removeFalsePositives(currentTitle:getContent())
local args = getArgs(frame, { parentOnly = true })
local editedByReviewer = false
local revisionUser = frame:preprocess('{{REVISIONUSER}}')
local submissions = { pending = {}, old = {} }
 
-- cerca i template nel wikitesto della pagina dopo aver rimosso
root
-- temporaneamente le graffe { singole che causano falsi positivi
:tag('div')
for tmp in text:gsub('%f[%{]%{%f[^%{]', '\r'):gmatch('%{%b{}%}') do
:addClass('bozza-history-row')
-- scarta i template che non siano i template Richiesta revisione bozza
:tag('div')
if tmp:find('^%{%{ *[Rr]ichiesta *revisione *bozza *[%|%}]') then
:addClass(i == 1 and 'nomobile' or '')
-- ripristina le graffe { singole nella porzione di testo trovata e
:wikitext(jFY)
-- crea un oggetto Submission per ciascun template Richiesta revisione bozza
:done()
local submission = Submission:new(tmp:gsub('\r', '{'))
:tag('div')
-- scarta l'oggetto Submission se la richiesta di revisione è mal compilata
:wikitext(frame:preprocess(submission))
if submission:getValidity() == true then
:done()
submissions[submission:getStatus()][submission:getTimestamp()] = submission
:done()
if submission:getStatus() == 'old' then
-- mantiene il conto delle richieste di revisione già evase nel
-- parametro 'numero richieste respinte' del sottotemplate Bozza/avviso
local k = 'numero richieste respinte'
args[k] = args[k] and args[k] + 1 or 1
-- verifica se l'ultima modifica della pagina è stata fatta
-- da uno dei revisori
if not editedByReviewer then
editedByReviewer = revisionUser == submission:getReviewer()
end
end
end
end
end
 
local pendingSubmission = select(2, next(submissions.pending))
history_table = styles .. tostring(history_table)
 
-- conditional statement finalizzato a impostare lo stato (parametro
-- posizionale 1) del sottotemplate Bozza/avviso
if ns == 0 or ns == 118 then
if args.sposta then
args[1] = 'S'
elseif pendingSubmission then
args[1] = 'R'
-- se c'è una richiesta di revisione in sospeso, passa il suo timestamp e
-- il nome utente del richiedente al sottotemplate Bozza/avviso
if pendingSubmission:getSubmitter() then
args['ts ultima richiesta revisione'] = pendingSubmission:getTimestamp()
args['autore richiesta revisione'] = pendingSubmission:getSubmitter()
end
elseif args.proroga then
args[1] = 'A'
elseif next(submissions.old) then
args[1] = 'N'
else
args[1] = nil
end
else
args[1] = mw.language.getContentLanguage():ucfirst(args[1] or args.stato or '')
end
 
local hideLastSubmission = args[1] == 'S' or args[1] == 'R'
local ret = frame:expandTemplate{
title = 'Template:Bozza/avviso',
args = { state, ts = args.ts, ['cronologia revisioni'] = history_table }
}
 
if current_titlenext(submissions.namespace == 118old) then
-- determina se una bozza può essere sottoposta a revisione in base al
local catpattern = "[Cc][Aa][Tt][Ee][Gg][Oo][Rr][YyIi][Aa]?"
-- namespace in cui si trova la pagina e alla presenza di richieste inevase
local canBeSubmitted = ns == 118 and not hideLastSubmission
 
-- crea un oggetto SubmissionHistory che contiene la cronologie delle
for colonprefix in text:gmatch('%[%[ *(' .. catpattern .. ') *: *[^%s][^\n]-%]%]') do
-- richieste di revisione della bozza già evase e passa il suo codice HTML
local ns = mw.site.namespaces[colonprefix]
-- al sottotemplate Bozza/avviso
args['cronologia revisioni'] = SubmissionHistory
:new(submissions.old, hideLastSubmission, canBeSubmitted)
:getHTML()
 
-- passa il timestamp dell'ultima richiesta evasa al sottotemplate Bozza/avviso
if ns and ns.canonicalName == 'Category' then
if canBeSubmitted then
ret = ret .. '[[Categoria:Bozze con categorie da disabilitare]]'
local lastSubmission
for _, submission in pairsByTimestamp(submissions.old) do
lastSubmission = submission
break
end
args['ts ultima revisione'] = lastSubmission:getTimestamp()
end
end
 
-- controlla la visibilità del pulsante 'Richiedi revisione' che
return ret
-- viene creato dal sottotemplate Bozza/avviso
if ns ~= 118 or editedByReviewer or hideLastSubmission then
args['mostra pulsante'] = 'no'
else
args['mostra pulsante'] = 'sì'
end
 
return frame:extensionTag{
name = 'templatestyles',
args = { src = 'Modulo:Bozza/styles.css' }
} .. frame:expandTemplate{
title = 'Template:Bozza/avviso',
args = args
} .. (ns == 118 and checkForCategories(text) or '')
end