A large portion of relevant modules/templates have now been switched to cargo. Various usages of SMW throughout the wiki need to be replaced by the new functions, in particular item tables. If some pages do not show up but contain no errors, please null-edit them. To see how you can help with the port check out Path_of_Exile_Wiki:To-do_list/SMW_migration (and leave a comment on the talk page if you have questions).

Module:Item link

From Path of Exile Wiki
Jump to: navigation, search

The item module provides functionality for linking to items.

Overview

This module is responsible for {{Item link}} ({{Il}} and {{Sl}}) which create links to items exposed via Semantic Mediawiki through Module:Item2.

Item templates

Module:Item2

All templates defined in Module:Item2:

Module:Item table

All templates defined in Module:Item table:

Module:Item link

All templates defined in Module:Item link:


-- Item link module
-- 
-- This is separate from the main item module for small speed ups. 
-- 
-- Those speed ups are only sigificant if the module is called a lot of times (100+), in tests this amounted to only a ~10% difference in page load times at best.
-- It should be noted those tests are difficult because of the large variance in page load times

-- ----------------------------------------------------------------------------
-- Imports
-- ----------------------------------------------------------------------------
local m_util = require('Module:Util')
local getArgs = require('Module:Arguments').getArgs

-- ----------------------------------------------------------------------------
-- Strings
-- ----------------------------------------------------------------------------
-- This section contains strings used by this module.
-- Add new strings here instead of in-code directly, this will help other
-- people to correct spelling mistakes easier and help with translation to
-- other PoE wikis.
--
-- TODO: Maybe move this out to a separate sub-page module
local i18n = {
    categories = {
        -- maintenance cats
        broken_item_links = '[[Category:Pages with broken item links]]',
    },
    errors = {
        invalid_args = 'Item link: page, item_name or item_name_exact must be specified',
        no_results = 'Item link: No results found for search parameter "%s".',
        too_many_results = 'Item link: Too many results for search parameter "%s". Consider using page parameter instead.',
        alt_art_undefined = 'Item link: Image parameter was specified, but there is no alternate art defined on page "%s"',
        alt_art_invalid_index = 'Item Link: Alternate art with index/name "%s" not found on page "%s"',
    },
}

-- ----------------------------------------------------------------------------
-- Constants & Data
-- ----------------------------------------------------------------------------

local c = {}
c.image_size = 39
c.image_size_full = c.image_size * 2
c.parameters = {
    name = 'items.name',
    inventory_icon = 'items.inventory_icon',
    html = 'items.html',
    width = 'items.size_x',
    height = 'items.size_y',
}

c.selectors = {'page', 'item_name', 'item_name_exact'}

-- ----------------------------------------------------------------------------
-- Invokable code
-- ----------------------------------------------------------------------------

--
-- Template:Item link & Template:Sl
--
local p = {}

