Module:FileMedia

From MEpedia, a crowd-sourced encyclopedia of ME and CFS science and history

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

local FileMedia = { suite  = "FileMedia",
                    serial = "2018-07-21",
                    item   = 24765326 }
--[=[
FileMedia
]=]



FileMedia.failsafe = function ( assert )
    local since = assert
    local r
    if since == "wikidata" then
        local item = FileMedia.item;
        since = false;
        if type( item ) == "number"  and  item > 0 then
            local ent = mw.wikibase.getEntity( string.format( "Q%d",
                                                              item ) );
            if type( ent ) == "table" then
                local vsn = ent:formatPropertyValues( "P348" );
                if type( vsn ) == "table"  and
                   type( vsn.value) == "string" and
                   vsn.value ~= "" then
                    r = vsn.value;
                end
            end
        end
    end
    if not r then
        if not since  or  since <= FileMedia.serial then
            r = FileMedia.serial
        else
            r = false
        end
    end
    return r
end -- FileMedia.failsafe()



FileMedia.getExtension = function ( ask )
    -- Retrieve "file name extension" from file name
    -- Precondition:
    --     ask  -- file name; string, or nil
    -- Postcondition:
    --     Returns string, or false
    local r = false
    local s = FileMedia.getTitle( ask )
    if s then
        s = ask:match( ".%.(%w+)%s*$" )
        if s then
            r = s:lower()
        end
    end
    return r
end -- FileMedia.getExtension()



FileMedia.getHeight = function ( ask )
    -- Retrieve image height
    -- Precondition:
    --     ask  -- file name or title; string, or nil
    -- Postcondition:
    --     Returns number, or false or nil
    local r = false
    local s = FileMedia.getTitle( ask )
    if s then
        local d = mw.title.makeTitle( "File", s )
        if d and d.file then
            r = d.file.height
        end
    end
    return r
end -- FileMedia.getHeight()



FileMedia.getHeightWidth = function ( ask )
    -- Retrieve image height x width
    -- Precondition:
    --     ask  -- file name or title; string, or nil
    -- Postcondition:
    --     Returns string like "123x456px", or false or nil
    local r = false
    local s = FileMedia.getTitle( ask )
    if s then
        local d = mw.title.makeTitle( "File", s )
        if d and d.file then
            r = d.file.height
            if r then
                r = string.format("%dx%dpx", r, d.file.width)
            end
        end
    end
    return r
end -- FileMedia.getHeightWidth()



FileMedia.getMimeType = function ( ask )
    -- Retrieve file MimeType
    -- Precondition:
    --     ask  -- file name or title; string, or nil
    -- Postcondition:
    --     Returns string, or false or nil
    local r = false
    local s = FileMedia.getTitle( ask )
    if s then
        local d = mw.title.makeTitle( "File", s )
        if d and d.file then
            r = d.file.mimeType
        end
    end
    return r
end -- FileMedia.getMimeType()



FileMedia.getPageCount = function ( ask )
    -- Retrieve number of file pages (paged media fragments)
    -- Precondition:
    --     ask  -- file name or title; string, or nil
    -- Postcondition:
    --     Returns number (0 if not paged media), or false or nil
    local r = false
    local s = FileMedia.getTitle( ask )
    if s then
        local d = mw.title.makeTitle( "File", s )
        if d and d.file then
            r = d.file.pages
            if r then
                r = #r
            elseif d.file.size then
                r = 0
            end
        end
    end
    return r
end -- FileMedia.getPageCount()



FileMedia.getPages = function ( ask )
    -- Retrieve table of file page sizes (paged media fragments)
    -- Precondition:
    --     ask  -- file name or title; string, or nil
    -- Postcondition:
    --     Returns table, or false or nil
    local r = false
    local s = FileMedia.getTitle( ask )
    if s then
        local d = mw.title.makeTitle( "File", s )
        if d and d.file then
            r = d.file.pages
        end
    end
    return r
end -- FileMedia.getPages()



FileMedia.getSize = function ( ask )
    -- Retrieve file size
    -- Precondition:
    --     ask  -- file name or title; string, or nil
    -- Postcondition:
    --     Returns number, or false or nil
    local r = false
    local s = FileMedia.getTitle( ask )
    if s then
        local d = mw.title.makeTitle( "File", s )
        if d and d.file then
            r = d.file.size
        end
    end
    return r
end -- FileMedia.getSize()



