local upldir = "/lib/uci/upload/"
local cbidir = luci.util.libpath() .. "/model/cbi/"
- local func, err = loadfile(cbimap) or loadfile(cbidir..cbimap..".lua")
+
+ assert(luci.fs.stat(cbimap) or luci.fs.stat(cbidir..cbimap..".lua"),
+ "Model not found!")
+
+ local func, err = loadfile(cbimap)
+ if not func then
+ func, err = loadfile(cbidir..cbimap..".lua")
+ end
assert(func, err)
luci.i18n.loadc("cbi")
self.parsechain = {self.config}
self.template = "cbi/map"
self.apply_on_parse = nil
+ self.readinput = true
+
self.uci = uci.cursor()
self.save = true
end
+function Map.formvalue(self, key)
+ return self.readinput and luci.http.formvalue(key)
+end
+
+function Map.formvaluetable(self, key)
+ return self.readinput and luci.http.formvaluetable(key)
+end
+
function Map.get_scheme(self, sectiontype, option)
if not option then
return self.scheme and self.scheme.sections[sectiontype]
end
function Map.submitstate(self)
- return luci.http.formvalue("cbi.submit")
+ return self:formvalue("cbi.submit")
end
-- Chain foreign config
table.insert(self.parsechain, config)
end
+function Map.state_handler(self, state)
+ return state
+end
+
-- Use optimized UCI writing
-function Map.parse(self)
- Node.parse(self)
+function Map.parse(self, readinput, ...)
+ self.readinput = (readinput ~= false)
+ Node.parse(self, ...)
if self.save then
for i, config in ipairs(self.parsechain) do
self.state = FORM_NODATA
end
- return self.state
+ return self:state_handler(self.state)
end
function Map.render(self, ...)
end
end
+--[[
+Compound - Container
+]]--
+Compound = class(Node)
+
+function Compound.__init__(self, ...)
+ Node.__init__(self)
+ self.children = {...}
+end
+
+function Compound.parse(self, ...)
+ local cstate, state = 0, 0
+
+ for k, child in ipairs(self.children) do
+ cstate = child:parse(...)
+ state = (not state or cstate < state) and cstate or state
+ end
+
+ return state
+end
+
+
+--[[
+Delegator - Node controller
+]]--
+Delegator = class(Node)
+function Delegator.__init__(self, ...)
+ Node.__init__(self, ...)
+ self.nodes = {}
+ self.template = "cbi/delegator"
+end
+
+function Delegator.state(self, name, node, transitor)
+ transitor = transitor or self.transistor_linear
+ local state = {node=node, name=name, transitor=transitor}
+
+ assert(instanceof(node, Node), "Invalid node")
+ assert(not self.nodes[name], "Duplicate entry")
+
+ self.nodes[name] = state
+ self:append(state)
+
+ return state
+end
+
+function Delegator.get(self, name)
+ return self.nodes[name]
+end
+
+function Delegator.transistor_linear(self, state, cstate)
+ if cstate > 0 then
+ for i, child in ipairs(self.children) do
+ if state == child then
+ return self.children[i+1]
+ end
+ end
+ else
+ return state
+ end
+end
+
+function Delegator.parse(self, ...)
+ local active = self:getactive()
+ assert(active, "Invalid state")
+
+ local cstate = active.node:parse()
+ self.active = active.transistor(self, active.node, cstate)
+
+ if not self.active then
+ return FORM_DONE
+ else
+ self.active:parse(false)
+ return FROM_PROCEED
+ end
+end
+
+function Delegator.render(self, ...)
+ self.active.node:render(...)
+end
+
+function Delegator.getactive(self)
+ return self:get(Map.formvalue(self, "cbi.delegated")
+ or (self.children[1] and self.children[1].name))
+end
--[[
Page - A simple node
self.template = "cbi/simpleform"
self.dorender = true
self.pageaction = false
+ self.readinput = true
end
-function SimpleForm.parse(self, ...)
- if luci.http.formvalue("cbi.submit") then
+SimpleForm.formvalue = Map.formvalue
+SimpleForm.formvaluetable = Map.formvaluetable
+
+function SimpleForm.parse(self, readinput, ...)
+ self.readinput = (readinput ~= false)
+ if self:submitstate() then
Node.parse(self, 1, ...)
end
end
function SimpleForm.submitstate(self)
- return luci.http.formvalue("cbi.submit")
+ return self:formvalue("cbi.submit")
end
function SimpleForm.section(self, class, ...)
self.optionals[section] = {}
- local field = luci.http.formvalue("cbi.opt."..self.config.."."..section)
+ local field = self.map:formvalue("cbi.opt."..self.config.."."..section)
for k,v in ipairs(self.children) do
if v.optional and not v:cfgvalue(section) then
if field == v.option then
end
local arr = luci.util.clone(self:cfgvalue(section))
- local form = luci.http.formvaluetable("cbid."..self.config.."."..section)
+ local form = self.map:formvaluetable("cbid."..self.config.."."..section)
for k, v in pairs(form) do
arr[k] = v
end
local datasource = {}
datasource.config = "table"
self.data = data
+
+ datasource.formvalue = Map.formvalue
+ datasource.formvaluetable = Map.formvaluetable
+ datasource.readinput = true
function datasource.get(self, section, option)
return data[section] and data[section][option]
end
function datasource.submitstate(self)
- return luci.http.formvalue("cbi.submit")
+ return Map.formvalue(self, "cbi.submit")
end
function datasource.del(...)
self.anonymous = true
end
-function Table.parse(self)
+function Table.parse(self, readinput)
+ self.map.readinput = (readinput ~= false)
for i, k in ipairs(self:cfgsections()) do
if self.map:submitstate() then
Node.parse(self, k)
if self.addremove then
local path = self.config.."."..s
if active then -- Remove the section
- if luci.http.formvalue("cbi.rns."..path) and self:remove(s) then
+ if self.map:formvalue("cbi.rns."..path) and self:remove(s) then
+ self:push_events()
return
end
else -- Create and apply default values
- if luci.http.formvalue("cbi.cns."..path) then
+ if self.map:formvalue("cbi.cns."..path) then
self:create(s)
return
end
if self.addremove then
-- Remove
local crval = REMOVE_PREFIX .. self.config
- local name = luci.http.formvaluetable(crval)
+ local name = self.map:formvaluetable(crval)
for k,v in pairs(name) do
if k:sub(-2) == ".x" then
k = k:sub(1, #k - 2)
-- Create
local created
local crval = CREATE_PREFIX .. self.config .. "." .. self.sectiontype
- local name = luci.http.formvalue(crval)
+ local name = self.map:formvalue(crval)
if self.anonymous then
if name then
created = self:create()
-- Return whether this object should be created
function AbstractValue.formcreated(self, section)
local key = "cbi.opt."..self.config.."."..section
- return (luci.http.formvalue(key) == self.option)
+ return (self.map:formvalue(key) == self.option)
end
-- Returns the formvalue for this object
function AbstractValue.formvalue(self, section)
- return luci.http.formvalue(self:cbid(section))
+ return self.map:formvalue(self:cbid(section))
end
function AbstractValue.additional(self, value)
local valid = {}
for i, v in ipairs(value) do
if v and #v > 0
- and not luci.http.formvalue("cbi.rle."..section.."."..self.option.."."..i)
- and not luci.http.formvalue("cbi.rle."..section.."."..self.option.."."..i..".x") then
+ and not self.map:formvalue("cbi.rle."..section.."."..self.option.."."..i)
+ and not self.map:formvalue("cbi.rle."..section.."."..self.option.."."..i..".x") then
table.insert(valid, v)
end
end
function FileUpload.formcreated(self, section)
return AbstractValue.formcreated(self, section) or
- luci.http.formvalue("cbi.rlf."..section.."."..self.option) or
- luci.http.formvalue("cbi.rlf."..section.."."..self.option..".x")
+ self.map:formvalue("cbi.rlf."..section.."."..self.option) or
+ self.map:formvalue("cbi.rlf."..section.."."..self.option..".x")
end
function FileUpload.cfgvalue(self, section)
function FileUpload.formvalue(self, section)
local val = AbstractValue.formvalue(self, section)
if val then
- if not luci.http.formvalue("cbi.rlf."..section.."."..self.option) and
- not luci.http.formvalue("cbi.rlf."..section.."."..self.option..".x")
+ if not self.map:formvalue("cbi.rlf."..section.."."..self.option) and
+ not self.map:formvalue("cbi.rlf."..section.."."..self.option..".x")
then
return val
end