* Added ffluci.util.instanceof function
authorSteven Barth <steven@midlink.org>
Mon, 17 Mar 2008 21:38:03 +0000 (21:38 +0000)
committerSteven Barth <steven@midlink.org>
Mon, 17 Mar 2008 21:38:03 +0000 (21:38 +0000)
* Minor beautifying in dispatcher
* Added field for additional Tags under <head> in main style
* Added structure for CBI
* Added CBI to Makefile

Makefile
src/ffluci/cbi.lua
src/ffluci/dispatcher.lua
src/ffluci/util.lua
src/ffluci/view/header.htm

index a2d4dd1..317f3a6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -5,8 +5,8 @@ FILES = ffluci/config.lua
 
 CFILES = ffluci/util.lua ffluci/http.lua \
 ffluci/fs.lua ffluci/i18n.lua ffluci/model/uci.lua \
-ffluci/template.lua ffluci/dispatcher.lua ffluci/menu.lua \
-ffluci/init.lua ffluci/sys.lua 
+ffluci/template.lua ffluci/cbi.lua ffluci/dispatcher.lua \
+ffluci/menu.lua ffluci/init.lua ffluci/sys.lua 
 
 DIRECTORIES = dist/ffluci/model dist/ffluci/controller/public dist/ffluci/controller/admin dist/ffluci/i18n dist/ffluci/view
 
index de02699..fc8b1ae 100644 (file)
@@ -25,8 +25,10 @@ limitations under the License.
 
 ]]--
 module("ffluci.cbi", package.seeall)
+require("ffluci.template")
 require("ffluci.util")
 local class = ffluci.util.class
+local instanceof = ffluci.util.instanceof
 
 
 -- Node pseudo abstract class
@@ -36,6 +38,7 @@ function Node.__init__(self, title, description)
        self.children = {}
        self.title = title
        self.description = description
+       self.template = "cbi/node"
 end
 
 function Node.append(self, obj)
@@ -43,13 +46,129 @@ function Node.append(self, obj)
 end
 
 
--- CBI Map
+--[[
+Map - A map describing a configuration file 
+]]--
 Map = class(Node)
 
-function Map.__init__(self, ...)
+function Map.__init__(self, config, ...)
+       Node.__init__(self, ...)
+       self.config = config
+       self.template = "cbi/map"
+end
+
+function Map.render(self)
+       ffluci.template.render(self.template)
+end
+
+function Map.section(self, class, ...)
+       if instanceof(class, AbstractClass) then
+               local obj = class(...)
+               obj.map = self
+               table.insert(self.children, obj)
+               return obj
+       else
+               error("class must be a descendent of AbstractSection")
+       end
+end
+
+
+--[[
+AbstractSection
+]]--
+AbstractSection = class(Node)
+
+function AbstractSection.__init__(self, ...)
+       Node.__init__(self, ...)
+end
+
+function AbstractSection.option(self, class, ...)
+       if instanceof(class, AbstractValue) then
+               local obj = class(...)
+               obj.section = self
+               obj.map     = self.map
+               table.insert(self.children, obj)
+               return obj
+       else
+               error("class must be a descendent of AbstractValue")
+       end     
+end
+       
+
+
+--[[
+NamedSection - A fixed configuration section defined by its name
+]]--
+NamedSection = class(AbstractSection)
+
+function NamedSection.__init__(self, section, ...)
+       AbstractSection.__init__(self, ...)
+       self.section = section
+       self.template = "cbi/nsection"
+end
+
+
+--[[
+TypedSection - A (set of) configuration section(s) defined by the type
+       addremove:      Defines whether the user can add/remove sections of this type
+       anonymous:  Allow creating anonymous sections
+       valid:          a table with valid names or a function returning nil if invalid
+]]--
+TypedSection = class(AbstractSection)
+
+function TypedSection.__init__(self, sectiontype, ...)
+       AbstractSection.__init__(self, ...)
+       self.sectiontype = sectiontype
+       self.template  = "cbi/tsection"
+       
+       self.addremove = true
+       self.anonymous = false
+       self.valid     = nil
+end
+
+
+--[[
+AbstractValue - An abstract Value Type
+       null:           Value can be empty
+       valid:          A table with valid names or a function returning nil if invalid
+       depends:        A table of option => value pairs of which one must be true
+]]--
+AbstractValue = class(Node)
+
+function AbstractValue.__init__(self, option, ...)
        Node.__init__(self, ...)
