(Новая страница: «------------------------------------------------------------------------------- -- -- Module:Item util -- -- This meta module conta...») |
Нет описания правки |
||
(не показано 6 промежуточных версий этого же участника) | |||
Строка 5: | Строка 5: | ||
-- This meta module contains utility functions for modules that deal with items |
-- This meta module contains utility functions for modules that deal with items |
||
------------------------------------------------------------------------------- |
------------------------------------------------------------------------------- |
||
+ | |||
+ | local m_util = require('Module:Util') |
||
+ | local m_cargo -- Lazy load require('Module:Cargo') |
||
+ | |||
+ | -- Should we use the sandbox version of our submodules? |
||
+ | local use_sandbox = m_util.misc.maybe_sandbox('Item util') |
||
-- The cfg table contains all localisable strings and configuration, to make it |
-- The cfg table contains all localisable strings and configuration, to make it |
||
-- easier to port this module to another wiki. |
-- easier to port this module to another wiki. |
||
− | local cfg = mw.loadData('Module:Item util/config') |
+ | local cfg = use_sandbox and mw.loadData('Module:Item util/config/sandbox') or mw.loadData('Module:Item util/config') |
local i18n = cfg.i18n |
local i18n = cfg.i18n |
||
Строка 25: | Строка 31: | ||
end |
end |
||
return cfg.item_namespaces |
return cfg.item_namespaces |
||
+ | end |
||
+ | |||
+ | function m.query_item(args, qargs) |
||
+ | qargs = qargs or {} |
||
+ | m_cargo = m_cargo or require('Module:Cargo') |
||
+ | if not m_util.table.has_any_key(args, cfg.search_terms) then |
||
+ | error(i18n.errors.missing_search_term) |
||
+ | end |
||
+ | local tables = {'items'} |
||
+ | local fields = { |
||
+ | 'items._pageName=_pageName', |
||
+ | 'items.drop_enabled=drop_enabled', |
||
+ | 'items.class_id=class_id', |
||
+ | } |
||
+ | local query = { |
||
+ | groupBy = 'items._pageID', |
||
+ | orderBy = 'items.drop_enabled DESC', |
||
+ | } |
||
+ | local search_param |
||
+ | local results |
||
+ | if args.metadata_id then |
||
+ | query.where = string.format( |
||
+ | 'items.metadata_id = "%s"', |
||
+ | args.metadata_id |
||
+ | ) |
||
+ | search_param = 'metadata_id' |
||
+ | elseif args.page then |
||
+ | -- Join with _pageData in order to check for page redirect |
||
+ | tables[#tables+1] = '_pageData' |
||
+ | query.join = 'items._pageName = _pageData._pageNameOrRedirect' |
||
+ | query.where = string.format( |
||
+ | '_pageData._pageName = "%s"', |
||
+ | m_cargo.addslashes(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.where = string.format( |
||
+ | 'items._pageNamespace IN (%s)', |
||
+ | m.get_item_namespaces{format = 'list'} |
||
+ | ) |
||
+ | query.orderBy = 'map_series.ordinal DESC, ' .. query.orderBy |
||
+ | if args.item_name_exact then |
||
+ | query.where = query.where .. string.format( |
||
+ | ' AND items.name = "%s"', |
||
+ | m_cargo.addslashes(args.item_name_exact) |
||
+ | ) |
||
+ | search_param = 'item_name_exact' |
||
+ | else |
||
+ | --[[ |
||
+ | Cargo's implementation of HOLDS breaks when there is a properly |
||
+ | escaped quotation mark at the end of a string literal. |
||
+ | |||
+ | Example of a WHERE clause that results in an error: |
||
+ | items.name_list HOLDS "\"O\' Eternal\"" |
||
+ | |||
+ | Instead, we avoid using HOLDS by explicitly joining the child table |
||
+ | and then comparing using a native operator. |
||
+ | --]] |
||
+ | tables[#tables+1] = 'items__name_list' |
||
+ | query.join = query.join .. ', items._ID = items__name_list._rowID' |
||
+ | query.where = query.where .. string.format( |
||
+ | ' AND items__name_list._value = "%s"', |
||
+ | m_cargo.addslashes(args.item_name) |
||
+ | ) |
||
+ | search_param = 'item_name' |
||
+ | end |
||
+ | end |
||
+ | -- Append additional tables and fields |
||
+ | if type(qargs.tables) == 'table' and #qargs.tables > 0 then |
||
+ | tables = m_util.table.merge(tables, qargs.tables) |
||
+ | end |
||
+ | if type(qargs.fields) == 'table' and #qargs.fields > 0 then |
||
+ | fields = m_util.table.merge(fields, qargs.fields) |
||
+ | end |
||
+ | -- Append to join, where and orderBy clauses |
||
+ | if qargs.join then |
||
+ | query.join = table.concat({query.join, qargs.join}, ', ') |
||
+ | end |
||
+ | if qargs.where then |
||
+ | query.where = table.concat({query.where, qargs.where}, ' AND ') |
||
+ | end |
||
+ | if qargs.orderBy then |
||
+ | query.orderBy = table.concat({qargs.orderBy, query.orderBy}, ', ') |
||
+ | end |
||
+ | results = m_cargo.query(tables, fields, query) |
||
+ | local err |
||
+ | if #results == 0 then |
||
+ | -- No results found |
||
+ | err = m_util.misc.raise_error_or_return{ |
||
+ | raise_required = true, |
||
+ | args = args, |
||
+ | msg = string.format( |
||
+ | i18n.errors.no_results_found, |
||
+ | search_param, |
||
+ | args[search_param] |
||
+ | ) |
||
+ | } |
||
+ | elseif #results > 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(results) do |
||
+ | if v.class_id == 'Map' then |
||
+ | map_count = map_count + 1 |
||
+ | end |
||
+ | if m_util.cast.boolean(v.drop_enabled) then |
||
+ | drop_enabled_count = drop_enabled_count + 1 |
||
+ | end |
||
+ | end |
||
+ | if (map_count == 0 or map_count ~= #results) and drop_enabled_count ~= 1 then |
||
+ | err = m_util.misc.raise_error_or_return{ |
||
+ | raise_required = true, |
||
+ | args = args, |
||
+ | msg = string.format( |
||
+ | i18n.errors.many_results_found, |
||
+ | search_param, |
||
+ | args[search_param] |
||
+ | ) |
||
+ | } |
||
+ | end |
||
+ | end |
||
+ | if args.debug then |
||
+ | mw.logObject(results) |
||
+ | end |
||
+ | if err ~= nil then |
||
+ | if not m_util.cast.boolean(args.nocat) then |
||
+ | err = err .. m_util.misc.add_category({args.error_category or i18n.categories.failed_query}) |
||
+ | end |
||
+ | return {error = err} |
||
+ | end |
||
+ | return results[1] -- orderBy ensures that the first result is the one we want |
||
end |
end |
||
Текущая версия от 16:19, 24 января 2022
Это мета-модуль, который предназначен для использования только другими модулями. Он не должен вызываться в викитексте. |
Этот модуль зависит от следующих других модулей: |
Этот мета-модуль предоставляет служебные функции для модулей, которые имеют дело с предметами.
Использование
Этот модуль должен быть загружен с помощью require()
.
Вышеприведенная документация извлекается из Модуль:Item util/doc.
Редакторы могут экспериментировать в sandbox этого модуля и в testcases страницах.
Подстраницы этого модуля.
Редакторы могут экспериментировать в sandbox этого модуля и в testcases страницах.
Подстраницы этого модуля.
-------------------------------------------------------------------------------
--
-- Module:Item util
--
-- This meta module contains utility functions for modules that deal with items
-------------------------------------------------------------------------------
local m_util = require('Module:Util')
local m_cargo -- Lazy load require('Module:Cargo')
-- Should we use the sandbox version of our submodules?
local use_sandbox = m_util.misc.maybe_sandbox('Item util')
-- 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 util/config/sandbox') or mw.loadData('Module:Item util/config')
local i18n = cfg.i18n
-- ----------------------------------------------------------------------------
-- Exported functions
-- ----------------------------------------------------------------------------
local m = {}
function m.get_item_namespaces(args)
-- Returns item namespaces from config as a table or as a comma-separated string
args.format = args.format or 'table'
if args.format == 'list' then
return cfg.item_namespaces_list
end
return cfg.item_namespaces
end
function m.query_item(args, qargs)
qargs = qargs or {}
m_cargo = m_cargo or require('Module:Cargo')
if not m_util.table.has_any_key(args, cfg.search_terms) then
error(i18n.errors.missing_search_term)
end
local tables = {'items'}
local fields = {
'items._pageName=_pageName',
'items.drop_enabled=drop_enabled',
'items.class_id=class_id',
}
local query = {
groupBy = 'items._pageID',
orderBy = 'items.drop_enabled DESC',
}
local search_param
local results
if args.metadata_id then
query.where = string.format(
'items.metadata_id = "%s"',
args.metadata_id
)
search_param = 'metadata_id'
elseif args.page then
-- Join with _pageData in order to check for page redirect
tables[#tables+1] = '_pageData'
query.join = 'items._pageName = _pageData._pageNameOrRedirect'
query.where = string.format(
'_pageData._pageName = "%s"',
m_cargo.addslashes(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.where = string.format(
'items._pageNamespace IN (%s)',
m.get_item_namespaces{format = 'list'}
)
query.orderBy = 'map_series.ordinal DESC, ' .. query.orderBy
if args.item_name_exact then
query.where = query.where .. string.format(
' AND items.name = "%s"',
m_cargo.addslashes(args.item_name_exact)
)
search_param = 'item_name_exact'
else
--[[
Cargo's implementation of HOLDS breaks when there is a properly
escaped quotation mark at the end of a string literal.
Example of a WHERE clause that results in an error:
items.name_list HOLDS "\"O\' Eternal\""
Instead, we avoid using HOLDS by explicitly joining the child table
and then comparing using a native operator.
--]]
tables[#tables+1] = 'items__name_list'
query.join = query.join .. ', items._ID = items__name_list._rowID'
query.where = query.where .. string.format(
' AND items__name_list._value = "%s"',
m_cargo.addslashes(args.item_name)
)
search_param = 'item_name'
end
end
-- Append additional tables and fields
if type(qargs.tables) == 'table' and #qargs.tables > 0 then
tables = m_util.table.merge(tables, qargs.tables)
end
if type(qargs.fields) == 'table' and #qargs.fields > 0 then
fields = m_util.table.merge(fields, qargs.fields)
end
-- Append to join, where and orderBy clauses
if qargs.join then
query.join = table.concat({query.join, qargs.join}, ', ')
end
if qargs.where then
query.where = table.concat({query.where, qargs.where}, ' AND ')
end
if qargs.orderBy then
query.orderBy = table.concat({qargs.orderBy, query.orderBy}, ', ')
end
results = m_cargo.query(tables, fields, query)
local err
if #results == 0 then
-- No results found
err = m_util.misc.raise_error_or_return{
raise_required = true,
args = args,
msg = string.format(
i18n.errors.no_results_found,
search_param,
args[search_param]
)
}
elseif #results > 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(results) do
if v.class_id == 'Map' then
map_count = map_count + 1
end
if m_util.cast.boolean(v.drop_enabled) then
drop_enabled_count = drop_enabled_count + 1
end
end
if (map_count == 0 or map_count ~= #results) and drop_enabled_count ~= 1 then
err = m_util.misc.raise_error_or_return{
raise_required = true,
args = args,
msg = string.format(
i18n.errors.many_results_found,
search_param,
args[search_param]
)
}
end
end
if args.debug then
mw.logObject(results)
end
if err ~= nil then
if not m_util.cast.boolean(args.nocat) then
err = err .. m_util.misc.add_category({args.error_category or i18n.categories.failed_query})
end
return {error = err}
end
return results[1] -- orderBy ensures that the first result is the one we want
end
return m