* Added class support to template engine
* Cleaned up dispatcher * Added 404 error page * Cleaned up properties
This commit is contained in:
parent
38d279e4ea
commit
cfe8fc894f
3 changed files with 92 additions and 52 deletions
|
@ -100,16 +100,17 @@ function dispatch(req)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Sends a 404 error code and renders the "error404" template if available
|
-- Sends a 404 error code and renders the "error404" template if available
|
||||||
function error404(message)
|
function error404(message)
|
||||||
message = message or "Not Found"
|
message = message or "Not Found"
|
||||||
|
|
||||||
ffluci.http.status(404, "Not Found")
|
local s, t = pcall(ffluci.template.Template, "error404")
|
||||||
|
|
||||||
if not pcall(ffluci.template.render, "error404") then
|
if not s then
|
||||||
ffluci.http.textheader()
|
ffluci.http.textheader()
|
||||||
print(message)
|
print(message)
|
||||||
|
else
|
||||||
|
t:render()
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
@ -118,9 +119,13 @@ end
|
||||||
function error500(message)
|
function error500(message)
|
||||||
ffluci.http.status(500, "Internal Server Error")
|
ffluci.http.status(500, "Internal Server Error")
|
||||||
|
|
||||||
if not pcall(ffluci.template.render, "error500") then
|
local s, t = pcall(ffluci.template.Template, "error500")
|
||||||
|
|
||||||
|
if not s then
|
||||||
ffluci.http.textheader()
|
ffluci.http.textheader()
|
||||||
print(message)
|
print(message)
|
||||||
|
else
|
||||||
|
t:render()
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
@ -147,14 +152,15 @@ end
|
||||||
function simpleview(request)
|
function simpleview(request)
|
||||||
local i18n = require("ffluci.i18n")
|
local i18n = require("ffluci.i18n")
|
||||||
local tmpl = require("ffluci.template")
|
local tmpl = require("ffluci.template")
|
||||||
local conf = require("ffluci.config")
|
|
||||||
local disp = require("ffluci.dispatcher")
|
local disp = require("ffluci.dispatcher")
|
||||||
|
|
||||||
pcall(i18n.load, request.module .. "." .. conf.lang)
|
i18n.loadc(request.module)
|
||||||
if not pcall(tmpl.get, request.module .. "/" .. request.action) then
|
local s, t = pcall(tmpl.Template, request.module .. "/" .. request.action)
|
||||||
|
|
||||||
|
if not s then
|
||||||
disp.error404()
|
disp.error404()
|
||||||
else
|
else
|
||||||
tmpl.render(request.module .. "/" .. request.action)
|
t:render()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -162,10 +168,9 @@ end
|
||||||
-- action_"request.action" and calls it
|
-- action_"request.action" and calls it
|
||||||
function action(request)
|
function action(request)
|
||||||
local i18n = require("ffluci.i18n")
|
local i18n = require("ffluci.i18n")
|
||||||
local conf = require("ffluci.config")
|
|
||||||
local disp = require("ffluci.dispatcher")
|
local disp = require("ffluci.dispatcher")
|
||||||
|
|
||||||
pcall(i18n.load, request.module .. "." .. conf.lang)
|
i18n.loadc(request.module)
|
||||||
local action = getfenv()["action_" .. request.action:gsub("-", "_")]
|
local action = getfenv()["action_" .. request.action:gsub("-", "_")]
|
||||||
if action then
|
if action then
|
||||||
action()
|
action()
|
||||||
|
|
|
@ -35,10 +35,9 @@ viewdir = ffluci.fs.dirname(ffluci.util.__file__()) .. "view/"
|
||||||
|
|
||||||
|
|
||||||
-- Compile modes:
|
-- Compile modes:
|
||||||
-- none: Never compile, only render precompiled
|
-- none: Never compile, only use precompiled data from files
|
||||||
-- memory: Always compile, do not save compiled files, ignore precompiled
|
-- memory: Always compile, do not save compiled files, ignore precompiled
|
||||||
-- always: Same as "memory" but also saves compiled files
|
-- file: Compile on demand, save compiled files, update precompiled
|
||||||
-- smart: Compile on demand, save compiled files, update precompiled
|
|
||||||
compiler_mode = "memory"
|
compiler_mode = "memory"
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,25 +55,12 @@ viewns = {
|
||||||
config = ffluci.model.uci.get,
|
config = ffluci.model.uci.get,
|
||||||
controller = os.getenv("SCRIPT_NAME"),
|
controller = os.getenv("SCRIPT_NAME"),
|
||||||
media = ffluci.config.mediaurlbase,
|
media = ffluci.config.mediaurlbase,
|
||||||
include = function(name) return render(name, getfenv(2)) end,
|
write = io.write,
|
||||||
write = io.write
|
include = function(name) Template(name):render(getfenv(2)) end,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
-- Compiles and builds a given template
|
|
||||||
function build(template, compiled)
|
|
||||||
local template = compile(ffluci.fs.readfile(template))
|
|
||||||
|
|
||||||
if compiled then
|
|
||||||
ffluci.fs.writefile(compiled, template)
|
|
||||||
end
|
|
||||||
|
|
||||||
return template
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- Compiles a given template into an executable Lua module
|
-- Compiles a given template into an executable Lua module
|
||||||
function compile(template)
|
function compile(template)
|
||||||
-- Search all <% %> expressions (remember: Lua table indexes begin with #1)
|
-- Search all <% %> expressions (remember: Lua table indexes begin with #1)
|
||||||
local function expr_add(command)
|
local function expr_add(command)
|
||||||
table.insert(expr, command)
|
table.insert(expr, command)
|
||||||
|
@ -137,53 +123,97 @@ function compile(template)
|
||||||
return template
|
return template
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Oldstyle render shortcut
|
||||||
|
function render(name, ...)
|
||||||
|
local s, t = pcall(Template, name)
|
||||||
|
if not s then
|
||||||
|
error("Unable to load template: " .. name)
|
||||||
|
else
|
||||||
|
t:render(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Returns and builds the template for "name" depending on the compiler mode
|
|
||||||
function get(name)
|
-- Template class
|
||||||
local templatefile = viewdir .. name .. ".htm"
|
Template = ffluci.util.class()
|
||||||
local compiledfile = viewdir .. name .. ".lua"
|
|
||||||
local template = nil
|
-- Shared template cache to store templates in to avoid unnecessary reloading
|
||||||
|
Template.cache = {}
|
||||||
|
|
||||||
|
|
||||||
|
-- Constructor - Reads and compiles the template on-demand
|
||||||
|
function Template.__init__(self, name)
|
||||||
|
if self.cache[name] then
|
||||||
|
self.template = self.cache[name]
|
||||||
|
else
|
||||||
|
self.template = nil
|
||||||
|
end
|
||||||
|
|
||||||
if compiler_mode == "smart" then
|
-- Create a new namespace for this template
|
||||||
local tplmt = ffluci.fs.mtime(templatefile)
|
self.viewns = {}
|
||||||
|
|
||||||
|
-- Copy over from general namespace
|
||||||
|
for k, v in pairs(viewns) do
|
||||||
|
self.viewns[k] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If we have a cached template, skip compiling and loading
|
||||||
|
if self.template then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Compile and build
|
||||||
|
local sourcefile = viewdir .. name .. ".htm"
|
||||||
|
local compiledfile = viewdir .. name .. ".lua"
|
||||||
|
|
||||||
|
if compiler_mode == "file" then
|
||||||
|
local tplmt = ffluci.fs.mtime(sourcefile)
|
||||||
local commt = ffluci.fs.mtime(compiledfile)
|
local commt = ffluci.fs.mtime(compiledfile)
|
||||||
|
|
||||||
-- Build if there is no compiled file or if compiled file is outdated
|
-- Build if there is no compiled file or if compiled file is outdated
|
||||||
if ((commt == nil) and not (tplmt == nil))
|
if ((commt == nil) and not (tplmt == nil))
|
||||||
or (not (commt == nil) and not (tplmt == nil) and commt < tplmt) then
|
or (not (commt == nil) and not (tplmt == nil) and commt < tplmt) then
|
||||||
template = loadstring(build(templatefile, compiledfile))
|
local compiled = compile(ffluci.fs.readfile(sourcefile))
|
||||||
|
ffluci.fs.writefile(compiledfile, compiled)
|
||||||
|
self.template = loadstring(compiled)
|
||||||
else
|
else
|
||||||
template = loadfile(compiledfile)
|
self.template = loadfile(compiledfile)
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif compiler_mode == "none" then
|
elseif compiler_mode == "none" then
|
||||||
template = loadfile(compiledfile)
|
self.template = loadfile(self.compiledfile)
|
||||||
|
|
||||||
elseif compiler_mode == "memory" then
|
elseif compiler_mode == "memory" then
|
||||||
template = loadstring(build(templatefile))
|
self.template = loadstring(compile(ffluci.fs.readfile(sourcefile)))
|
||||||
|
|
||||||
elseif compiler_mode == "always" then
|
|
||||||
template = loadstring(build(templatefile, compiledfile))
|
|
||||||
|
|
||||||
else
|
else
|
||||||
error("Invalid compiler mode: " .. compiler_mode)
|
error("Invalid compiler mode: " .. compiler_mode)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return template or error("Unable to load template: " .. name)
|
-- If we have no valid template throw error, otherwise cache the template
|
||||||
|
if not self.template then
|
||||||
|
error("Unable to load template: " .. name)
|
||||||
|
else
|
||||||
|
self.cache[name] = self.template
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Renders a template
|
-- Renders a template
|
||||||
function render(name, scope)
|
function Template.render(self, scope)
|
||||||
scope = scope or getfenv(2)
|
scope = scope or getfenv(2)
|
||||||
|
|
||||||
-- Our template module
|
-- Save old environment
|
||||||
local view = get(name)
|
local oldfenv = getfenv(self.template)
|
||||||
|
|
||||||
-- Put our predefined objects in the scope of the template
|
-- Put our predefined objects in the scope of the template
|
||||||
ffluci.util.updfenv(view, scope)
|
ffluci.util.updfenv(self.template, scope)
|
||||||
ffluci.util.updfenv(view, viewns)
|
ffluci.util.updfenv(self.template, self.viewns)
|
||||||
|
|
||||||
-- Now finally render the thing
|
-- Now finally render the thing
|
||||||
return view()
|
self.template()
|
||||||
|
|
||||||
|
-- Reset environment
|
||||||
|
setfenv(self.template, oldfenv)
|
||||||
end
|
end
|
||||||
|
|
5
src/ffluci/view/error404.htm
Normal file
5
src/ffluci/view/error404.htm
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<%+header%>
|
||||||
|
<h1>404 Not Found</h1>
|
||||||
|
<p>Sorry, the object you requested was not found.</p>
|
||||||
|
<tt>Unable to dispatch: <%=os.getenv("PATH_INFO")%></tt>
|
||||||
|
<%+footer%>
|
Loading…
Reference in a new issue