+       self.option  = option
+       
+       self.null    = true
+       self.valid   = nil
+       self.depends = nil
 end
+       
+
+--[[
+Value - A one-line value 
+       maxlength:      The maximum length
+       isnumber:       The value must be a valid (floating point) number
+       isinteger:  The value must be a valid integer
+]]--
+Value = class(AbstractValue)
 
-function Map.render(self, template)
-       -- ToDo
+function Value.__init__(self, ...)
+       AbstractValue.__init__(self, ...)
+       self.template  = "cbi/value"
+       
+       self.maxlength = nil
+       self.isnumber  = false
+       self.isinteger = false
 end
+
+
+--[[
+Boolean - A simple boolean value       
+]]--
+Boolean = class(AbstractValue)
+
+function Boolean.__init__(self, ...)
+       AbstractValue.__init__(self, ...)
+       self.template = "cbi/boolean"
+end
\ No newline at end of file
index bf2ac51..d2998aa 100644 (file)
@@ -104,13 +104,9 @@ end
 function error404(message)
        message = message or "Not Found"
        
-       local s, t = pcall(ffluci.template.Template, "error404")
-       
-       if not s then
+       if not pcall(ffluci.template.render, "error404") then
                ffluci.http.textheader()
                print(message)
-       else
-               t:render()
        end
        return false    
 end
@@ -119,13 +115,9 @@ end
 function error500(message)
        ffluci.http.status(500, "Internal Server Error")
        
-       local s, t = pcall(ffluci.template.Template, "error500")
-       
-       if not s then
+       if not pcall(ffluci.template.render, "error500") then
                ffluci.http.textheader()
                print(message)
-       else
-               t:render()
        end
        return false    
 end
@@ -155,12 +147,8 @@ function simpleview(request)
        local disp = require("ffluci.dispatcher")
        
        i18n.loadc(request.module)
-       local s, t = pcall(tmpl.Template, request.module .. "/" .. request.action)
-       
-       if not s then
+       if not pcall(tmpl.render, request.module .. "/" .. request.action) then
                disp.error404()
-       else
-               t:render()
        end
 end
 
index 6e0d867..4f0551e 100644 (file)
@@ -92,6 +92,7 @@ function exec(command)
        return data
 end
 
+
 -- Runs "command" and returns its output as a array of lines
 function execl(command)
        local pp   = io.popen(command)  
@@ -108,6 +109,7 @@ function execl(command)
        return data
 end
 
+
 -- Populate obj in the scope of f as key 
 function extfenv(f, key, obj)
        local scope = getfenv(f)
@@ -116,6 +118,19 @@ function extfenv(f, key, obj)
 end
 
 
+-- Checks whether an object is an instanceof class
+function instanceof(object, class)
+       local meta = getmetatable(object)
+    while meta and meta.__index do 
+       if meta.__index == class then
+               return true
+       end
+        meta = getmetatable(meta.__index)
+    end
+    return false       
+end
+
+
 -- Updates the scope of f with "extscope"
 function updfenv(f, extscope)
        local scope = getfenv(f)
@@ -125,6 +140,7 @@ function updfenv(f, extscope)
        setfenv(f, scope)
 end
 
+
 -- Returns the filename of the calling script
 function __file__()
        return debug.getinfo(2, 'S').source:sub(2)
index 44826f0..cef95b3 100644 (file)
@@ -11,6 +11,7 @@ require("ffluci.http").htmlheader()
 <head>
 <link rel="stylesheet" type="text/css" href="<%=media%>/cascade.css" />
 <title>FFLuCI</title>
+<% if addheaders then write(addheaders) end %>
 </head>
 <body>
 <div id="header">