* libs/cbi: Fixed a bug which prevented creation of non-anonymous sections
[project/luci.git] / libs / cbi / luasrc / cbi.lua
index 31fa8bf..2e788be 100644 (file)
@@ -31,9 +31,11 @@ require("luci.util")
 require("luci.http")
 require("luci.model.uci")
 
+local uci        = luci.model.uci
 local class      = luci.util.class
 local instanceof = luci.util.instanceof
 
+
 -- Loads a CBI map from given file, creating an environment and returns it
 function load(cbimap)
        require("luci.fs")
@@ -141,27 +143,22 @@ function Map.__init__(self, config, ...)
 
        self.config = config
        self.template = "cbi/map"
-       self.uci = luci.model.uci.Session()
-       self.ucidata, self.uciorder = self.uci:sections(self.config)
-       if not self.ucidata or not self.uciorder then
+       if not uci.load(self.config) then
                error("Unable to read UCI data: " .. self.config)
        end
 end
 
 -- Use optimized UCI writing
 function Map.parse(self, ...)
-       self.uci:t_load(self.config)
        Node.parse(self, ...)
-       self.uci:t_save(self.config)
+       uci.save(self.config)
+       uci.unload(self.config)
 end
 
 -- Creates a child section
-function Map.section(self, class, section, ...)
+function Map.section(self, class, ...)
        if instanceof(class, AbstractSection) then
-               local obj  = class(self, section, ...)
-
-               Node._i18n(obj, self.config, section, nil, ...)
-
+               local obj  = class(self, ...)
                self:append(obj)
                return obj
        else
@@ -171,59 +168,35 @@ end
 
 -- UCI add
 function Map.add(self, sectiontype)
-       local name = self.uci:t_add(self.config, sectiontype)
-       if name then
-               self.ucidata[name] = {}
-               self.ucidata[name][".type"] = sectiontype
-               table.insert(self.uciorder, name)
-       end
-       return name
+       return uci.add(self.config, sectiontype)
 end
 
 -- UCI set
 function Map.set(self, section, option, value)
-       local stat = self.uci:t_set(self.config, section, option, value)
-       if stat then
-               local val = self.uci:t_get(self.config, section, option)
-               if option then
-                       self.ucidata[section][option] = val
-               else
-                       if not self.ucidata[section] then
-                               self.ucidata[section] = {}
-                       end
-                       self.ucidata[section][".type"] = val
-                       table.insert(self.uciorder, section)
-               end
+       if option then
+               return uci.set(self.config, section, option, value)
+       else
+               return uci.set(self.config, section, value)
        end
-       return stat
 end
 
 -- UCI del
 function Map.del(self, section, option)
-       local stat = self.uci:t_del(self.config, section, option)
-       if stat then
-               if option then
-                       self.ucidata[section][option] = nil
-               else
-                       self.ucidata[section] = nil
-                       for i, k in ipairs(self.uciorder) do
-                               if section == k then
-                                       table.remove(self.uciorder, i)
-                               end
-                       end
-               end
+       if option then
+               return uci.delete(self.config, section, option)
+       else
+               return uci.delete(self.config, section)
        end
-       return stat
 end
 
--- UCI get (cached)
+-- UCI get
 function Map.get(self, section, option)
        if not section then
-               return self.ucidata, self.uciorder
-       elseif option and self.ucidata[section] then
-               return self.ucidata[section][option]
+               return uci.get_all(self.config)
+       elseif option then
+               return uci.get(self.config, section, option)
        else
-               return self.ucidata[section]
+               return uci.get_all(self.config, section)
        end
 end
 
@@ -250,7 +223,7 @@ function AbstractSection.option(self, class, option, ...)
        if instanceof(class, AbstractValue) then
                local obj  = class(self.map, option, ...)
 
-               Node._i18n(obj, self.config, self.section, option, ...)
+               Node._i18n(obj, self.config, self.section or self.sectiontype, option, ...)
 
                self:append(obj)
                return obj
@@ -338,10 +311,11 @@ NamedSection - A fixed configuration section defined by its name
 ]]--
 NamedSection = class(AbstractSection)
 
-function NamedSection.__init__(self, map, section, ...)
-       AbstractSection.__init__(self, map, ...)
+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
 end
@@ -384,8 +358,10 @@ TypedSection - A (set of) configuration section(s) defined by the type
 ]]--
 TypedSection = class(AbstractSection)
 
-function TypedSection.__init__(self, ...)
-       AbstractSection.__init__(self, ...)
+function TypedSection.__init__(self, map, type, ...)
+       AbstractSection.__init__(self, map, type, ...)
+       Node._i18n(self, map.config, type, nil, ...)
+
        self.template  = "cbi/tsection"
        self.deps = {}
        self.excludes = {}
@@ -396,15 +372,12 @@ end
 -- Return all matching UCI sections for this TypedSection
 function TypedSection.cfgsections(self)
        local sections = {}
-       local map, order = self.map:get()
-
-       for i, k in ipairs(order) do
-               if map[k][".type"] == self.sectiontype then
-                       if self:checkscope(k) then
-                               table.insert(sections, k)
-                       end
-               end
-       end
+       uci.foreach(self.map.config, self.sectiontype,
+               function (section)
+                       if self:checkscope(section[".name"]) then
+                               table.insert(sections, section[".name"])
+                       end 
+               end)
 
        return sections
 end
@@ -579,6 +552,7 @@ 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
+               
                Node.render(self, scope)
        end
 end
@@ -609,9 +583,6 @@ end
 --[[
 Value - A one-line value
        maxlength:      The maximum length
-       isnumber:       The value must be a valid (floating point) number
-       isinteger:  The value must be a valid integer
-       ispositive: The value must be positive (and a number)
 ]]--
 Value = class(AbstractValue)
 
@@ -620,8 +591,6 @@ function Value.__init__(self, ...)
        self.template  = "cbi/value"
 
        self.maxlength  = nil
-       self.isnumber   = false
-       self.isinteger  = false
 end
 
 -- This validation is a bit more complex
@@ -630,7 +599,7 @@ function Value.validate(self, val)
                val = nil
        end
 
-       return luci.util.validate(val, self.isnumber, self.isinteger)
+       return val
 end
 
 
@@ -735,6 +704,14 @@ function MultiValue.__init__(self, ...)
        self.delimiter = " "
 end
 
+function MultiValue.render(self, ...)
+       if self.widget == "select" and not self.size then
+               self.size = #self.vallist
+       end
+
+       AbstractValue.render(self, ...)
+end
+
 function MultiValue.value(self, key, val)
        val = val or key
        table.insert(self.keylist, tostring(key))