FileMedia.getTitle = function ( ask )
    -- Retrieve file page title from page name
    -- Precondition:
    --     ask  -- file name; string, or nil
    -- Postcondition:
    --     Returns string, or false if not a valid file
    local r = false
    if FileMedia.isType( ask, "file" ) then
        local space, s = ask:match( "^([^:]+):(.+)$" )
        if space then
            if FileMedia.isSpacing( space ) then
                r = mw.text.trim( s )
            end
        else
            r = mw.text.trim( ask )
        end
    end
    return r
end -- FileMedia.getTitle()



FileMedia.getType = function ( ask )
    -- Retrieve supposed file type from "file name extension"
    -- Precondition:
    --     ask  -- file name; string, or nil
    -- Postcondition:
    --     Returns string, or false
    --             "audio"
    --             "data"
    --             "paged"
    --             "pixel"
    --             "program"
    --             "style"
    --             "vector"
    --             "video"
    local r = false
    if ask then
        local s = ask:match( ".%.(%w+)%s*$" )
        if s then
            local ext = mw.loadData( "Module:FileMedia/extensions" )
            if ext then
                s = ext[ s:lower() ]
                if s then
                    r = s
                end
            end
        end
    end
    return r
end -- FileMedia.getType()


FileMedia.getWidth = function ( ask )
    -- Retrieve image width
    -- Precondition:
    --     ask  -- file name or title; string, or nil
    -- Postcondition:
    --     Returns number, or false or nil
    local r = false
    local s = FileMedia.getTitle( ask )
    if s then
        local d = mw.title.makeTitle( "File", s )
        if d and d.file then
            r = d.file.width
        end
    end
    return r
end -- FileMedia.getWidth()



FileMedia.isFile = function ( ask )
    -- Is this a valid (existing) file title or file name?
    -- Precondition:
    --     ask  -- file title or file name; string, or nil
    -- Postcondition:
    --     Returns boolean
    -- Expensive function.
    local r
    local s = FileMedia.getTitle( ask )
    if s then
        r = mw.title.makeTitle( "File", s ).fileExists
    else
        r = false
    end
    return r
end -- FileMedia.isFile()



FileMedia.isSpacing = function ( ask )
    -- Is presumed space name not conflicting with files?
    -- Precondition:
    --     ask  -- possible space name; string, or nil
    -- Postcondition:
    --     Returns boolean; false: conflict
    local r = true
    if ask then
        local space = mw.site.namespaces[ mw.text.trim( ask ) ]
        if space then
            space = space.canonicalName
            r     = ( space == "Media"  or  space == "File" )
        end
    end
    return r
end -- FileMedia.isSpacing()



FileMedia.isType = function ( ask, against )
    -- Does file name match type expectation?
    -- Precondition:
    --     ask      -- file name; string, or nil
    --     against  -- expectation; generic or "file" or "image" or any
    -- Postcondition:
    --     Returns boolean
    local r = false
    local s = FileMedia.getType( ask )
    if s then
        local scope
        if against == "file" then
            scope = "audio paged pixel vector video"
        elseif against == "image" then
            scope = "paged pixel vector"
        end
        if scope then
            local suffix = ask:match( ".%.(%w+)%s*$" )
            if suffix  and  suffix:lower() ~= "doc" then
                r = scope:match( s )
            end
        else
            r = ( s == against )
        end
        if r then
            s = ask:match( "^%s*([^:]+)%s*:" )
            r = FileMedia.isSpacing( s )
        end
    end
    return r
end -- FileMedia.isType()



FileMedia.setParSize = function ( assign, atleast, ahead )
    -- Check or adapt transclusion parameter for size
    -- Precondition:
    --     assign   -- size parameter; string, or nil
    --     atleast  -- fallback value; string, or nil
    --     ahead    -- start with pipe, if not empty; boolean, or nil
    -- Postcondition:
    --     Returns px string, if valid or corrected, else false
    local r = false
    if type( assign ) == "string" then
        local s = mw.text.trim( assign )
        if s ~= "" then
            if s:match( "^[1-9]%d?%d?%d?$" ) then
                r = s .. "px"
            else
                s = s:lower()
                if s:match( "%d$" ) then
                    s = s .. "px"
                elseif not s:match( "%dpx$" ) then
                    s = false
                end
                if s then
                    if s:match( "^[1-9]%d?%d?%d?px$" )  or
                       s:match( "^[1-9]%d?%d?%d?x[1-9]%d?%d?%d?px$" )  or
                       s:match( "^x[1-9]%d?%d?%d?px$" ) then
                        r = s
                    end
                end
            end
        end
    end
    if not r and atleast then
        r = atleast
    end
    if r and ahead then
        r = "|" .. r
    end
    return r
