* ffluci.cbi: updates
authorSteven Barth <steven@midlink.org>
Fri, 21 Mar 2008 19:30:53 +0000 (19:30 +0000)
committerSteven Barth <steven@midlink.org>
Fri, 21 Mar 2008 19:30:53 +0000 (19:30 +0000)
* ffluci.template: fixed a bug where different template scopes were not separated correctly
* Added ffluci.dispatcher.cbi and ffluci.dispatcher.dynamic

src/ffluci/cbi.lua
src/ffluci/controller/public/index.lua
src/ffluci/dispatcher.lua
src/ffluci/template.lua
src/ffluci/util.lua
src/ffluci/view/cbi/lvalue.htm
src/ffluci/view/cbi/map.htm
src/ffluci/view/cbi/nsection.htm
src/ffluci/view/cbi/tsection.htm
src/ffluci/view/cbi/value.htm

index 149c1d70fae4b071079cb2ad5c78fd1601d28fcc..5a20aadc53765dd01a9b5240d50e6802ac2c25ed 100644 (file)
@@ -25,22 +25,50 @@ limitations under the License.
 
 ]]--
 module("ffluci.cbi", package.seeall)
+
 require("ffluci.template")
 require("ffluci.util")
 require("ffluci.http")
 require("ffluci.model.uci")
-local Template = ffluci.template.Template
-local class = ffluci.util.class
+
+local Template   = ffluci.template.Template
+local class      = ffluci.util.class
 local instanceof = ffluci.util.instanceof
 
 
+function load(cbimap)
+       require("ffluci.fs")
+       require("ffluci.i18n")
+       
+       local cbidir = ffluci.fs.dirname(ffluci.util.__file__()) .. "model/cbi/"
+       local func = loadfile(cbidir..cbimap..".lua")
+       
+       if not func then
+               error("Unable to load CBI map: " .. cbimap)
+               return nil
+       end
+       
+       ffluci.util.resfenv(func)
+       ffluci.util.updfenv(func, ffluci.cbi)
+       ffluci.util.extfenv(func, "translate", ffluci.i18n.translate)
+       
+       local map = func()
+       
+       if not instanceof(map, Map) then
+               error("CBI map returns no valid map object!")
+               return nil
+       end
+       
+       return map
+end
+
 -- Node pseudo abstract class
 Node = class()
 
 function Node.__init__(self, title, description)
        self.children = {}
-       self.title = title
-       self.description = description
+       self.title = title or ""
+       self.description = description or ""
        self.template = "cbi/node"
 end
 
@@ -55,7 +83,7 @@ function Node.parse(self)
 end
 
 function Node.render(self)
-       ffluci.template.render(self.template)
+       ffluci.template.render(self.template, {self=self})
 end
 
 
@@ -83,7 +111,7 @@ function Map.section(self, class, ...)
 end
 
 function Map.read(self)
-       self.ucidata = self.ucidata or ffluci.model.uci.show(self.config)
+       self.ucidata = self.ucidata or ffluci.model.uci.show(self.config)[self.config]
        return self.ucidata
 end
 
@@ -173,7 +201,7 @@ function AbstractValue.formvalue(self)
 end
 
 function AbstractValue.ucivalue(self)
-       return self.map.read()[self.section][self.option]
+       return self.map:read()[self.section][self.option]
 end
 
 function AbstractValue.validate(self, value)
index 9ca70f56c1e90da3b9cf8f212d72476e5eadbb2a..4f8160a4c90b1dcc5a4566f300ea076f7398bed0 100644 (file)
@@ -1,2 +1 @@
-module(..., package.seeall)
-dispatcher = require("ffluci.dispatcher").simpleview
\ No newline at end of file
+module(..., package.seeall)
\ No newline at end of file
index d2998aa493034380dd883bc87b3ab33c3b744981..0f05c3d1730472759040bd30c6fa192c6d690a7e 100644 (file)
@@ -95,6 +95,7 @@ function dispatch(req)
                return error404()
        else
                module.request = request
+               module.dispatcher = module.dispatcher or dynamic
                setfenv(module.dispatcher, module)
                return module.dispatcher(request)
        end     
@@ -139,30 +140,85 @@ function httpdispatch()
        dispatch({category=cat, module=mod, action=act})
 end
 
--- The Simple View Dispatcher directly renders the template
--- which is placed in ffluci/views/"request.module"/"request.action" 
-function simpleview(request)
+
+-- Dispatchers --
+
+
+-- The Action Dispatcher searches the module for any function called
+-- action_"request.action" and calls it
+function action(request)
        local i18n = require("ffluci.i18n")
-       local tmpl = require("ffluci.template")
        local disp = require("ffluci.dispatcher")
        
        i18n.loadc(request.module)
