libs/cbi: Prevent SimpleForms from prematurely parsing form data
[project/luci.git] / libs / cbi / luasrc / cbi.lua
index 0ec2ff815de7095fe94c56fefc5ac6ff9498d62c..9996c8418dc27962d630d4ec41273c3d52194ec0 100644 (file)
@@ -39,6 +39,9 @@ FORM_NODATA  =  0
 FORM_VALID   =  1
 FORM_INVALID = -1
 
+CREATE_PREFIX = "cbi.cts."
+REMOVE_PREFIX = "cbi.rts."
+
 -- Loads a CBI map from given file, creating an environment and returns it
 function load(cbimap, ...)
        require("luci.fs")
@@ -137,6 +140,10 @@ function Template.__init__(self, template)
        self.template = template
 end
 
+function Template.render(self)
+       luci.template.render(self.template, {self=self})
+end
+
 
 --[[
 Map - A map describing a configuration file
@@ -233,6 +240,11 @@ function Map.get(self, section, option)
        end
 end
 
+-- UCI stateget
+function Map.stateget(self, section, option)
+       return uci.get_statevalue(self.config, section, option)
+end
+
 
 --[[
 SimpleForm - A Simple non-UCI form
@@ -248,11 +260,15 @@ function SimpleForm.__init__(self, config, title, description, data)
 end
 
 function SimpleForm.parse(self, ...)
-       Node.parse(self, 1, ...)
+       if luci.http.formvalue("cbi.submit") then
+               Node.parse(self, 1, ...)
+       end
                
        local valid = true
        for i, v in ipairs(self.children) do
-               valid = valid and not v.tag_missing[1] and not v.tag_invalid[1]
+               valid = valid 
+                and (not v.tag_missing or not v.tag_missing[1])
+                and (not v.tag_invalid or not v.tag_invalid[1])
        end
        
        local state = 
@@ -260,7 +276,7 @@ function SimpleForm.parse(self, ...)
                or valid and 1
                or -1
 
-       self.dorender = self:handle(state)
+       self.dorender = self:handle(state, self.data)
 end
 
 function SimpleForm.render(self, ...)
@@ -273,6 +289,7 @@ end
 function SimpleForm.field(self, class, ...)
        if instanceof(class, AbstractValue) then
                local obj  = class(self, ...)
+               obj.track_missing = true
                self:append(obj)
                return obj
        else
@@ -505,7 +522,7 @@ end
 function TypedSection.parse(self)
        if self.addremove then
                -- Create
-               local crval = "cbi.cts." .. self.config .. "." .. self.sectiontype
+               local crval = CREATE_PREFIX .. self.config .. "." .. self.sectiontype
                local name  = luci.http.formvalue(crval)
                if self.anonymous then
                        if name then
@@ -531,7 +548,7 @@ function TypedSection.parse(self)
                end
 
                -- Remove
-               crval = "cbi.rts." .. self.config
+               crval = REMOVE_PREFIX .. self.config
                name = luci.http.formvaluetable(crval)
                for k,v in pairs(name) do
                        if self:cfgvalue(k) and self:checkscope(k) then
@@ -602,10 +619,12 @@ function AbstractValue.__init__(self, map, option, ...)
        self.tag_missing = {}
        self.deps = {}
 
+       self.track_missing = false
        self.rmempty   = false
        self.default   = nil
        self.size      = nil
        self.optional  = false
+       self.stateful  = false
 end
 
 -- Add a dependencie to another section field
@@ -638,17 +657,17 @@ function AbstractValue.parse(self, section)
        local cvalue = self:cfgvalue(section)
 
        if fvalue and fvalue ~= "" then -- If we have a form value, write it to UCI
-               fvalue = self:transform(self:validate(fvalue))
+               fvalue = self:transform(self:validate(fvalue, section))
                if not fvalue then
                        self.tag_invalid[section] = true
                end
-               if fvalue and not (fvalue == self:cfgvalue(section)) then
+               if fvalue and not (fvalue == cvalue) then
                        self:write(section, fvalue)
                end
        else                                                    -- Unset the UCI or error
                if self.rmempty or self.optional then
                        self:remove(section)
-               elseif not fvalue or fvalue ~= cvalue then
+               elseif self.track_missing and not fvalue or fvalue ~= cvalue then
                        self.tag_missing[section] = true
                end
        end
@@ -687,7 +706,9 @@ end
 
 -- Return the UCI value of this object
 function AbstractValue.cfgvalue(self, section)
-       return self.map:get(section, self.option)
+       return self.stateful
+        and self.map:stateget(section, self.option)
+        or  self.map:get(section, self.option)
 end
 
 -- Validate the form value
@@ -865,3 +886,14 @@ function MultiValue.validate(self, val)
 
        return result
 end
+
+--[[
+TextValue - A multi-line value
+       rows:   Rows
+]]--
+TextValue = class(AbstractValue)
+
+function TextValue.__init__(self, ...)
+       AbstractValue.__init__(self, ...)
+       self.template  = "cbi/tvalue"
+end