libs/core: bring get_first() boolean casting in line with get_bool()
[project/luci.git] / libs / core / luasrc / model / uci.lua
index 66bd0a0..e42856b 100644 (file)
@@ -30,8 +30,9 @@ local table = require "table"
 
 
 local setmetatable, rawget, rawset = setmetatable, rawget, rawset
-local error, pairs, ipairs, tostring = error, pairs, ipairs, tostring
-local require, getmetatable, type = require, getmetatable, type
+local require, getmetatable = require, getmetatable
+local error, pairs, ipairs = error, pairs, ipairs
+local type, tostring, tonumber = type, tostring, tonumber
 
 --- LuCI UCI model library.
 -- The typical workflow for UCI is:  Get a cursor instance from the
@@ -167,6 +168,35 @@ function Cursor.get_list(self, config, section, option)
        return nil
 end
 
+--- Get the given option from the first section with the given type.
+-- @param config       UCI config
+-- @param type         UCI section type
+-- @param option       UCI option (optional)
+-- @param default      Default value (optional)
+-- @return                     UCI value
+function Cursor.get_first(self, conf, stype, opt, def)
+       local rv = def
+
+       self:foreach(conf, stype,
+               function(s)
+                       local val = not opt and s['.name'] or s[opt]
+
+                       if type(def) == "number" then
+                               val = tonumber(val)
+                       elseif type(def) == "boolean" then
+                               val = (val == "1" or val == "true" or
+                                      val == "yes" or val == "on")
+                       end
+
+                       if val ~= nil then
+                               rv = val
+                               return false
+                       end
+               end)
+
+       return rv
+end
+
 --- Set given values as list.
 -- @param config       UCI config
 -- @param section      UCI section name
@@ -227,6 +257,32 @@ function Cursor._affected(self, configlist)
        return reloadlist
 end
 
+--- Create a sub-state of this cursor. The sub-state is tied to the parent
+-- curser, means it the parent unloads or loads configs, the sub state will
+-- do so as well.
+-- @return                     UCI state cursor tied to the parent cursor
+function Cursor.substate(self)
+       Cursor._substates = Cursor._substates or { }
+       Cursor._substates[self] = Cursor._substates[self] or cursor_state()
+       return Cursor._substates[self]
+end
+
+local _load = Cursor.load
+function Cursor.load(self, ...)
+       if Cursor._substates and Cursor._substates[self] then
+               _load(Cursor._substates[self], ...)
+       end
+       return _load(self, ...)
+end
+
+local _unload = Cursor.unload
+function Cursor.unload(self, ...)
+       if Cursor._substates and Cursor._substates[self] then
+               _unload(Cursor._substates[self], ...)
+       end
+       return _unload(self, ...)
+end
+
 
 --- Add an anonymous section.
 -- @class function