-- Loads a CBI map from given file, creating an environment and returns it
function load(cbimap, ...)
require("luci.fs")
- require("luci.i18n")
+ local i18n = require "luci.i18n"
require("luci.config")
require("luci.util")
local cbidir = luci.util.libpath() .. "/model/cbi/"
- local func, err = loadfile(cbidir..cbimap..".lua")
-
- if not func then
- return nil
- end
+ local func, err = loadfile(cbimap) or loadfile(cbidir..cbimap..".lua")
+ assert(func, err)
luci.i18n.loadc("cbi")
+ luci.i18n.loadc("uvl")
- luci.util.resfenv(func)
- 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 env = {
+ translate=i18n.translate,
+ translatef=i18n.translatef,
+ arg={...}
+ }
+
+ setfenv(func, setmetatable(env, {__index =
+ function(tbl, key)
+ return rawget(tbl, key) or _M[key] or _G[key]
+ end}))
local maps = {func()}
luci.uvl.STRICT_UNKNOWN_OPTIONS = false
luci.uvl.STRICT_UNKNOWN_SECTIONS = false
- local stat, err = node.map.validator:validate_section(node.config, name, co)
- if err then
- node.map.save = false
- if err:is(luci.uvl.errors.ERR_DEPENDENCY) then
- node.tag_deperror[name] = true
- else
- node.tag_invalid[name] = true
+ local function tag_fields(e)
+ if e.option and node.fields[e.option] then
+ node.fields[e.option].error = e
+ elseif e.childs then
+ for _, c in ipairs(e.childs) do tag_fields(c) end
end
- for i, v in ipairs(err.childs) do
- if v.option and node.fields[v.option] then
- if v:is(luci.uvl.errors.ERR_OPTION) then
- local suberr = v.childs and v.childs[1]
- if suberr:is(luci.uvl.errors.ERR_DEPENDENCY) then
- node.fields[v.option].tag_reqerror[name] = true
- elseif suberr:is(luci.uvl.errors.ERR_OPT_REQUIRED) then
- node.fields[v.option].tag_missing[name] = true
- node.tag_deperror[name] = true
- else
- node.fields[v.option].tag_invalid[name] = true
- end
- end
+ end
+
+ local function tag_section(e)
+ local s = { }
+ for _, c in ipairs(e.childs) do
+ if c.childs and not c:is(luci.uvl.errors.ERR_DEPENDENCY) then
+ table.insert( s, c.childs[1]:string() )
+ else
+ table.insert( s, c:string() )
end
end
+ if #s > 0 then node.error = s end
+ end
+
+ local stat, err = node.map.validator:validate_section(node.config, name, co)
+ if err then
+ node.map.save = false
+ tag_fields(err)
+ tag_section(err)
end
end
self.config = config
self.parsechain = {self.config}
self.template = "cbi/map"
+ self.apply_on_parse = nil
self.uci = uci.cursor()
self.save = true
if not self.uci:load(self.config) then
self.validator = luci.uvl.UVL()
self.scheme = self.validator:get_scheme(self.config)
-
+
end
function Map.get_scheme(self, sectiontype, option)
if luci.http.formvalue("cbi.apply") then
for i, config in ipairs(self.parsechain) do
self.uci:commit(config)
- self.uci:apply(config)
-
+
-- Refresh data because commit changes section names
self.uci:load(config)
end
-
+ if self.apply_on_parse then
+ self.uci:apply(self.parsechain)
+ else
+ self._apply = function()
+ local cmd = self.uci:apply(self.parsechain, true)
+ return io.popen(cmd)
+ end
+ end
+
-- Reparse sections
Node.parse(self, ...)
-
+
end
for i, config in ipairs(self.parsechain) do
self.uci:unload(config)
end
end
+function Map.render(self, ...)
+ Node.render(self, ...)
+ if self._apply then
+ local fp = self._apply()
+ fp:read("*a")
+ fp:close()
+ end
+end
+
-- Creates a child section
function Map.section(self, class, ...)
if instanceof(class, AbstractSection) then
function NamedSection.__init__(self, map, section, stype, ...)
AbstractSection.__init__(self, map, stype, ...)
Node._i18n(self, map.config, section, nil, ...)
-
+
-- Defaults
self.addremove = false
AbstractSection.parse_dynamic(self, s)
if luci.http.formvalue("cbi.submit") then
Node.parse(self, s)
-
+
if not self.override_scheme and self.map.scheme then
_uvl_validate_section(self, s)
end
local crval = REMOVE_PREFIX .. self.config
local name = luci.http.formvaluetable(crval)
for k,v in pairs(name) do
+ if k:sub(-2) == ".x" then
+ k = k:sub(1, #k - 2)
+ end
if self:cfgvalue(k) and self:checkscope(k) then
self:remove(k)
end
AbstractSection.parse_dynamic(self, k)
if luci.http.formvalue("cbi.submit") then
Node.parse(self, k)
-
+
if not self.override_scheme and self.map.scheme then
_uvl_validate_section(self, k)
end
if self.addremove then
-- Create
+ local created
local crval = CREATE_PREFIX .. self.config .. "." .. self.sectiontype
local name = luci.http.formvalue(crval)
if self.anonymous then
if name then
- self:create()
+ created = self:create()
end
else
if name then
end
if name and #name > 0 then
- self:create(name)
+ created = self:create(name) and name
end
end
end
+
+ if created then
+ AbstractSection.parse_optionals(self, created)
+ end
end
end
self.cast = (vs.type == "list") and "list" or "string"
self.title = self.title or vs.title
self.description = self.description or vs.descr
+ self.default = vs.default
if vs.depends and not self.override_dependencies then
for i, deps in ipairs(vs.depends) do
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) then
+ 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
table.insert(valid, v)
end
end