Add extended dispatching targets, optimize dispatching behaviour

This commit is contained in:
Steven Barth 2009-01-04 15:47:45 +00:00
parent f3157bc759
commit 0cc5fdd394

View file

@ -146,6 +146,7 @@ function dispatch(request)
local t = true local t = true
local token = ctx.urltoken local token = ctx.urltoken
local preq = {} local preq = {}
local freq = {}
for i, s in ipairs(request) do for i, s in ipairs(request) do
local tkey, tval local tkey, tval
@ -158,6 +159,7 @@ function dispatch(request)
else else
t = false t = false
preq[#preq+1] = s preq[#preq+1] = s
freq[#freq+1] = s
c = c.nodes[s] c = c.nodes[s]
n = i n = i
if not c then if not c then
@ -174,10 +176,12 @@ function dispatch(request)
if c and c.leaf then if c and c.leaf then
for j=n+1, #request do for j=n+1, #request do
table.insert(args, request[j]) args[#args+1] = request[j]
freq[#freq+1] = request[j]
end end
end end
ctx.requestpath = freq
ctx.path = preq ctx.path = preq
if track.i18n then if track.i18n then
@ -203,7 +207,7 @@ function dispatch(request)
if key == "controller" then if key == "controller" then
return build_url() return build_url()
elseif key == "REQUEST_URI" then elseif key == "REQUEST_URI" then
return build_url(unpack(ctx.requested.path)) return build_url(unpack(ctx.requestpath))
else else
return rawget(table, key) or _G[key] return rawget(table, key) or _G[key]
end end
@ -285,7 +289,16 @@ function dispatch(request)
luci.sys.process.setuser(track.setuser) luci.sys.process.setuser(track.setuser)
end end
if c and (c.index or type(c.target) == "function") then local target = nil
if c then
if type(c.target) == "function" then
target = c.target
elseif type(c.target) == "table" then
target = c.target.target
end
end
if c and (c.index or type(target) == "function") then
ctx.dispatched = c ctx.dispatched = c
ctx.requested = ctx.requested or ctx.dispatched ctx.requested = ctx.requested or ctx.dispatched
end end
@ -298,9 +311,9 @@ function dispatch(request)
end end
end end
if c and type(c.target) == "function" then if type(target) == "function" then
util.copcall(function() util.copcall(function()
local oldenv = getfenv(c.target) local oldenv = getfenv(target)
local module = require(c.module) local module = require(c.module)
local env = setmetatable({}, {__index= local env = setmetatable({}, {__index=
@ -308,10 +321,14 @@ function dispatch(request)
return rawget(tbl, key) or module[key] or oldenv[key] return rawget(tbl, key) or module[key] or oldenv[key]
end}) end})
setfenv(c.target, env) setfenv(target, env)
end) end)
c.target(unpack(args)) if type(c.target) == "table" then
target(c.target, unpack(args))
else
target(unpack(args))
end
else else
error404() error404()
end end
@ -558,110 +575,134 @@ function rewrite(n, ...)
end end
end end
local function _call(self, ...)
if #self.argv > 0 then
return getfenv()[self.name](unpack(self.argv), ...)
else
return getfenv()[self.name](...)
end
end
--- Create a function-call dispatching target. --- Create a function-call dispatching target.
-- @param name Target function of local controller -- @param name Target function of local controller
-- @param ... Additional parameters passed to the function -- @param ... Additional parameters passed to the function
function call(name, ...) function call(name, ...)
local argv = {...} return {type = "call", argv = {...}, name = name, target = _call}
return function(...) end
if #argv > 0 then
return getfenv()[name](unpack(argv), ...)
else local _template = function(self, ...)
return getfenv()[name](...) require "luci.template".render(self.view)
end
end
end end
--- Create a template render dispatching target. --- Create a template render dispatching target.
-- @param name Template to be rendered -- @param name Template to be rendered
function template(name) function template(name)
return function() return {type = "template", view = name, target = _template}
require("luci.template") end
luci.template.render(name)
local function _cbi(self, ...)
local cbi = require "luci.cbi"
local tpl = require "luci.template"
local http = require "luci.http"
local config = self.config or {}
local maps = cbi.load(self.model, ...)
local state = nil
for i, res in ipairs(maps) do
if config.autoapply then
res.autoapply = config.autoapply
end
local cstate = res:parse()
if not state or cstate < state then
state = cstate
end
end end
if config.on_valid_to and state and state > 0 and state < 2 then
http.redirect(config.on_valid_to)
return
end
if config.on_changed_to and state and state > 1 then
http.redirect(config.on_changed_to)
return
end
if config.on_success_to and state and state > 0 then
http.redirect(config.on_success_to)
return
end
if config.state_handler then
if not config.state_handler(state, maps) then
return
end
end
local pageaction = true
http.header("X-CBI-State", state or 0)
tpl.render("cbi/header", {state = state})
for i, res in ipairs(maps) do
res:render()
if res.pageaction == false then
pageaction = false
end
end
tpl.render("cbi/footer", {pageaction=pageaction, state = state, autoapply = config.autoapply})
end end
--- Create a CBI model dispatching target. --- Create a CBI model dispatching target.
-- @param model CBI model to be rendered -- @param model CBI model to be rendered
function cbi(model, config) function cbi(model, config)
config = config or {} return {type = "cbi", config = config, model = model, target = _cbi}
return function(...) end
require("luci.cbi")
require("luci.template")
local http = require "luci.http"
maps = luci.cbi.load(model, ...)
local state = nil local function _arcombine(self, ...)
local argv = {...}
local target = #argv > 0 and self.targets[2] or self.targets[1]
setfenv(target.target, self.env)
target:target(unpack(argv))
end
for i, res in ipairs(maps) do --- Create a combined dispatching target for non argv and argv requests.
if config.autoapply then -- @param trg1 Overview Target
res.autoapply = config.autoapply -- @param trg2 Detail Target
end function arcombine(trg1, trg2)
local cstate = res:parse() return {type = "arcombine", env = getfenv(), target = _arcombine, targets = {trg1, trg2}}
if not state or cstate < state then end
state = cstate
end
local function _form(self, ...)
local cbi = require "luci.cbi"
local tpl = require "luci.template"
local http = require "luci.http"
local maps = luci.cbi.load(self.model, ...)
local state = nil
for i, res in ipairs(maps) do
local cstate = res:parse()
if not state or cstate < state then
state = cstate
end end
if config.on_valid_to and state and state > 0 and state < 2 then
luci.http.redirect(config.on_valid_to)
return
end
if config.on_changed_to and state and state > 1 then
luci.http.redirect(config.on_changed_to)
return
end
if config.on_success_to and state and state > 0 then
luci.http.redirect(config.on_success_to)
return
end
if config.state_handler then
if not config.state_handler(state, maps) then
return
end
end
local pageaction = true
http.header("X-CBI-State", state or 0)
luci.template.render("cbi/header", {state = state})
for i, res in ipairs(maps) do
res:render()
if res.pageaction == false then
pageaction = false
end
end
luci.template.render("cbi/footer", {pageaction=pageaction, state = state, autoapply = config.autoapply})
end end
http.header("X-CBI-State", state or 0)
tpl.render("header")
for i, res in ipairs(maps) do
res:render()
end
tpl.render("footer")
end end
--- Create a CBI form model dispatching target. --- Create a CBI form model dispatching target.
-- @param model CBI form model tpo be rendered -- @param model CBI form model tpo be rendered
function form(model) function form(model)
return function(...) return {type = "cbi", model = model, target = _form}
require("luci.cbi")
require("luci.template")
local http = require "luci.http"
maps = luci.cbi.load(model, ...)
local state = nil
for i, res in ipairs(maps) do
local cstate = res:parse()
if not state or cstate < state then
state = cstate
end
end
http.header("X-CBI-State", state or 0)
luci.template.render("header")
for i, res in ipairs(maps) do
res:render()
end
luci.template.render("footer")
end
end end