-- Loads a CBI map from given file, creating an environment and returns it
-function load(cbimap)
+function load(cbimap, ...)
require("luci.fs")
require("luci.i18n")
require("luci.config")
- require("luci.sys")
+ require("luci.util")
- local cbidir = luci.sys.libpath() .. "/model/cbi/"
+ local cbidir = luci.util.libpath() .. "/model/cbi/"
local func, err = loadfile(cbidir..cbimap..".lua")
if not func then
luci.util.updfenv(func, luci.cbi)
luci.util.extfenv(func, "translate", luci.i18n.translate)
luci.util.extfenv(func, "translatef", luci.i18n.translatef)
+ luci.util.extfenv(func, "arg", {...})
local maps = {func()}
Node._i18n(self, config, nil, nil, ...)
self.config = config
+ self.parsechain = {self.config}
self.template = "cbi/map"
if not uci.load(self.config) then
error("Unable to read UCI data: " .. self.config)
end
end
+
+-- Chain foreign config
+function Map.chain(self, config)
+ table.insert(self.parsechain, config)
+end
+
-- Use optimized UCI writing
function Map.parse(self, ...)
Node.parse(self, ...)
- uci.save(self.config)
- uci.unload(self.config)
+ for i, config in ipairs(self.parsechain) do
+ uci.save(config)
+ end
+ if luci.http.formvalue("cbi.apply") then
+ for i, config in ipairs(self.parsechain) do
+ uci.commit(config)
+ if luci.config.uci_oncommit and luci.config.uci_oncommit[config] then
+ luci.util.exec(luci.config.uci_oncommit[config])
+ end
+
+ -- Refresh data because commit changes section names
+ uci.unload(config)
+ uci.load(config)
+ end
+
+ -- Reparse sections
+ Node.parse(self, ...)
+
+ end
+ for i, config in ipairs(self.parsechain) do
+ uci.unload(config)
+ end
end
-- Creates a child section
-- Creates the section
function AbstractSection.create(self, section)
- local stat = self.map:set(section, nil, self.sectiontype)
+ local stat
+
+ if section then
+ stat = self.map:set(section, nil, self.sectiontype)
+ else
+ section = self.map:add(self.sectiontype)
+ stat = section
+ end
if stat then
for k,v in pairs(self.children) do
return
end
else -- Create and apply default values
- if luci.http.formvalue("cbi.cns."..path) and self:create(s) then
- for k,v in pairs(self.children) do
- v:write(s, v.default)
- end
+ if luci.http.formvalue("cbi.cns."..path) then
+ self:create(s)
+ return
end
end
end
self.template = "cbi/tsection"
self.deps = {}
- self.excludes = {}
self.anonymous = false
end
return sections
end
--- Creates a new section of this type with the given name (or anonymous)
-function TypedSection.create(self, name)
- name = name or self.map:add(self.sectiontype)
- AbstractSection.create(self, name)
-end
-
-- Limits scope to sections that have certain option => value pairs
function TypedSection.depends(self, option, value)
table.insert(self.deps, {option=option, value=value})
end
--- Excludes several sections by name
-function TypedSection.exclude(self, field)
- self.excludes[field] = true
-end
-
function TypedSection.parse(self)
if self.addremove then
-- Create
-- Verifies scope of sections
function TypedSection.checkscope(self, section)
-- Check if we are not excluded
- if self.excludes[section] then
+ if self.filter and not self.filter(section) then
return nil
end
if cond then
return string.format(
' %s="%s"', tostring(key),
- tostring( val or scope[key] or self[key] or "" )
+ tostring( val
+ or scope[key]
+ or (type(self[key]) ~= "function" and self[key])
+ or "" )
)
else
return ''
function Value.__init__(self, ...)
AbstractValue.__init__(self, ...)
self.template = "cbi/value"
-
- self.maxlength = nil
+ self.keylist = {}
+ self.vallist = {}
end
--- This validation is a bit more complex
-function Value.validate(self, val)
- if self.maxlength and tostring(val):len() > self.maxlength then
- val = nil
- end
-
- return val
+function Value.value(self, key, val)
+ val = val or key
+ table.insert(self.keylist, tostring(key))
+ table.insert(self.vallist, tostring(val))
end
end
-function DummyValue.render(self, s)
- luci.template.render(self.template, {self=self, section=s})
-end
-
--[[
Flag - A flag being enabled or disabled