-       if not pcall(tmpl.render, request.module .. "/" .. request.action) then
+       local action = getfenv()["action_" .. request.action:gsub("-", "_")]
+       if action then
+               action()
+       else
                disp.error404()
        end
 end
 
--- The Action Dispatcher searches the module for any function called
--- action_"request.action" and calls it
-function action(request)
+-- The CBI dispatcher directly parses and renders the CBI map which is
+-- placed in ffluci/modles/cbi/"request.module"/"request.action" 
+function cbi(request)
        local i18n = require("ffluci.i18n")
        local disp = require("ffluci.dispatcher")
+       local tmpl = require("ffluci.template")
+       local cbi  = require("ffluci.cbi")
        
        i18n.loadc(request.module)
+       
+       stat, map = pcall(cbi.load, request.module.."/"..request.action)
+       if stat then
+               tmpl.render("header")
+               map:render()
+               tmpl.render("footer")
+       else
+               disp.error404()
+       end
+end
+
+-- The dynamic dispatchers combines the action, simpleview and cbi dispatchers
+-- in one dispatcher. It tries to lookup the request in this order.
+function dynamic(request)
+       local i18n = require("ffluci.i18n")
+       local disp = require("ffluci.dispatcher")
+       local tmpl = require("ffluci.template")
+       local cbi  = require("ffluci.cbi")      
+       
+       i18n.loadc(request.module)
+       
        local action = getfenv()["action_" .. request.action:gsub("-", "_")]
        if action then
                action()
-       else
+               return
+       end
+       
+       if pcall(tmpl.render, request.module .. "/" .. request.action) then
+               return
+       end
+       
+       stat, map = pcall(cbi.load, request.module.."/"..request.action)
+       if stat then
+               tmpl.render("header")
+               map:render()
+               tmpl.render("footer")
+               return
+       end     
+       
+       disp.error404()
+end
+
+-- The Simple View Dispatcher directly renders the template
+-- which is placed in ffluci/views/"request.module"/"request.action" 
+function simpleview(request)
+       local i18n = require("ffluci.i18n")
+       local tmpl = require("ffluci.template")
+       local disp = require("ffluci.dispatcher")
+       
+       i18n.loadc(request.module)
+       if not pcall(tmpl.render, request.module .. "/" .. request.action) then
                disp.error404()
        end
 end
\ No newline at end of file
index 00145a0a02cf99436deb8efd859278a9094feff8..18265a4a16d82fe4325d792d00a03e2b85de5cbe 100644 (file)
@@ -124,12 +124,13 @@ function compile(template)
 end
 
 -- Oldstyle render shortcut
-function render(name, ...)
+function render(name, scope, ...)
+       scope = scope or getfenv(2)
        local s, t = pcall(Template, name)
        if not s then
                error("Unable to load template: " .. name)
        else
-               t:render(...)
+               t:render(scope, ...)
        end
 end
 
@@ -208,6 +209,7 @@ function Template.render(self, scope)
        local oldfenv = getfenv(self.template)
        
        -- Put our predefined objects in the scope of the template
+       ffluci.util.resfenv(self.template)
        ffluci.util.updfenv(self.template, scope)
        ffluci.util.updfenv(self.template, self.viewns)
        
index 12031ff7d8e0c3b0a179201abe8f361cd1d1ac68..b219be130e890af1c521fcce30e32cbe7ad73bb9 100644 (file)
@@ -114,7 +114,6 @@ end
 function extfenv(f, key, obj)
        local scope = getfenv(f)
        scope[key] = obj
-       setfenv(f, scope)
 end
 
 
@@ -131,13 +130,20 @@ function instanceof(object, class)
 end
 
 
+-- Resets the scope of f doing a shallow copy of its scope into a new table
+function resfenv(f)
+       local scope = getfenv(f)
+       setfenv(f, {})
+       updfenv(f, scope)
+end 
+
+
 -- Updates the scope of f with "extscope"
 function updfenv(f, extscope)
        local scope = getfenv(f)
        for k, v in pairs(extscope) do
                scope[k] = v
        end
-       setfenv(f, scope)
 end
 
 
index eb2eac2fd969baffe1490c372d5e7f5ee91b4a71..6a994195991121b83f9b78d38e01aa0786a78446 100644 (file)
@@ -1,11 +1,11 @@
-<div class="cbi-lvalue">
-<div class="cbi-lvalue-title"><%=self.title%></div>
-<div class="cbi-lvalue-field">
-<select name="<%=self.config.."."..self.section.."."..self.option%>">
-<%for k, v in self.list do%>
-<option value="<%=k%>"><%=v%></option>
+                                               <div class="cbi-lvalue">
+                                                       <div class="cbi-lvalue-title"><%=self.title%></div>
+                                                       <div class="cbi-lvalue-field">
+                                                               <select name="cbid.<%=self.config.."."..self.section.."."..self.option%>">
+<%for k, v in pairs(self.list) do%>
+                                                                       <option value="<%=k%>"><%=v%></option>
 <% end %>
