Module:Film song

From Wikisource
Jump to navigation Jump to search

require('strict')

-- Module:Film_song
local p = {}

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

local function getEditionNumber(QID)
    if not QID then
        return nil
    end
    
    local editionNumber = mw.wikibase.getEntity(QID):getBestStatements('P393')[1]
    if editionNumber then
        return editionNumber.mainsnak.datavalue.value
    else
        return nil
    end
end

local function getWorkItem(QID)
    -- Fetch the entity data for the given QID
    local entity = mw.wikibase.getEntity(QID)
    if not entity then
        return nil, 'No entity found for ' .. QID
    end
    
    -- Access the 'recording or performance of' property (P629) directly
    local recordingOrPerformance = entity.claims['P2550']
    if not recordingOrPerformance or #recordingOrPerformance == 0 then
    	recordingOrPerformance = entity.claims['P629']
    end
    if not recordingOrPerformance or #recordingOrPerformance == 0 then
        return nil, 'No "edition or translation of" or "recording or performance of" property found for ' .. QID
    end
    
    -- Extract the QID of the work item
    local workQID = recordingOrPerformance[1].mainsnak.datavalue.value.id
    if not workQID then
        return nil, 'No work QID found for ' .. QID
    end
    
    return workQID
end

local function getVersionItemLabel(args)
    local QID = args[1]
    local template = args[2] or "" -- Added to handle different situations
    
    if not QID then
        return 'Error: No Wikidata item specified'
    end
    
    local versionItemLabel = mw.wikibase.getLabel(QID)
    if not versionItemLabel or versionItemLabel == '' then
        versionItemLabel = 'Item ' .. QID -- Fallback text if no label is found
    end
    
    -- Check for edition number and append to the label if necessary
    if template == "anchor" then
        local editionNumber = getEditionNumber(QID)
        if editionNumber then
            versionItemLabel = mw.uri.anchorEncode(versionItemLabel .. "_rendition_" .. editionNumber)
        end
    end
    
    return versionItemLabel
end

local function getLink(args)
    local QID = args[1]
    local template = args[2] or "" -- Assign default value within the function

    if not QID then
        return error_message({'[[Module:Film song]] error: no Wikidata item specified'})
    end
    
    local workQID, err = getWorkItem(QID)
    if err then
        return err
    end
    
    local versionItemLabel = getVersionItemLabel(args)
    local editionNumber = getEditionNumber(QID)
    local versionItemNonTemplateLabel = "" -- for later logic
    
    if editionNumber and not template then
    	versionItemLabel = versionItemLabel .. " (rendition " .. editionNumber .. ")"
	end

	if template ~= "" then
        local versionItemAnchor = versionItemLabel:gsub(" ", "_")
        local pageTitle = mw.title.getCurrentTitle().text
        if editionNumber then
            versionItemAnchor = mw.uri.anchorEncode(versionItemAnchor .. "_rendition_" .. editionNumber)
            versionItemLabel = versionItemLabel .. " (rendition " .. editionNumber .. ")"
        end
        return mw.ustring.format('[[%s#%s|%s]]', pageTitle, versionItemAnchor, versionItemLabel)
    -- else
    -- 	if versionItemNonTemplateLabel then
    -- 		versionItemLabel = versionItemNonTemplateLabel
    -- 	end
	end

    local sitelink = mw.wikibase.getSitelink(workQID, 'enwikisource')
    if not sitelink then
        return versionItemLabel
    end
	
		
    return mw.ustring.format('[[%s|%s]]', sitelink, versionItemLabel)
end

function p._film_song_link(args)
	if not args[1] then
		return error_message({'[[Module:Film song]] error: no Wikidata item specified'})
	end
	
	local link = mw.html.create('div'):addClass('wst-film-song-link')
	
	local anchor = getVersionItemLabel({args[1], 'anchor'})
	link:attr('id', anchor)
	
	local link_text = getLink({args[1]})
	link:wikitext('Song: "' .. link_text .. '" ([[File:Wikidata-logo.svg|15px|link=d:' .. args[1] .. ']])')
	
	return tostring(link)
end

function p._film_song_link_table(args)
	if not args[1] then
		return error_message({'[[Module:Film song]] error: no Wikidata item specified'})
	end
	return '"' .. getLink({args[1], 'table'}) .. '" ([[File:Wikidata-logo.svg|15px|link=d:' .. args[1] .. ']])'
end

-- Function to generate the list of songs
function p._film_song_list(args)
	local currentPageQID = args[1] or mw.wikibase.getEntityIdForCurrentPage()
    -- Check if entity is nil or if entity does not have claims
    -- (if this is the case this should be fixed on Wikidata, but shouldn't cause a public error on Wikisource)
    if not currentPageQID then
        return ''
    end
    
    local entity = mw.wikibase.getEntity(currentPageQID)
    -- Check if entity exists and has the 'has part(s)' property (P527)
    if not entity or not entity.claims or not entity.claims['P527'] then
        return ''
    end
    
    local parts = entity.claims['P527']
    local list = {}
    
    for _, part in ipairs(parts) do
        local partQID = part.mainsnak.datavalue.value.id
        local partEntity = mw.wikibase.getEntity(partQID)
        local performerQID = partEntity and partEntity.claims['P175'] and partEntity.claims['P175'][1].mainsnak.datavalue.value.id or nil
        local performerPage = performerQID and mw.wikibase.getSitelink(performerQID, 'enwikisource') or nil
        local performerName = performerPage and mw.ustring.gsub(performerPage, "Author:", "") or "Unknown"
        
        -- Expand the 'film song link table' template for each song part
        local songLinkTable = p._film_song_link_table({partQID})
        
        -- Ensure performer name has no leading or trailing whitespace
        performerName = mw.text.trim(performerName)
        
        -- Construct the table row with the expanded template and author link
        table.insert(list, string.format('<tr><td>%s</td><td>[[Author:%s|%s]]</td></tr>', songLinkTable, performerName, performerName))
    end
    
    if #list == 0 then
    	return ''
    end
    
	local list_string = table.concat(list, '\n')
	
	-- Replace all instances of "[[Author:Unknown|]]" with "Unknown"
	list_string = list_string:gsub('%[%[Author:Unknown|%]%]', 'Unknown')
	list_string = list_string:gsub('%[%[Author:Unknown|Unknown]%]', 'Unknown')
	
	local list_table = mw.html.create('table')
		:addClass('wikitable wst-film-song-list')
		:wikitext(table.concat({
			'<tr><th>Song</th><th>Performer</th></tr>',
			list_string
		}))
	
	return tostring(list_table) .. '[[Category:' .. 'Sound films containing lyrical music' .. ']]'
end

-- frame functions

function p.film_song_link(frame)
	return p._film_song_link(getArgs(frame))
end

function p.film_song_link_table(frame)
	return p._film_song_link_table(getArgs(frame))
end

function p.film_song_list(frame)
	return p._film_song_list(getArgs(frame))
end

return p