2 FFLuCI - Configuration Bind Interface
5 Offers an interface for binding confiugration values to certain
6 data types. Supports value and range validation and basic dependencies.
12 Copyright 2008 Steven Barth <steven@midlink.org>
14 Licensed under the Apache License, Version 2.0 (the "License");
15 you may not use this file except in compliance with the License.
16 You may obtain a copy of the License at
18 http://www.apache.org/licenses/LICENSE-2.0
20 Unless required by applicable law or agreed to in writing, software
21 distributed under the License is distributed on an "AS IS" BASIS,
22 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 See the License for the specific language governing permissions and
24 limitations under the License.
27 module("ffluci.cbi", package.seeall)
29 require("ffluci.template")
30 require("ffluci.util")
31 require("ffluci.http")
32 require("ffluci.model.uci")
34 local Template = ffluci.template.Template
35 local class = ffluci.util.class
36 local instanceof = ffluci.util.instanceof
41 require("ffluci.i18n")
43 local cbidir = ffluci.fs.dirname(ffluci.util.__file__()) .. "model/cbi/"
44 local func = loadfile(cbidir..cbimap..".lua")
47 error("Unable to load CBI map: " .. cbimap)
51 ffluci.util.resfenv(func)
52 ffluci.util.updfenv(func, ffluci.cbi)
53 ffluci.util.extfenv(func, "translate", ffluci.i18n.translate)
57 if not instanceof(map, Map) then
58 error("CBI map returns no valid map object!")
65 -- Node pseudo abstract class
68 function Node.__init__(self, title, description)
70 self.title = title or ""
71 self.description = description or ""
72 self.template = "cbi/node"
75 function Node.append(self, obj)
76 table.insert(self.children, obj)
79 function Node.parse(self)
80 for k, child in ipairs(self.children) do
85 function Node.render(self)
86 ffluci.template.render(self.template, {self=self})
91 Map - A map describing a configuration file
95 function Map.__init__(self, config, ...)
96 Node.__init__(self, ...)
98 self.template = "cbi/map"
101 function Map.section(self, class, ...)
102 if instanceof(class, AbstractSection) then
103 local obj = class(...)
105 obj.config = self.config
109 error("class must be a descendent of AbstractSection")
113 function Map.read(self)
114 self.ucidata = self.ucidata or ffluci.model.uci.show(self.config)[self.config]
121 AbstractSection = class(Node)
123 function AbstractSection.__init__(self, sectiontype, ...)
124 Node.__init__(self, ...)
125 self.sectiontype = sectiontype
128 function AbstractSection.option(self, class, ...)
129 if instanceof(class, AbstractValue) then
130 local obj = class(...)
132 obj.config = self.config
136 error("class must be a descendent of AbstractValue")
143 NamedSection - A fixed configuration section defined by its name
145 NamedSection = class(AbstractSection)
147 function NamedSection.__init__(self, section, ...)
148 AbstractSection.__init__(self, ...)
149 self.template = "cbi/nsection"
151 self.section = section
154 function NamedSection.option(self, ...)
155 local obj = AbstractSection.option(self, ...)
156 obj.section = self.section
162 TypedSection - A (set of) configuration section(s) defined by the type
163 addremove: Defines whether the user can add/remove sections of this type
164 anonymous: Allow creating anonymous sections
165 valid: a table with valid names or a function returning nil if invalid
167 TypedSection = class(AbstractSection)
169 function TypedSection.__init__(self, ...)
170 AbstractSection.__init__(self, ...)
171 self.template = "cbi/tsection"
173 self.addremove = true
174 self.anonymous = false
180 AbstractValue - An abstract Value Type
181 null: Value can be empty
182 valid: A function returning the value if it is valid otherwise nil
183 depends: A table of option => value pairs of which one must be true
184 default: The default value
186 AbstractValue = class(Node)
188 function AbstractValue.__init__(self, option, ...)
189 Node.__init__(self, ...)
198 function AbstractValue.formvalue(self)
199 local key = "uci."..self.map.config.."."..self.section.."."..self.option
200 return ffluci.http.formvalue(key)
203 function AbstractValue.ucivalue(self)
204 return self.map:read()[self.section][self.option]
207 function AbstractValue.validate(self, value)
208 return ffluci.util.validate(value, nil, nil, self.valid)
211 function AbstractValue.write(self, value)
212 ffluci.model.uci.set(self.config, self.section, self.option, value)
217 Value - A one-line value
218 maxlength: The maximum length
219 isnumber: The value must be a valid (floating point) number
220 isinteger: The value must be a valid integer
222 Value = class(AbstractValue)
224 function Value.__init__(self, ...)
225 AbstractValue.__init__(self, ...)
226 self.template = "cbi/value"
229 self.isnumber = false
230 self.isinteger = false
235 ListValue - A one-line value predefined in a list
237 ListValue = class(AbstractValue)
239 function ListValue.__init__(self, ...)
240 AbstractValue.__init__(self, ...)
241 self.template = "cbi/lvalue"
246 function ListValue.addValue(self, key, val)