-</select>
-</div>
-<div class="cbi-value-description"><%=self.description%></div>
-</div>
\ No newline at end of file
+                                                               </select>
+                                                       </div>
+                                                       <div class="cbi-value-description"><%=self.description%></div>
+                                               </div>
\ No newline at end of file
index e4f493bd09a3af4b85c1060e8810ee1e5b4ccf30..b724ffccbb4a8ba22271eda65798ddd839806e98 100644 (file)
@@ -1,7 +1,10 @@
-<div class="cbi-map" id="cbi-<%=self.config%>">
-<form method="post" action="<%=os.getenv("REQUEST_URI")%>">
-<h1><%=self.title%></h1>
-<div class="cbi-map-descr"><%=self.description%></div>
+               <div class="cbi-map" id="cbi-<%=self.config%>">
+                       <form method="post" action="<%=os.getenv("REQUEST_URI")%>">
+                               <h1><%=self.title%></h1>
+                               <div class="cbi-map-descr"><%=self.description%></div>
+                               <br />
 <% for k, node in ipairs(self.children) do node:render() end %>
-</form>
-</div>
+                               <br />
+                               <input type="submit" /> <input type="reset" />
+                       </form>
+               </div>
index 5badeca562c1e55c76e2bf95855d5175ef04db30..e002c68b09af8110cfcf0a546ffc74a732533646 100644 (file)
@@ -1,5 +1,7 @@
-<div class="cbi-nsection" id="cbi-<%=self.config%>-<%=self.sectiontype%>-<%=self.section%>">
-<h2><%=self.title%></h2>
-<div class="cbi-nsection-descr"><%=self.description%></div>
+                               <div class="cbi-nsection" id="cbi-<%=self.config%>-<%=self.section%>">
+                                       <h2><%=self.title%></h2>
+                                       <div class="cbi-nsection-descr"><%=self.description%></div>
+                                       <div class="cbi-nsection-options">
 <% for k, node in ipairs(self.children) do node:render() end %>
-</div>
+                                       </div>
+                               </div>
index 8c7f0c1151853f86113b537aeb0d322206ed5b58..b613f6271f069b588a831a2d306acac05460e1e8 100644 (file)
@@ -2,20 +2,20 @@
 local allsections = self.map:read()
 local sections = {}
 for k, v in pairs(allsections) do
-       if v[".type"] == sectiontype then
+       if v[".type"] == self.sectiontype then
                sections[k] = v
        end
 end 
 %>
-<div class="cbi-tsection" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
-<h2><%=self.title%></h2>
-<div class="cbi-tsection-descr"><%=self.description%></div>
+                               <div class="cbi-tsection" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
+                                       <h2><%=self.title%></h2>
+                                       <div class="cbi-tsection-descr"><%=self.description%></div>
 <% for k, v in pairs(sections) do %>
-<div class="cbi-tsection-node" id="cbi-<%=self.config%>-<%=k%>">
-<% for k, node in ipairs(self.children) do
+                                       <div class="cbi-tsection-node" id="cbi-<%=self.config%>-<%=k%>">
+<% for i, node in ipairs(self.children) do
        node.section = k
-       node:render(k)
+       node:render()
 end %>
-</div>
+                                       </div>
 <% end %>
-</div>
+                               </div>
index cc22c4e56414fac7610972199eaf5972d1e35c7c..a898d08c1d626debfa7114e94643c89ceb7740e2 100644 (file)
@@ -1,7 +1,7 @@
-<div class="cbi-value">
-<div class="cbi-value-title"><%=self.title%></div>
-<div class="cbi-value-field">
-<input type="text" name="<%=self.config.."."..self.section.."."..self.option%>" value="<%=self:ucivalue()%>" />
-</div>
-<div class="cbi-value-description"><%=self.description%></div>
-</div>
\ No newline at end of file
+                                               <div class="cbi-value">
+                                                       <div class="cbi-value-title"><%=self.title%></div>
+                                                       <div class="cbi-value-field">
+                                                               <input type="text" name="cbid.<%=self.config.."."..self.section.."."..self.option%>" value="<%=(self:ucivalue() or "")%>" />
+                                                       </div>
+                                                       <div class="cbi-value-description"><%=self.description%></div>
+                                               </div>
\ No newline at end of file