Строка 57: | Строка 57: | ||
tpl_args.item_name = tpl_args.item_name or tpl_args[1] |
tpl_args.item_name = tpl_args.item_name or tpl_args[1] |
||
tpl_args.name = tpl_args.name or tpl_args[2] |
tpl_args.name = tpl_args.name or tpl_args[2] |
||
− | |||
⚫ | |||
− | error(i18n.errors.invalid_args) |
||
− | end |
||
− | |||
tpl_args.large = m_util.cast.boolean(tpl_args.large) |
tpl_args.large = m_util.cast.boolean(tpl_args.large) |
||
local img |
local img |
||
local result |
local result |
||
⚫ | |||
− | local search_param |
||
− | + | tpl_args.fields = { |
|
− | + | 'items.name=name', |
|
⚫ | |||
− | local fields = { |
||
− | 'items. |
+ | 'items.html=html', |
− | 'items. |
+ | 'items.alternate_art_inventory_icons=alternate_art_inventory_icons', |
− | 'items. |
+ | 'items.size_x=size_x', |
− | 'items. |
+ | 'items.size_y=size_y', |
⚫ | |||
− | 'items.size_x', |
||
− | 'items.size_y', |
||
− | 'items.drop_enabled', |
||
− | 'items.class_id', |
||
} |
} |
||
+ | tpl_args.error_category = i18n.categories.broken_item_links |
||
− | local query = { |
||
− | + | result = m_item_util.query_item(tpl_args) |
|
− | + | if result.error then |
|
− | + | return result.error |
|
− | if tpl_args.metadata_id then |
||
− | query.where = string.format( |
||
− | 'items.metadata_id="%s"', |
||
− | tpl_args.metadata_id |
||
− | ) |
||
− | search_param = 'metadata_id' |
||
− | elseif tpl_args.page then |
||
− | -- Join with _pageData in order to check for page redirect |
||
− | tables[#tables+1] = '_pageData' |
||
− | fields[#fields+1] = '_pageData._pageNameOrRedirect' |
||
− | query.join = 'items._pageName = _pageData._pageNameOrRedirect' |
||
− | query.where = string.format( |
||
− | '_pageData._pageName="%s"', |
||
− | tpl_args.page |
||
− | ) |
||
− | search_param = 'page' |
||
− | else |
||
− | tables[#tables+1] = 'maps' |
||
− | tables[#tables+1] = 'map_series' |
||
− | query.join = 'items._pageID = maps._pageID, maps.series = map_series.name' |
||
− | query.orderBy = 'map_series.ordinal DESC, items.drop_enabled DESC' |
||
− | if tpl_args.item_name_exact then |
||
− | query.where = string.format( |
||
− | 'items.name = "%s" AND items._pageNamespace IN (%s)', |
||
− | m_cargo.addslashes(tpl_args.item_name_exact), |
||
− | m_item_util.get_item_namespaces{format = 'list'} |
||
− | ) |
||
− | search_param = 'item_name_exact' |
||
− | else |
||
− | -- Explicitly join name_list child table instead of using HOLDS |
||
− | tables[#tables+1] = 'items__name_list' |
||
− | query.join = query.join .. ', items._ID = items__name_list._rowID' |
||
− | query.where = string.format( |
||
− | 'items__name_list._value = "%s" AND items._pageNamespace IN (%s)', |
||
− | m_cargo.addslashes(tpl_args.item_name), |
||
− | m_item_util.get_item_namespaces{format = 'list'} |
||
− | ) |
||
− | search_param = 'item_name' |
||
− | end |
||
− | end |
||
− | result = m_cargo.query(tables, fields, query) |
||
− | local err |
||
− | if #result == 0 then |
||
− | -- No results found |
||
− | err = m_util.misc.raise_error_or_return{ |
||
− | raise_required=true, |
||
− | args=tpl_args, |
||
− | msg=string.format( |
||
− | i18n.errors.no_results, |
||
− | search_param, |
||
− | tpl_args[search_param] |
||
− | ) |
||
− | } |
||
− | elseif #result > 1 then |
||
− | -- More than one result found |
||
− | -- |
||
− | -- If results are all maps, use the one from the most recent map |
||
− | -- series, regardless of whether it's drop enabled. Otherwise, |
||
− | -- if only one of the results is drop enabled then use that one. |
||
− | local map_count = 0 |
||
− | local drop_enabled_count = 0 |
||
− | for i, v in ipairs(result) do |
||
− | if v['items.class_id'] == 'Map' then |
||
− | map_count = map_count + 1 |
||
− | end |
||
− | if m_util.cast.boolean(v['items.drop_enabled']) then |
||
− | drop_enabled_count = drop_enabled_count + 1 |
||
− | end |
||
− | end |
||
− | if (map_count == 0 or map_count ~= #result) and drop_enabled_count ~= 1 then |
||
− | err = m_util.misc.raise_error_or_return{ |
||
− | raise_required=true, |
||
− | args=tpl_args, |
||
− | msg=string.format( |
||
− | i18n.errors.too_many_results, |
||
− | search_param, |
||
− | tpl_args[search_param] |
||
− | ) |
||
− | } |
||
− | end |
||
− | end |
||
− | if err ~= nil then |
||
− | return err .. m_util.misc.add_category({i18n.categories.broken_item_links}) |
||
end |
end |
||
− | result = result[1] -- Use the first result |
||
else |
else |
||
result = { |
result = { |
||
− | [' |
+ | ['_pageName'] = tpl_args.page or tpl_args.name |
} |
} |
||
end |
end |
||
Строка 182: | Строка 88: | ||
if tpl_args.image ~= nil then |
if tpl_args.image ~= nil then |
||
− | if result[' |
+ | if result['alternate_art_inventory_icons'] == nil then |
return m_util.misc.raise_error_or_return{ |
return m_util.misc.raise_error_or_return{ |
||
raise_required=true, |
raise_required=true, |
||
Строка 188: | Строка 94: | ||
msg=string.format( |
msg=string.format( |
||
i18n.errors.alt_art_undefined, |
i18n.errors.alt_art_undefined, |
||
− | result[' |
+ | result['_pageName'] |
) .. m_util.misc.add_category({i18n.categories.broken_item_links}) |
) .. m_util.misc.add_category({i18n.categories.broken_item_links}) |
||
} |
} |
||
end |
end |
||
− | result[' |
+ | result['alternate_art_inventory_icons'] = m_util.string.split( |
− | result[' |
+ | result['alternate_art_inventory_icons'], |
',%s*' |
',%s*' |
||
) |
) |
||
Строка 200: | Строка 106: | ||
local index = tonumber(tpl_args.image) |
local index = tonumber(tpl_args.image) |
||
if index ~= nil then |
if index ~= nil then |
||
− | img = result[' |
+ | img = result['alternate_art_inventory_icons'][index] |
else |
else |
||
-- offset 1 is needed |
-- offset 1 is needed |
||
local suffix = string.len(' inventory icon.png') + 1 |
local suffix = string.len(' inventory icon.png') + 1 |
||
-- add an extra offset by 1 to account for the space |
-- add an extra offset by 1 to account for the space |
||
− | local prefix = string.len(string.sub(result[' |
+ | local prefix = string.len(string.sub(result['inventory_icon'], 1, -suffix)) + 2 |
− | for _, filename in ipairs(result[' |
+ | for _, filename in ipairs(result['alternate_art_inventory_icons']) do |
if string.sub(filename, prefix, -suffix) == tpl_args.image then |
if string.sub(filename, prefix, -suffix) == tpl_args.image then |
||
img = filename |
img = filename |
||
Строка 221: | Строка 127: | ||
msg=string.format( |
msg=string.format( |
||
i18n.errors.alt_art_invalid_index, |
i18n.errors.alt_art_invalid_index, |
||
− | tpl_args.image, result[' |
+ | tpl_args.image, result['_pageName'] |
) .. m_util.misc.add_category({i18n.categories.broken_item_links}) |
) .. m_util.misc.add_category({i18n.categories.broken_item_links}) |
||
} |
} |
||
end |
end |
||
− | elseif result[' |
+ | elseif result['inventory_icon'] ~= nil then |
− | img = result[' |
+ | img = result['inventory_icon'] |
end |
end |
||
Строка 236: | Строка 142: | ||
-- Hopefully there are no maps with identical names besides the series. |
-- Hopefully there are no maps with identical names besides the series. |
||
local linked_page = tpl_args.link |
local linked_page = tpl_args.link |
||
− | if result[' |
+ | if result['class_id'] == 'Map' and m_util.table.has_any_key(tpl_args, {'item_name', 'item_name_exact'}) then |
− | linked_page = linked_page or tpl_args |
+ | linked_page = linked_page or tpl_args.item_name_exact or tpl_args.item_name |
else |
else |
||
− | linked_page = linked_page or result[' |
+ | linked_page = linked_page or result['_pageName'] |
end |
end |
||
Строка 256: | Строка 162: | ||
end |
end |
||
− | if #result[' |
+ | if #result['name'] > 0 then |
activator:wikitext(string.format( |
activator:wikitext(string.format( |
||
'[[%s|%s]]', |
'[[%s|%s]]', |
||
linked_page, |
linked_page, |
||
− | result[' |
+ | result['name'] or result['_pageName'] |
) |
) |
||
) |
) |
||
Строка 268: | Строка 174: | ||
display:attr('class', 'c-item-hoverbox__display') |
display:attr('class', 'c-item-hoverbox__display') |
||
− | if result[' |
+ | if result['html'] ~= nil then |
− | display:wikitext(result[' |
+ | display:wikitext(result['html']) |
if img then |
if img then |
||
Строка 277: | Строка 183: | ||
if img and tpl_args.large then |
if img and tpl_args.large then |
||
− | local width = tonumber(result[' |
+ | local width = tonumber(result['size_x']) or tonumber(tpl_args.width) |
− | local height = tonumber(result[' |
+ | local height = tonumber(result['size_y']) or tonumber(tpl_args.height) |
if width and height then |
if width and height then |
||
img = string.format( |
img = string.format( |
Версия 17:34, 18 января 2022
Этот модуль используется на очень большом количестве страниц. Чтобы избежать крупномасштабных сбоев и ненужной нагрузки на сервер, любые изменения в этом модуле должны быть сначала протестированы на его подстраницах /песочница или /testcases. Протестированные изменения могут быть добавлены на эту страницу за одну правку. Пожалуйста, обсудите любые изменения на странице обсуждения перед их внедрением. |
Этот модуль зависит от следующих других модулей: |
Модуль предоставляет функциональные возможности для ссылок на предметы.
Содержание
Описание
Этот модуль отвечает за {{Item link}}
(({{Il}}
), которые создают ссылки на предметы с помощью cargo через Модуль:Item2.
Шаблоны Item
Модуль:Item2
Все шаблоны, определенные в Модуль:Item2:
Модуль:Item table
Все шаблоны, определенные в Модуль:Item table:
- {{Item table}}
- {{Query base items}}
- {{Query unique items}}
- {{Item unique versions}}
- {{Area item drops}}
- {{Item table/skill gems}}
- {{Map item drops}}
- {{Prophecy description}}
- {{Simple item list}}
Модуль:Item link
Все шаблоны, определенные в Модуль:Item link:
- {{Item link}}
- {{Il}}
- {{Item icon link}}
Модуль:Item acquisition
Вышеприведенная документация извлекается из Модуль:Item link/doc.
Редакторы могут экспериментировать в sandbox этого модуля и в testcases страницах.
Подстраницы этого модуля.
Редакторы могут экспериментировать в sandbox этого модуля и в testcases страницах.
Подстраницы этого модуля.
-------------------------------------------------------------------------------
--
-- Module:Item link
--
-- This module implements Template:Item link.
--
-- 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.
-------------------------------------------------------------------------------
require('Module:No globals')
local getArgs = require('Module:Arguments').getArgs
local m_util = require('Module:Util')
local m_cargo = require('Module:Cargo')
local m_item_util = require('Module:Item util')
-- Should we use the sandbox version of our submodules?
local use_sandbox = m_util.misc.maybe_sandbox('Item link')
-- The cfg table contains all localisable strings and configuration, to make it
-- easier to port this module to another wiki.
local cfg = use_sandbox and mw.loadData('Module:Item link/config/sandbox') or mw.loadData('Module:Item link/config')
local i18n = cfg.i18n
-- ----------------------------------------------------------------------------
-- Exported functions
-- ----------------------------------------------------------------------------
local p = {}
--
-- Template:Item link
--
function p.item_link (frame)
--[[
Creates a link to the item and displays the item info box on hover
on the link.
Examples
--------
= p.item_link{'Multistrike'}
= p.item_link{'Multistrike Support'}
]]
-- Get arguments:
local tpl_args = getArgs(frame, {
parentFirst = true,
removeBlanks = false,
})
frame = m_util.misc.get_frame(frame)
tpl_args.item_name = tpl_args.item_name or tpl_args[1]
tpl_args.name = tpl_args.name or tpl_args[2]
tpl_args.large = m_util.cast.boolean(tpl_args.large)
local img
local result
if tpl_args.skip_query == nil then
tpl_args.fields = {
'items.name=name',
'items.inventory_icon=inventory_icon',
'items.html=html',
'items.alternate_art_inventory_icons=alternate_art_inventory_icons',
'items.size_x=size_x',
'items.size_y=size_y',
}
tpl_args.error_category = i18n.categories.broken_item_links
result = m_item_util.query_item(tpl_args)
if result.error then
return result.error
end
else
result = {
['_pageName'] = tpl_args.page or tpl_args.name
}
end
for k, prop in pairs(cfg.parameters) do
if tpl_args[k] ~= nil then
result[prop] = tpl_args[k]
end
end
if tpl_args.image ~= nil then
if result['alternate_art_inventory_icons'] == nil then
return m_util.misc.raise_error_or_return{
raise_required=true,
args=tpl_args,
msg=string.format(
i18n.errors.alt_art_undefined,
result['_pageName']
) .. m_util.misc.add_category({i18n.categories.broken_item_links})
}
end
result['alternate_art_inventory_icons'] = m_util.string.split(
result['alternate_art_inventory_icons'],
',%s*'
)
local index = tonumber(tpl_args.image)
if index ~= nil then
img = result['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['inventory_icon'], 1, -suffix)) + 2
for _, filename in ipairs(result['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['_pageName']
) .. m_util.misc.add_category({i18n.categories.broken_item_links})
}
end
elseif result['inventory_icon'] ~= nil then
img = result['inventory_icon']
end
--
-- output
--
-- Maps have their main page on the item name now, link there instead.
-- Hopefully there are no maps with identical names besides the series.
local linked_page = tpl_args.link
if result['class_id'] == 'Map' and m_util.table.has_any_key(tpl_args, {'item_name', 'item_name_exact'}) then
linked_page = linked_page or tpl_args.item_name_exact or tpl_args.item_name
else
linked_page = linked_page or result['_pageName']
end
local container = mw.html.create('span')
container:addClass('c-item-hoverbox')
if tpl_args.large then
container:addClass('c-item-hoverbox--large')
end
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
if #result['name'] > 0 then
activator:wikitext(string.format(
'[[%s|%s]]',
linked_page,
result['name'] or result['_pageName']
)
)
end
local display = mw.html.create('span')
display:attr('class', 'c-item-hoverbox__display')
if result['html'] ~= nil then
display:wikitext(result['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['size_x']) or tonumber(tpl_args.width)
local height = tonumber(result['size_y']) or tonumber(tpl_args.height)
if width and height then
img = string.format(
'[[%s|%sx%spx|link=%s|alt=]]',
img,
width*cfg.image_size,
height*cfg.image_size,
linked_page
)
elseif width then
img = string.format(
'[[%s|%spx|link=%s|alt=]]',
img,
width*cfg.image_size,
linked_page
)
elseif height then
img = string.format(
'[[%s|x%spx|link=%s|alt=]]',
img,
height*cfg.image_size,
linked_page
)
else
img = string.format(
'[[%s|link=%s|alt=]]',
img,
linked_page
)
end
activator:wikitext(img)
end
container
:node(activator)
:node(display)
:done()
return tostring(container)
end
return p