function p.item_link (frame)
    --
    -- Args/Frame
    --
    
    local tpl_args = getArgs(frame, {
        parentFirst = true,
        removeBlanks = false,
    })
    frame = m_util.misc.get_frame(frame)
    
    -- Backwards compability
    tpl_args.item_name = tpl_args.item_name or tpl_args[1]
    tpl_args.name = tpl_args.name or tpl_args[2]
    
    if m_util.table.has_all_value(tpl_args, c.selectors) and tpl_args.skip_query == nil then
        error(i18n.errors.invalid_args)
    end
    
    tpl_args.large = m_util.cast.boolean(tpl_args.large)
    
    local img
    local result
    
    if m_util.table.has_one_value(tpl_args, c.selectors, nil) and tpl_args.skip_query == nil then
        local query = {
            groupBy='items._pageID',
        }
        
        if tpl_args.page ~= nil then
            -- TODO returns the result even if the + format is specified. 
            query.where = string.format('items._pageName="%s"', tpl_args.page)
        else
            if tpl_args.item_name ~= nil then
                query.where = string.format('items.name_list HOLDS "%s"', tpl_args.item_name)
            elseif tpl_args.item_name_exact ~= nil then
                query.where = string.format('items.name = "%s"', tpl_args.item_name_exact)
            end
        end
        
        if tpl_args.link_type == 'skill' then
            query.where = string.format('%s AND (items.class = "Active Skill Gems" OR items.class = "Support Skill Gems")', query.where) 
        end
        
        result = m_util.cargo.query(
            {
                'items'
            },
            {
                'items._pageName',
                'items.name',
                'items.inventory_icon',
                'items.html',
                'items.alternate_art_inventory_icons',
                'items.size_x',
                'items.size_y',
            },
            query
        )
        
        local err
        if #result == 0 then
            err = m_util.misc.raise_error_or_return{raise_required=true, args=tpl_args, msg=string.format(
                i18n.errors.no_results, 
                tpl_args.page or tpl_args.item_name or tpl_args.item_name_exact 
            )}
        elseif #result > 1 then
            err = m_util.misc.raise_error_or_return{raise_required=true, args=tpl_args, msg=string.format(
                i18n.errors.too_many_results,
                tpl_args.page or tpl_args.item_name or tpl_args.item_name_exact
            )}
        end
        
        if err ~= nil then
            return err .. i18n.categories.broken_item_links
        end
        
        result = result[1]
    else
        result = {
            ['items._pageName'] = tpl_args.page or tpl_args.name
        }
    end
    
    for k, prop in pairs(c.parameters) do
        if tpl_args[k] ~= nil then
            result[prop] = tpl_args[k]
        end
    end
    
    if tpl_args.image ~= nil then
        if result['items.alternate_art_inventory_icons'] then
            return m_util.misc.raise_error_or_return{raise_required=true, args=tpl_args, msg=string.format(
                i18n.errors.alt_art_undefined,
                result['items._pageName']
            ) .. i18n.categories.broken_item_links}
        end
        
        result['items.alternate_art_inventory_icons'] = m_util.string.split(result['items.alternate_art_inventory_icons'], ',%s*')
        
        local index = tonumber(tpl_args.image)
        if index ~= nil then
            img = result['items.alternate_art_inventory_icons'][index]
        else
            -- offset 1 is needed
            local suffix = string.len(' inventory icon.png') + 1 
            -- add an extra offset by 1 to account for the space 
            local prefix = string.len(string.sub(result['items.inventory_icon'], 1, -suffix)) + 2
            
            for _, filename in ipairs(result['items.alternate_art_inventory_icons']) do
                if string.sub(filename, prefix, -suffix) == tpl_args.image then
                    img = filename
                    break
                end
            end
        end
        
        if img == nil then
            return m_util.misc.raise_error_or_return{raise_required=true, args=tpl_args, msg=string.format(
                 i18n.errors.alt_art_invalid_index,
                tpl_args.image, result['items._pageName']
            ) .. i18n.categories.broken_item_links}
        end
    elseif result['items.inventory_icon'] ~= nil then
        img = result['items.inventory_icon']
    end
    
    -- output
    
    local container = mw.html.create('span')
    container:addClass('c-item-hoverbox')
    
    local activator = mw.html.create('span')
    activator:addClass('c-item-hoverbox__activator')

    if img and not tpl_args.large then
        activator:wikitext(string.format('[[%s|16x16px|link=|alt=]]', img))
    end
       
    activator:wikitext(string.format('[[%s|%s]]', result['items._pageName'], result['items.name'] or result['items._pageName']))
    
    local display = mw.html.create('span')
    display:attr('class', 'c-item-hoverbox__display')

    if result['items.html'] ~= nil then
        display:wikitext(result['items.html'])
            
        if img then
            display:wikitext(string.format('[[%s|link=|alt=]]', img))
        end
    end

    if img and tpl_args.large then
        local width = tonumber(result['items.size_x']) or tonumber(tpl_args.width)
        local height = tonumber(result['items.size_y']) or tonumber(tpl_args.height)
        if width and height then
            img = string.format('<br>[[%s|%sx%spx|link=%s|alt=]]', img, width*c.image_size, height*c.image_size, result['items._pageName'])
        elseif width then
            img = string.format('<br>[[%s|%spx|link=%s|alt=]]', img, width*c.image_size, result['items._pageName'])
        elseif height then
            img = string.format('<br>[[%s|x%spx|link=%s|alt=]]', img, height*c.image_size, result['items._pageName'])
        else
            img = string.format('<br>[[%s|link=%s|alt=]]', img, result['items._pageName'])
        end
        activator:wikitext(img)
    end

    container
        :node(activator)
        :node(display)
        :done()
        
    return tostring(container)
end

return p