end -- FileMedia.setParSize()



-- Export
local p = { }



p.getExtension = function ( frame )
    -- Retrieve "file name extension" from page title or name
    --     1  -- file title or name
    local lucky, r = pcall( FileMedia.getExtension,
                            frame.args[ 1 ] )
    return r or ""
end -- p.getExtension



p.getHeight = function ( frame )
    -- Retrieve image height from page title or name
    --     1  -- file title or name
    local lucky, r = pcall( FileMedia.getHeight,
                            frame.args[ 1 ] )
    return r or ""
end -- p.getHeight



p.getHeightWidth = function ( frame )
    -- Retrieve image height x width from page title or name
    --     1  -- file title or name
    local lucky, r = pcall( FileMedia.getHeightWidth,
                            frame.args[ 1 ] )
    return r or ""
end -- p.getHeightWidth



p.getMimeType = function ( frame )
    -- Retrieve MIME type from page title or name
    --     1  -- file title or name
    local lucky, r = pcall( FileMedia.getMimeType,
                            frame.args[ 1 ] )
    return r or ""
end -- p.getMimeType



p.getPageCount = function ( frame )
    -- Retrieve number of file pages (paged media fragments) from page title or name
    --     1  -- file title or name
    local lucky, r = pcall( FileMedia.getPageCount,
                            frame.args[ 1 ] )
    return r or ""
end -- p.getPageCount



p.getSize = function ( frame )
    -- Retrieve file size from page title or name
    --     1  -- file title or name
    local lucky, r = pcall( FileMedia.getSize,
                            frame.args[ 1 ] )
    return r or ""
end -- p.getSize



p.getTitle = function ( frame )
    -- Retrieve file title from page title or name
    --     1  -- file title or name
    local lucky, r = pcall( FileMedia.getTitle,
                            frame.args[ 1 ] )
    return r or ""
end -- p.getTitle



p.getType = function ( frame )
    -- Retrieve supposed file type from "file name extension"
    --     1  -- file title or name
    local lucky, r = pcall( FileMedia.getType,
                            frame.args[ 1 ] )
    return r or ""
end -- p.getType



p.getWidth = function ( frame )
    -- Retrieve file width from page title or name
    --     1  -- file title or name
    local lucky, r = pcall( FileMedia.getWidth,
                            frame.args[ 1 ] )
    return r or ""
end -- p.getWidth



p.isFile = function ( frame )
    -- Is this a valid (existing) file title or file name?
    --     1  -- file name; with or without namespace
    -- Expensive function.
    local lucky, r = pcall( FileMedia.isFile,
                            frame.args[ 1 ] )
    return r and "1" or ""
end -- p.isFile



p.isType = function ( frame )
    -- Does file name match type expectation?
    --     1  -- file name
    --     2  -- expected
    local r        = false
    local supposed = frame.args[ 2 ]
    if supposed then
        supposed = supposed:match( "^%s*(%w+)%s*$" )
        if supposed then
            local lucky
            lucky, r = pcall( FileMedia.isType,
                              frame.args[ 1 ],
                              supposed:lower() )
        end
    end
    return r and "1" or ""
end -- p.isType



p.setParSize = function ( frame )
    -- Check or adapt transclusion parameter [ 1 ] for size
    -- Returns px string, if valid or corrected, else empty
    --         Fallback to parameter [ 2 ]
    local lead = frame.args.pipe
    local r
    if lead  and
       ( lead == ""  or  lead == "0" ) then
        lead = false
    end
    r = FileMedia.setParSize( frame.args[ 1 ],
                              frame.args[ 2 ],
                              lead )
    return  r or ""
end -- p.setParSize



p.failsafe = function ( frame )
    -- Versioning interface
    local s = type( frame )
    local since
    if s == "table" then
        since = frame.args[ 1 ]
    elseif s == "string" then
        since = frame
    end
    if since then
        since = mw.text.trim( since )
        if since == "" then
            since = false
        end
    end
    return FileMedia.failsafe( since )  or  ""
end -- p.failsafe()



p.FileMedia = function ()
    return FileMedia
end -- p.FileMedia

return p