X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fluci.git;a=blobdiff_plain;f=libs%2Fcbi%2Fluasrc%2Fcbi.lua;h=ff33604254f745148659ef4eccf6669fc7960ff4;hp=7370a04c46a0858468b7e7f6d85fbb66d2582415;hb=e72a526984982f6fa2b6f2ed5ce01523094bfe43;hpb=d0a622dce8163cb1f9d0a178127b7abda6c4e818 diff --git a/libs/cbi/luasrc/cbi.lua b/libs/cbi/luasrc/cbi.lua index 7370a04c4..ff3360425 100644 --- a/libs/cbi/luasrc/cbi.lua +++ b/libs/cbi/luasrc/cbi.lua @@ -37,13 +37,13 @@ local instanceof = luci.util.instanceof -- 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 @@ -56,6 +56,7 @@ function load(cbimap) 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()} @@ -144,17 +145,44 @@ function Map.__init__(self, config, ...) 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 @@ -214,6 +242,7 @@ function AbstractSection.__init__(self, map, sectiontype, ...) self.map = map self.config = map.config self.optionals = {} + self.defaults = {} self.optional = true self.addremove = false @@ -303,7 +332,28 @@ end -- Creates the section function AbstractSection.create(self, section) - return 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 + if v.default then + self.map:set(section, v.option, v.default) + end + end + + for k,v in pairs(self.defaults) do + self.map:set(section, k, v) + end + end + + return stat end @@ -316,7 +366,7 @@ NamedSection = class(AbstractSection) function NamedSection.__init__(self, map, section, type, ...) AbstractSection.__init__(self, map, type, ...) Node._i18n(self, map.config, section, nil, ...) - + self.template = "cbi/nsection" self.section = section self.addremove = false @@ -334,10 +384,9 @@ function NamedSection.parse(self) 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 @@ -366,7 +415,6 @@ function TypedSection.__init__(self, map, type, ...) self.template = "cbi/tsection" self.deps = {} - self.excludes = {} self.anonymous = false end @@ -378,37 +426,17 @@ function TypedSection.cfgsections(self) function (section) if self:checkscope(section[".name"]) then table.insert(sections, section[".name"]) - end + end end) return sections end --- Creates a new section of this type with the given name (or anonymous) -function TypedSection.create(self, name) - if name then - self.map:set(name, nil, self.sectiontype) - else - name = self.map:add(self.sectiontype) - end - - for k,v in pairs(self.children) do - if v.default then - self.map:set(name, v.option, v.default) - end - end -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 @@ -459,7 +487,7 @@ end -- 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 @@ -554,7 +582,28 @@ function AbstractValue.render(self, s, scope) if not self.optional or self:cfgvalue(s) or self:formcreated(s) then scope = scope or {} scope.section = s - + scope.cbid = "cbid." .. self.config .. + "." .. s .. + "." .. self.option + + scope.ifattr = function(cond,key,val) + if cond then + return string.format( + ' %s="%s"', tostring(key), + 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 + Node.render(self, scope) end end @@ -591,17 +640,14 @@ Value = class(AbstractValue) 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 @@ -618,10 +664,6 @@ function DummyValue.parse(self) end -function DummyValue.render(self, s) - luci.template.render(self.template, {self=self, section=s}) -end - --[[ Flag - A flag being enabled or disabled @@ -731,7 +773,7 @@ function MultiValue.valuelist(self, section) end function MultiValue.validate(self, val) - val = (type(val) == "table") and val or {val} + val = (type(val) == "table") and val or {val} local result