Module:Infobox Music

From the Tesseract Wiki, the wiki for all things Marvel Cinematic Universe
Jump to navigation Jump to search

Documentation for this module may be created at Module:Infobox Music/doc

-- <nowiki>
--------------------------
-- Module for [[Template:Infobox Music]]
-- Please test changes to this module at [[Module:Infobox Music/sandbox]] first
------------------------
local p = {}

local onmain = require('Module:Mainonly').on_main
local yesno = require('Module:Yesno')
-- local empty = require('Module:Paramtest').is_empty
local infobox = require('Module:Infobox')
local sortkeys = require('Module:Infobox Music/sortkeys')
local cleanimg = require('Module:Clean image').clean

function p.main(frame)
	local args = frame:getParent().args
	return p._main(args)
end

-- =p._main{name='Citadel XVI'}
function p._main(args)
	local ret = infobox.new(args)

	ret:defineParams{
		{ name = 'number', func = { name = numberarg, params = { 'number' }, flag = { 'p' } } },
		{ name = 'number_smw', func = { name = numbersmwarg, params = { 'number' }, flag = { 'p' } } },
		{ name = 'name', func = { name = namearg, params = { 'name', 'number' }, flag = { 'p', 'd' } } },
		{ name = 'file', func = { name = filearg, params = { 'file' }, flag = { 'p' } } },
		{ name = 'release', func = 'release' },
		{ name = 'album', func = 'has_content' },
		{ name = 'vocals', func = 'has_content' },
		{ name = 'instruments', func = 'has_content' },
		{ name = 'duration', func = { name = durationarg, params = { 'duration' }, flag = { 'p' } } },
		{ name = 'composer', func = 'has_content' },
		{ name = 'youtube', func = { name = youtubearg, params = { 'youtube' }, flag = { 'p' } } },
		{ name = 'downloads', func = { name = downloadsarg, params = { 'downloads' }, flag = { 'p' } } },
	}
	
	ret:useSMW({
		release = 'Release date'
	})

	ret:useSMWOne({
		number_smw = 'Music number'
	})
	
	ret:create()
	ret:cleanParams()
	
	ret:defineLinks({ links = {{ 'Template:%s/doc', 'Infobox' },
		{ 'Template_talk:%s', 'Talk page' }}, colspan = 2 })
		
	ret:defineName('Infobox Music')
	ret:addClass('infobox-music')
	
	-- Since the name is a combination of the track name and number,
	-- need to duplicate Module:Infobox's name-comparison logic here
	-- in order to set the 'no-parenthesis-style' if appropriate
	if args.name then
		if mw.text.decode(args.name) == mw.title.getCurrentTitle().fullText then
			ret:addClass('no-parenthesis-style')
		end
	end
	
	if onmain() then
		local a2 = ret:categoryData()
	end
	
	-- PARAMETER: name
	ret:addRow{
		{ tag = 'argh', content = 'name', class = 'infobox-header', colspan = '2',
			css = { ['border-bottom'] = '0' } } }
	
	-- PARAMETER: file
	if ret:paramDefined('file') then
		ret:addRow{
			{ tag = 'argh', content = 'file', class = 'infobox-image', colspan = '2',
				css = { ['text-align'] = 'center',
						['padding'] = '3px 0 0.2em 0',
						['border-right'] = '0'
					}
			} }
	end
	
	-- PARAMETER: release
	-- (update included automatically by infobox)
	ret:addRow{ { tag = 'th', content = '[[List of music by release date|Release]]' },
		{ tag = 'argd', content = 'release' } }

	-- PARAMETER: duration
	ret:addRow{
		{ tag = 'th', content = 'Duration' },
		{ tag = 'argd', content = 'duration' } }
	
	-- PARAMETER: album
	if ret:paramDefined('album') then
		ret:addRow{
			{ tag = 'th', content = 'Album' },
			{ tag = 'argd', content = 'album' } }
	end
	
	-- PARAMETER: vocals
	if ret:paramDefined('vocals') then
		ret:addRow{
			{ tag = 'th', content = 'Vocals' },
			{ tag = 'argd', content = 'vocals' } }
	end
	
	-- PARAMETER: instruments
	ret:addRow{
		{ tag = 'th', content = 'Instruments' },
		{ tag = 'argd', content = 'instruments' } }
	
	-- PARAMETER: composer
	ret:addRow{
		{ tag = 'th', content = 'Composer' },
		{ tag = 'argd', content = 'composer' } }
		
	-- PARAMETER: youtube
	if ret:paramDefined('youtube') then
		ret:addRow{
			{ tag = 'th', content = 'YouTube' },
			{ tag = 'argd', content = 'youtube' } }
	end
	
	-- PARAMETER: downloads
	if ret:paramDefined('downloads') then
		ret:addRow{
			{ tag = 'th', content = 'Downloads' },
			{ tag = 'argd', content = 'downloads' } }
	end
	
	ret:finish()
	if onmain() then
		-- Add a category sort key for music tracks that need it
		local name = args.name or string.match( ret:param('name', 'd'), '(.-)<span' )
		local sortkey = sortkeys[name]
		local defaultsort = sortkey and mw.getCurrentFrame():callParserFunction{ name = 'DEFAULTSORT', args = { sortkey } } or ''
		local a2 = ret:categoryData()
		ret:wikitext( defaultsort )
		ret:wikitext( addcategories( ret, a2 ) )
	end

	return ret:tostring()
	
