libs/uci: add luci.model.uci.bind class for easier oop-uci integration
[project/luci.git] / libs / uci / luasrc / model / uci / bind.lua
1 --[[
2 LuCI - UCI utilities for model classes
3
4 Copyright 2009 Jo-Philipp Wich <xm@subsignal.org>
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17
18 ]]--
19
20 local assert, pairs, type = assert, pairs, type
21 local utl = require "luci.util"
22
23 module "luci.model.uci.bind"
24
25 bind = utl.class()
26
27 function bind.__init__(self, config, cursor)
28 assert(config, "call to bind() without config file")
29 self.cfg = config
30 self.uci = cursor
31 end
32
33 function bind.init(self, cursor)
34 assert(cursor, "call to init() without uci cursor")
35 self.uci = cursor
36 end
37
38 function bind.section(self, stype)
39 local x = utl.class(bsection)
40 x.__init__ = function(inst, sid)
41 assert(self.uci:get(self.cfg, sid) == stype,
42 "attempt to instantiate bsection(%q) of wrong type, expected %q"
43 % { sid, stype })
44
45 inst.bind = self
46 inst.stype = stype
47 inst.sid = sid
48 end
49 return x
50 end
51
52 function bind.usection(self, stype)
53 local x = utl.class(bsection)
54 x.__init__ = function(inst)
55 inst.bind = self
56 inst.stype = stype
57 inst.sid = true
58 end
59 return x()
60 end
61
62 function bind.list(self, list, add, rem)
63 local lookup = { }
64
65 if type(list) == "string" then
66 local item
67 for item in list:gmatch("%S+") do
68 lookup[item] = true
69 end
70
71 elseif type(list) == "table" then
72 local item
73 for _, item in pairs(list) do
74 lookup[item] = true
75 end
76 end
77
78 if add then lookup[add] = true end
79 if rem then lookup[rem] = nil end
80
81 return utl.keys(lookup)
82 end
83
84 function bind.bool(self, v)
85 return ( v == "1" or v == "true" or v == "yes" or v == "on" )
86 end
87
88
89 bsection = utl.class()
90
91 function bsection.uciop(self, op, ...)
92 assert(self.bind and self.bind.uci,
93 "attempt to use unitialized binding: " .. type(self.sid))
94
95 return op and self.bind.uci[op](self.bind.uci, self.bind.cfg, ...)
96 or self.bind.uci
97 end
98
99 function bsection.get(self, k, c)
100 local v
101 self:uciop("foreach", self.stype,
102 function(s)
103 if type(c) == "table" then
104 local ck, cv
105 for ck, cv in pairs(c) do
106 if s[ck] ~= cv then return true end
107 end
108 elseif type(c) == "string" and s['.name'] ~= c then
109 return true
110 end
111 if k ~= nil then
112 v = s[k]
113 else
114 v = s
115 end
116 return false
117 end)
118 return v
119 end
120
121 function bsection.set(self, k, v, c)
122 local stat
123 self:uciop("foreach", self.stype,
124 function(s)
125 if type(c) == "table" then
126 local ck, cv
127 for ck, cv in pairs(c) do
128 if s[ck] ~= cv then return true end
129 end
130 elseif type(c) == "string" and s['.name'] ~= c then
131 return true
132 end
133 stat = self:uciop("set", c, k, v)
134 return false
135 end)
136 return stat or false
137 end
138
139 function bsection.property(self, k, n)
140 self[n or k] = function(c, val)
141 if val == nil then
142 return c:get(k, c.sid)
143 else
144 return c:set(k, val, c.sid)
145 end
146 end
147 end
148
149 function bsection.property_bool(self, k, n)
150 self[n or k] = function(c, val)
151 if val == nil then
152 return self.bind:bool(c:get(k, c.sid))
153 else
154 return c:set(k, self.bind:bool(val) and "1" or "0", c.sid)
155 end
156 end
157 end
158