CREATE_PREFIX = "cbi.cts."
REMOVE_PREFIX = "cbi.rts."
+RESORT_PREFIX = "cbi.sts."
+FEXIST_PREFIX = "cbi.cbe."
-- Loads a CBI map from given file, creating an environment and returns it
function load(cbimap, ...)
-- Render the children
function Node.render_children(self, ...)
+ local k, node
for k, node in ipairs(self.children) do
+ node.last_child = (k == #self.children)
node:render(...)
end
end
self.uci:apply(self.parsechain)
self:_run_hooks("on_apply", "on_after_apply")
else
- self._apply = function()
- local cmd = self.uci:apply(self.parsechain, true)
- return io.popen(cmd)
- end
+ -- This is evaluated by the dispatcher and delegated to the
+ -- template which in turn fires XHR to perform the actual
+ -- apply actions.
+ self.apply_needed = true
end
-- Reparse sections
function Map.render(self, ...)
self:_run_hooks("on_init")
Node.render(self, ...)
- if false and self._apply then
- local fp = self._apply()
- fp:read("*a")
- fp:close()
- self:_run_hooks("on_apply")
- end
end
-- Creates a child section
-- UCI set
function Map.set(self, section, option, value)
- if option then
- return self.uci:set(self.config, section, option, value)
+ if type(value) ~= "table" or #value > 0 then
+ if option then
+ return self.uci:set(self.config, section, option, value)
+ else
+ return self.uci:set(self.config, section, value)
+ end
else
- return self.uci:set(self.config, section, value)
+ return Map.del(self, section, option)
end
end
assert(tab and self.tabs and self.tabs[tab],
"Cannot render not existing tab %q" % tostring(tab))
- for _, node in ipairs(self.tabs[tab].childs) do
+ local k, node
+ for k, node in ipairs(self.tabs[tab].childs) do
+ node.last_child = (k == #self.tabs[tab].childs)
node:render(...)
end
end
-- Create
local created
local crval = CREATE_PREFIX .. self.config .. "." .. self.sectiontype
- local name = self.map:formvalue(crval)
+ local origin, name = next(self.map:formvaluetable(crval))
if self.anonymous then
if name then
- created = self:create()
+ created = self:create(nil, origin)
end
else
if name then
end
if name and #name > 0 then
- created = self:create(name) and name
+ created = self:create(name, origin) and name
if not created then
self.invalid_cts = true
end
end
end
+ if self.sortable then
+ local stval = RESORT_PREFIX .. self.config .. "." .. self.sectiontype
+ local order = self.map:formvalue(stval)
+ if order and #order > 0 then
+ local sid
+ local num = 0
+ for sid in util.imatch(order) do
+ self.map.uci:reorder(self.config, sid, num)
+ num = num + 1
+ end
+ self.changed = (num > 0)
+ end
+ end
+
if created or self.changed then
self:push_events()
end
function AbstractValue.render(self, s, scope)
if not self.optional or self.section:has_tabs() or self:cfgvalue(s) or self:formcreated(s) then
scope = scope or {}
- scope.section = s
- scope.cbid = self:cbid(s)
- scope.striptags = luci.util.striptags
- scope.pcdata = luci.util.pcdata
-
- scope.ifattr = function(cond,key,val)
- if cond then
- return string.format(
- ' %s="%s"', tostring(key),
- luci.util.pcdata(tostring( val
- or scope[key]
- or (type(self[key]) ~= "function" and self[key])
- or "" ))
- )
- else
- return ''
- end
- end
-
- scope.attr = function(...)
- return scope.ifattr( true, ... )
- end
-
+ scope.section = s
+ scope.cbid = self:cbid(s)
Node.render(self, scope)
end
end
return value[1]
end
elseif self.cast == "table" then
- return luci.util.split(value, "%s+", nil, true)
+ return { value }
end
end
AbstractValue.__init__(self, ...)
self.template = "cbi/fvalue"
- self.enabled = "1"
+ self.enabled = "1"
self.disabled = "0"
+ self.default = self.disabled
end
-- A flag can only have two states: set or unset
function Flag.parse(self, section)
- local fvalue = self:formvalue(section)
-
- if fvalue then
- fvalue = self.enabled
- else
- fvalue = self.disabled
- end
+ local fexists = self.map:formvalue(
+ FEXIST_PREFIX .. self.config .. "." .. section .. "." .. self.option)
- if fvalue == self.enabled or (not self.optional and not self.rmempty) then
- if not(fvalue == self:cfgvalue(section)) then
+ if fexists then
+ local fvalue = self:formvalue(section) and self.enabled or self.disabled
+ if fvalue ~= self.default or (not self.optional and not self.rmempty) then
self:write(section, fvalue)
+ else
+ self:remove(section)
end
else
self:remove(section)
end
end
+function Flag.cfgvalue(self, section)
+ return AbstractValue.cfgvalue(self, section) or self.default
+end
--[[
end
function DynamicList.write(self, section, value)
- if self.cast == "string" and type(value) == "table" then
- value = table.concat(value, " ")
- elseif self.cast == "table" and type(value) == "string" then
- local x, t = { }
- for x in value:gmatch("%S+") do
- t[#t+1] = x
+ local t = { }
+
+ if type(value) == "table" then
+ local x
+ for _, x in ipairs(value) do
+ if x and #x > 0 then
+ t[#t+1] = x
+ end
end
+ else
+ t = { value }
+ end
+
+ if self.cast == "string" then
+ value = table.concat(t, " ")
+ else
value = t
end
local x
local t = { }
for x in value:gmatch("%S+") do
- t[#t+1] = x
+ if #x > 0 then
+ t[#t+1] = x
+ end
end
value = t
end
local value = AbstractValue.formvalue(self, section)
if type(value) == "string" then
- local x
- local t = { }
- for x in value:gmatch("%S+") do
- t[#t+1] = x
+ if self.cast == "string" then
+ local x
+ local t = { }
+ for x in value:gmatch("%S+") do
+ t[#t+1] = x
+ end
+ value = t
+ else
+ value = { value }
end
- value = t
end
return value