luci-base: support option aliases in luci.cbi

AbstractValue descendants may now specify a new optional property `alias`
which refers to a uci option to read/write/remove that differs from the
option name itself.

This is mainly useful for widgets that are toggled based on dependencies,
e.g. for alternating between SingleValue and MultiValue, but which are
intented to write into the same uci option.

Such a setup was previously possible already by overriding the .cfgvalue(),
.write() and .remove() callbacks with custom implementations, but that
required a lot of boiler plate code and was rather fragile.

With the `alias` property, CBI now takes care of the details and tracks
aliased fields within a section accordingly.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
Jo-Philipp Wich 2018-06-07 08:49:51 +02:00
parent 501f1a9008
commit 4cca96ef09

View file

@ -1417,6 +1417,12 @@ function AbstractValue.parse(self, section, novld)
self:add_error(section, "invalid", val_err)
end
if self.alias then
self.section.aliased = self.section.aliased or {}
self.section.aliased[section] = self.section.aliased[section] or {}
self.section.aliased[section][self.alias] = true
end
if fvalue and (self.forcewrite or not (fvalue == cvalue)) then
if self:write(section, fvalue) then
-- Push events
@ -1426,10 +1432,16 @@ function AbstractValue.parse(self, section, novld)
end
else -- Unset the UCI or error
if self.rmempty or self.optional then
if self:remove(section) then
-- Push events
self.section.changed = true
--luci.util.append(self.map.events, self.events)
if not self.alias or
not self.section.aliased or
not self.section.aliased[section] or
not self.section.aliased[section][self.alias]
then
if self:remove(section) then
-- Push events
self.section.changed = true
--luci.util.append(self.map.events, self.events)
end
end
elseif cvalue ~= fvalue and not novld then
-- trigger validator with nil value to get custom user error msg.
@ -1455,7 +1467,7 @@ function AbstractValue.cfgvalue(self, section)
if self.tag_error[section] then
value = self:formvalue(section)
else
value = self.map:get(section, self.option)
value = self.map:get(section, self.alias or self.option)
end
if not value then
@ -1496,12 +1508,12 @@ AbstractValue.transform = AbstractValue.validate
-- Write to UCI
function AbstractValue.write(self, section, value)
return self.map:set(section, self.option, value)
return self.map:set(section, self.alias or self.option, value)
end
-- Remove from UCI
function AbstractValue.remove(self, section)
return self.map:del(section, self.option)
return self.map:del(section, self.alias or self.option)
end