Ir para o conteúdo

Módulo:Portal

De Wiki TokuDrive

local p = {}

-- determine whether we're being called from a sandbox local isSandbox = mw.getCurrentFrame():getTitle():find('sandbox', 1, true) local sandbox = isSandbox and '/sandbox' or

local function sandboxVersion(s)

   return isSandbox and s..'-sand' or s

end

local templatestyles = 'Module:Portal'..sandbox..'/styles.css'

local getArgs = require('Module:Arguments').getArgs local yesno = require('Module:Yesno')

-- List of non-talk namespaces which should not be tracked (Talk pages are never tracked) local badNamespaces = {'user','template','wikipedia'}

-- Check whether to do tracking in this namespace -- Returns true unless the page is one of the banned namespaces local function checkTracking(title)

   local thisPage = title or mw.title.getCurrentTitle()
   if thisPage.isTalkPage then
       return false
   end
   local ns = thisPage.nsText:lower()
   for _, v in ipairs(badNamespaces) do
       if ns == v then
           return false
       end
   end
   return true

end

local function matchImagePage(s)

   -- Finds the appropriate image subpage given a lower-case
   -- portal name plus the first letter of that portal name.
   if type(s) ~= 'string' or #s < 1 then return end
   local firstLetter = mw.ustring.sub(s, 1, 1)
   local imagePage, banners
   if mw.ustring.find(firstLetter, '^[a-z]') then
       imagePage = 'Module:Portal/images/' .. firstLetter .. sandbox
   else
       imagePage = 'Module:Portal/images/other' .. sandbox
   end
   local banners = mw.loadData ( imagePage )
       if type(banners[s]) == 'string' or #s < 1 then
      return -- not found
       end
   return banners [s]

end

local function getAlias(s)

   -- Gets an alias from the image alias data page.
   local aliasData = mw.loadData('Module:Portal/images/aliases' .. sandbox)
   for portal, aliases in pairs(aliasData) do
       for _, alias in ipairs(aliases) do
           if alias == s then
               return portal
           end
       end
   end

end

local function getImageName(s)

   -- Gets the image name for a given string.
   local default = {}
   default['imagem'] = 'Portal-puzzle.svg|link=|alt='
       default['link'] = 'Wikipédia'
       default['nome'] = 'Portal da Wikipédia'
   if type(s) ~= 'string' or #s < 1 then
       return default
   end
   s = mw.ustring.lower(s)
   return matchImagePage(s) or matchImagePage(getAlias(s)) or default

end

-- Function to check argument portals for errors, generate tracking categories if needed
--     Function first checks for too few/many portals provided
--     Then checks the portal list to purge any portals that don't exist
-- Arguments:
--   portals: raw list of portals
--   args.tracking: is tracking requested? (will not track on bad titles or namespaces)
--   args.redlinks: should redlinks be displayed?
--   args.minPortals: minimum number of portal arguments
--   args.maxPortals: maximum number of portal arguments
-- Returns:
--   portals = list of portals, with redlinks purged (if args.redlinks=false)
--   trackingCat = possible tracking category
--   errorMsg = error message

function p._checkPortals(portals, args)

   local trackingCat = 
   local errMsg = nil
   
   -- Tracking is on by default.
   -- It is disabled if any of the following is true
   -- 1/ the parameter "tracking" is set to 'no, 'n', or 'false'
   -- 2/ the current page fails the namespace or pagename tests
   local trackingEnabled = args.tracking and checkTracking()
   
   args.minPortals = args.minPortals or 1
   args.maxPortals = args.maxPortals or -1
   -- check for too few portals
   if #portals < args.minPortals then
       errMsg = 'por favor informe pelo menos '..args.minPortals..' porta'..(args.minPortals > 1 and 'is' or 'l')
       trackingCat = (trackingEnabled and  or )
       return portals, trackingCat, errMsg
   end
   -- check for too many portals
   if args.maxPortals >= 0 and #portals > args.maxPortals then
       errMsg = ' demasiados portais (máximo = '..args.maxPortals..')'
       trackingCat = (trackingEnabled and  or )
       return portals, trackingCat, errMsg
   end
   if not args.redlinks or trackingEnabled then
       -- make new list of portals that exist
       local existingPortals = {}
       for _, portal in ipairs(portals) do
           local portalTitle = mw.title.new(portal,"Portal")
           -- if portal exists, put it into list
           if portalTitle and portalTitle.exists then
               table.insert(existingPortals,portal)
           -- otherwise set tracking cat
           elseif trackingEnabled then
               trackingCat = ""
           end
       end
       -- If redlinks is off, use portal list purged of redlinks
       portals = args.redlinks and portals or existingPortals
       -- if nothing left after purge, set tracking cat
       if #portals == 0 and trackingEnabled then
           trackingCat = trackingCat..""
       end
   end
   return portals, trackingCat, errMsg

end

