+ return self.uci:get(self.config, section, option)
+ else
+ return self.uci:get_all(self.config, section)
+ end
+end
+
+--[[
+Compound - Container
+]]--
+Compound = class(Node)
+
+function Compound.__init__(self, ...)
+ Node.__init__(self)
+ self.template = "cbi/compound"
+ self.children = {...}
+end
+
+function Compound.populate_delegator(self, delegator)
+ for _, v in ipairs(self.children) do
+ v.delegator = delegator
+ end
+end
+
+function Compound.parse(self, ...)
+ local cstate, state = 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.defaultpath = {}
+ self.pageaction = false
+ self.readinput = true
+ self.allow_reset = false
+ self.allow_cancel = false
+ self.allow_back = false
+ self.allow_finish = false
+ self.template = "cbi/delegator"
+end
+
+function Delegator.set(self, name, node)
+ if type(node) == "table" and getmetatable(node) == nil then
+ node = Compound(unpack(node))
+ end
+ assert(type(node) == "function" or instanceof(node, Compound), "Invalid")
+ assert(not self.nodes[name], "Duplicate entry")
+
+ self.nodes[name] = node
+end
+
+function Delegator.add(self, name, node)
+ node = self:set(name, node)
+ self.defaultpath[#self.defaultpath+1] = name
+end
+
+function Delegator.insert_after(self, name, after)
+ local n = #self.chain
+ for k, v in ipairs(self.chain) do
+ if v == state then
+ n = k + 1
+ break
+ end
+ end
+ table.insert(self.chain, n, name)
+end
+
+function Delegator.set_route(self, ...)
+ local n, chain, route = 0, self.chain, {...}
+ for i = 1, #chain do
+ if chain[i] == self.current then
+ n = i
+ break
+ end
+ end
+ for i = 1, #route do
+ n = n + 1
+ chain[n] = route[i]
+ end
+ for i = n + 1, #chain do
+ chain[i] = nil
+ end
+end
+
+function Delegator.get(self, name)
+ return self.nodes[name]
+end
+
+function Delegator.parse(self, ...)
+ if self.allow_cancel and Map.formvalue(self, "cbi.cancel") then
+ if self:_run_hooks("on_cancel") then
+ return FORM_DONE
+ end
+ end
+
+ if not Map.formvalue(self, "cbi.delg.current") then
+ self:_run_hooks("on_init")
+ end
+
+ local newcurrent
+ self.chain = self.chain or self:get_chain()
+ self.current = self.current or self:get_active()
+ self.active = self.active or self:get(self.current)
+ assert(self.active, "Invalid state")
+
+ local stat = FORM_DONE
+ if type(self.active) ~= "function" then
+ self.active:populate_delegator(self)
+ stat = self.active:parse()
+ else
+ self:active()
+ end
+
+ if stat > FORM_PROCEED then
+ if Map.formvalue(self, "cbi.delg.back") then
+ newcurrent = self:get_prev(self.current)
+ else
+ newcurrent = self:get_next(self.current)
+ end
+ elseif stat < FORM_PROCEED then
+ return stat
+ end
+
+
+ if not Map.formvalue(self, "cbi.submit") then
+ return FORM_NODATA
+ elseif not newcurrent or not self:get(newcurrent) then
+ self:_run_hooks("on_done")
+ return FORM_DONE