end

function namearg(name, number)
	if not infobox.isDefined(name) then
		name = mw.title.getCurrentTitle().text
	end
	return name .. number
end

function numberarg(arg)
	if infobox.isDefined(arg) then
		if tonumber(arg) then
			return '<span style="font-size: 80%;"> (#' .. arg .. ')</span>'
		end
		if string.lower(arg) == 'n/a' or string.lower(arg) == 'no' then
			return ''
		end
	else
		return ''
	end
end

function numbersmwarg(arg)
	if infobox.isDefined(arg) and tonumber(arg) then
		return arg
	end
end

function filearg(arg)
	if string.match(arg, "(\.ogg)$") or string.match(arg, "(\.mp3)$") then
		frame = mw.getCurrentFrame()
		return frame:expandTemplate{ title = 'Listen inline', args = { filename = arg } }
	end
end

function membersarg(arg)
	return (string.lower(arg) == 'yes' and 'Yes') or (string.lower(arg) == 'no' and 'No') or nil
end

function durationarg(arg)
	if string.match(arg, "^(%d?%d:%d%d)$") then
		return arg
	end
end

function youtubearg(arg)
	_arg = string.gsub(arg, 'https?://www%.', 'https://')
	if string.match(_arg, "^https://youtube%.com[%l%d%-]*$") then
		return string.format('[%s Link]', arg)
	end
end

function downloadsarg(arg)
	if yesno(arg) then
		return 'Yes'
	end
	return 'No'
end

local composers = {
	['alan silvestri'] = 'Music composed by Alan Silvestri',
}

function addcategories( ibox, catargs )
	local args = ibox.args
	local ret = { 'Music tracks' }
	
	local cat_map = {
		-- Added if the parameter has content
		defined = {
			-- param = 'category',
		},
		-- Added if the parameter has no content
		notdefined = {
			number = 'Missing track number',
			file = 'Needs audio added',
			instruments = 'Needs instruments',
			duration = 'Needs track duration added',
			composer = 'Needs composer added',
		},
		notdefined_notscex = {
			release = 'Needs release date'
		}
	}
	
	if yesno( args.vocals ) then
		table.insert( ret, 'Music tracks with vocals' )
	end
	if yesno( args.downloads ) then
		table.insert( ret, 'Download-only music' )
	end
	if args.composer then
		local complist = string.lower( args.composer )
		local compcount = 0
		for name, cat in pairs( composers ) do
			if complist:find( name ) then
				table.insert( ret, cat )
				compcount = compcount + 1
			end
		end
		if compcount > 1 then
			table.insert( ret, 'Tracks with multiple composers' )
		end
	end

	-- Run and add mapped categories
	for n, v in pairs( cat_map.defined ) do
		if catargs[n] and catargs[n].one_defined then
			table.insert( ret, v )
		end
	end
	for n, v in pairs( cat_map.notdefined ) do
		if catargs[n] and catargs[n].all_defined == false then
			table.insert( ret, v )
		end
	end
	
	-- combine table and format category wikicode
	for i, v in ipairs( ret ) do
		if ( v ~= '' ) then
			ret[i] = string.format( '[[Category:%s]]', v )
		end
	end
	
	return table.concat( ret, '' )
end

return p