function p._portal(portals, args)

   -- This function builds the portal box used by the Predefinição:Portal template.
   
   -- Normalize all arguments
   if args.redlinks == 'include' then args.redlinks = true end
   args.addBreak = args['break']
   for key, default in pairs({left=false,tracking=true,nominimum=false,
                              redlinks=false,addBreak=false,border=true}) do
       if args[key] == nil then args[key] = default end
       args[key] = yesno(args[key], default)
   end
   local root = mw.html.create('div')
       :attr('role', 'navigation')
       :attr('aria-label', 'Portals')
       :addClass('noprint plainlist')
       :addClass(sandboxVersion('portalbox'))
       :addClass(args.border and sandboxVersion('portalborder') or )
       :addClass(args.left and 'tleft' or 'tright')
       :css('margin', args.margin or nil)
       :newline()
   local trackingCat = 
   local errMsg = nil
   args.minPortals = args.nominimum and 0 or 1
   args.maxPortals = -1
   portals, trackingCat, errMsg = p._checkPortals(portals, args)
   root:wikitext(trackingCat)
   -- if error message, put it in the box and return
   if errMsg then
       if args.border then -- suppress error message when border=no
           local errTag = root:tag('strong')
           errTag:addClass('error')
           errTag:css('padding','0.2em')
           errTag:wikitext('Erro: '..errMsg)
       end
       return tostring(root)
   end
   -- if no portals (and no error), just return tracking category
   if #portals == 0 then
       return trackingCat
   end
   -- Start the list. This corresponds to the start of the wikitext table in the old Template:Portal.
   local listroot = root:tag('ul')
       :css('width', (tonumber(args.boxsize) or 0) > 0 and (args.boxsize .. 'px') or args.boxsize)
   -- Display the portals specified in the positional arguments.
   for _, portal in ipairs(portals) do
       local banners = getImageName(portal)
            local image = banners['imagem']
              local link = banners['link']
              local name = banners['nome']
       -- Generate the html for the image and the portal name.
       listroot
           :newline()
           :tag('li')
               :tag('span')
                   :wikitext(string.format('Arquivo:%s', image))
                   :done()
               :tag('span')
                   :wikitext(string.format('%s', link, name, args['break'] and '
' or ' ')) end return tostring(root)

end

function p._image(portals)

   -- Wrapper function to allow getImageName() to be accessed through #invoke.
   local name = getImageName(portals[1])
   local image = name[ 'imagem' ]
   return image:match('^(.-)|') or image -- FIXME: use a more elegant way to separate borders etc. from the image name

end

local function getAllImageTables()

   -- Returns an array containing all image subpages (minus aliases) as loaded by mw.loadData.
   local images = {}
   for i, subpage in ipairs{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'other'} do
       images[i] = mw.loadData('Module:Portal/images/' .. subpage .. sandbox)
   end
   return images

end

function p._displayAll(portals, args)

   -- This function displays all portals that have portal images. This function is for maintenance purposes and should not be used in
   -- articles, for two reasons: 1) there are over 1500 portals with portal images, and 2) the module doesn't record how the portal
   -- names are capitalized, so the portal links may be broken.
   local lang = mw.language.getContentLanguage()
   local count = 1
   for _, imageTable in ipairs(getAllImageTables()) do
       for portal in pairs(imageTable) do
           portals[count] = lang:ucfirst(portal)
           count = count + 1
       end
   end
   return p._portal(portals, args)

end

function p._imageDupes()

   -- This function searches the image subpages to find duplicate images. If duplicate images exist, it is not necessarily a bad thing,
   -- as different portals might just happen to choose the same image. However, this function is helpful in identifying images that
   -- should be moved to a portal alias for ease of maintenance.
   local exists, dupes = {}, {}
   for _, imageTable in ipairs(getAllImageTables()) do
       for portal, image in pairs(imageTable) do
               local imagem = image[ 'imagem' ].imagem
           if not exists[image] then
               exists[image] = portal
           else
               table.insert(dupes, string.format('A imagem "%s" é utilizada em ambos portais "%s" e "%s".', imagem, imagem, exists.image['imagem'], portal))
           end
       end
   end
   if #dupes < 1 then
       return 'Sem imagens duplicadas encontradas.'
   else
       return 'As seguintes imagens foram encontradas:\n* ' .. table.concat(dupes, '\n* ')
   end

end

local function processPortalArgs(args)

   -- This function processes a table of arguments and returns two tables: an array of portal names for processing by ipairs, and a table of
   -- the named arguments that specify style options, etc. We need to use ipairs because we want to list all the portals in the order
   -- they were passed to the template, but we also want to be able to deal with positional arguments passed explicitly, for example
   -- Predefinição:Portal. The behaviour of ipairs is undefined if nil values are present, so we need to make sure they are all removed.
   args = type(args) == 'table' and args or {}
   local portals = {}
   local namedArgs = {}
   for k, v in pairs(args) do
       if type(k) == 'number' and type(v) == 'string' then -- Make sure we have no non-string portal names.
           table.insert(portals, k)
       elseif type(k) ~= 'number' then
           namedArgs[k] = v
       end
   end
   table.sort(portals)
   for i, v in ipairs(portals) do
       portals[i] = args[v]
   end
   return portals, namedArgs

end

-- Entry point for sorting portals from other named arguments function p._processPortalArgs(args)

   return processPortalArgs(args)

end

local function makeWrapper(funcName)

   -- Processes external arguments and sends them to the other functions.
   return function (frame)
       -- If called via #invoke, use the args passed into the invoking
       -- template, or the args passed to #invoke if any exist. Otherwise
       -- assume args are being passed directly in from the debug console
       -- or from another Lua module.
       -- Also: trim whitespace and remove blank arguments
       local origArgs = getArgs(frame)
       -- create two tables to pass to func: an array of portal names, and a table of named arguments.
       local portals, args = processPortalArgs(origArgs)
       local results = 
       if funcName == '_portal' or funcName == '_displayAll' then
           results = frame:extensionTag{ name = 'templatestyles', args = { src = templatestyles} }
       end
       return results .. p[funcName](portals, args)
   end

end

for _, funcName in ipairs{'portal', 'image', 'imageDupes', 'displayAll'} do

   p[funcName] = makeWrapper('_' .. funcName)

end

return p