--[[
- @author Bruno Massa
- @file common.lua
- This file group togheter many function that dont have
- a clear category. These functions deals with many different
- tasks.
]]
do
C.SCHEMA_UNINSTALLED = -1
C.SCHEMA_INSTALLED = 0
C.REQUIREMENT_INFO = -1
C.REQUIREMENT_OK = 0
C.REQUIREMENT_WARNING = 1
C.REQUIREMENT_ERROR = 2
C.FILE_EXIST = 1
C.FILE_READABLE = 2
C.FILE_WRITABLE = 4
C.FILE_EXECUTABLE = 8
C.FILE_NOT_EXIST = 16
C.FILE_NOT_READABLE = 32
C.FILE_NOT_WRITABLE = 64
C.FILE_NOT_EXECUTABLE = 128
end
--[[
- Show the value of a variable, to rapidly see the content
- of a variable. This variable can be a number, string ou table
-
- If no err variable is given, the default output is a standard
- Ajato message. If err is true, it stops the Ajato and print
- it as a Lua error.
-
- @param variable
- Any type, a variable that we need to see the value
- @param err
- Boolean, true to stop Lua execution and print it as an error
]]
function ad(variable, err)
-- Closes the program and show traceback
if err then
error(variable)
end
-- Display the debug info using debug messages
ajato_add_message(variable, 'debug')
end
--[[
- This dispatch function hands off structured Ajato tables to
- type-specific-_alter implementations. It ensures a consistent
- interface for all altering operations.
-
- @param type
- String, The data type of the structured table. 'form', 'links',
- 'node_content', and so on are several examples.
- @param data
- Table, The data to be altered.
- @param ...
- Any type, Any additional params will be passed on to the called
- hook_[type]_alter functions.
]]
function ajato_alter(alter_type, data, ...)
-- Hang onto a reference to the data table so that it isn't blown away later.
args = {...}
for module in pairs(ajato_module_implements(alter_type ..'_alter')) do
data = ajato_tables_merge(data, _G[module ..'_'..
alter_type ..'_alter'](data, unpack(args)))
end
return data
end
--[[
- Simulate parcially the "test ? yes : no" operator
- on PHP and C/C++. The fisrt argument should be
- a variable only. It doesnt evaluate statements like
- these languages.
-
- @param test
- Any type, the function will check if the variable
- is nil or blank. In case it is, return the third
- argument
- @param yes
- Any type, return it in case the test if successful
- @param no
- Any type, return it in case the test failed
- @return
- Any type, yes in case the test is valid.
]]
function ajato_choose(test, yes, no)
if test then
return yes
else
return no
end
end
--[[
- Simulate the explode() function from PHP. It split a given
- string into table values. But this function only split
- with one character
-
- @param original_string
- String, the original string
- @param match
- String, the character that mark transition between pieces
- in a string
- @param max
- Number, the maximun number of children
- @return
- Table, all pieces from the string
]]
function ajato_explode(original_string, match, max)
local result = {}
for word in string.gmatch(original_string, '([^'.. match ..']*)') do
if hv(word) then
result[#result + 1] = word
end
if max then
max = max - 1
if max == 0 then
break
end
end
end
return result
end
--[[
- Send the user to a different Ajato page.
-
- This issues an on-site HTTP redirect. The function makes sure the redirected
- URL is formatted correctly.
-
- Usually the redirected URL is constructed from this function's input
- parameters. However you may override that behavior by setting a
- destination in either the $_REQUEST-array (i.e. by using
- the query string of an URI) or the $_REQUEST['edit']-array (i.e. by
- using a hidden form field). This is used to direct the user back to
- the proper page after completing a form. For example, after editing
- a post on the 'admin/content/node'-page or after having logged on using the
- 'user login'-block in a sidebar. The function ajato_get_destination()
- can be used to help set the destination URL.
-
-
- This function ends the request; use it rather than a print theme('page')
- statement in your menu callback.
-
- @param path
- String, A internal path or a full URL.
- @param query
- Table, The query string component, if any.
- @param fragment
- String, The destination fragment identifier (named anchor).
- @param http_response_code
- Number, Valid values for an actual "goto" as per RFC 2616 section 10.3 are:
- - 301 Moved Permanently (the recommended value for most redirects)
- - 302 Found (default in Ajato, sometimes used for spamming search engines)
- - 303 See Other
- - 304 Not Modified
- - 305 Use Proxy
- - 307 Temporary Redirect (an alternative to "503 Site Down for Maintenance")
- Note: Other values are defined by RFC 2616, but are rarely used and poorly
- supported.
- @see ajato_get_destination()
]]
function ajato_goto(path, query, fragment, http_response_code)
path = path or ''
http_response_code = http_response_code or 302
local url = ajato_path_format(path, query, fragment)
-- Before the redirect, allow modules to react to the end of the page request.
ajato_module_hook('exit', url)
cgilua.redirect (url)
end
--[[
- Form an associative table from a linear table (enter a just numeric table
- and convert it to )
-
- This function walks through the provided table and constructs an associative
- table out of it. The keys of the resulting table will be the values of the
- input table. The values will be the same as the keys unless a function is
- specified, in which case the output of the function is used for the values
- instead.
-
- @param original_table
- Table, A numeric index table.
- @param func
- String, The function to apply to all values before output.
- @return
- Table, An associative table
]]
function ajato_map_assoc(original_table, func)
if not func then
local result = {}
for _, value in pairs(original_table) do
result[value] = value
end
return result
elseif _G[func] then
local result = {}
for _, value in pairs(original_table) do
result[value] = _G[func](value)
end
return result
end
end
--[[
- Generates a site off-line message
]]
function ajato_page_site_offline()
-- Set the maintenance theme
ajato_maintenance_theme()
-- Send the HTTP error
cgilua.htmlheader('HTTP/1.1 503 Service unavailable')
ajato_set_title(t('Site off-line'))
local result = ajato_variable_get('site_offline_message' ,
t('@site is currently under maintenance. We should be back shortly. Thank you for your patience.',
{['@site'] = ajato_variable_get('site_name', 'Ajato')}))
return result
end
--[[
- Generates a 404 error if the request can not be handled.
]]
function ajato_page_not_found()
-- Send the HTTP error
cgilua.htmlheader('HTTP/1.1 404 Not Found')
-- watchdog('page not found', check_plain(sys['get']['q']), nil, C.WATCHDOG_WARNING)
local result
local path = ajato_path_get_normal(ajato_variable_get('site_404', ''))
if hv(path) and path ~= sys['get']['q'] then
result = ajato_menu_execute(path)
end
if not hv(result) then
ajato_set_title(t('Page not found'))
result = t('Page not found')
end
return result
end
--[[
- Generates a 403 error if the request is not allowed.
]]
function ajato_page_access_denied()
-- Send the HTTP error
cgilua.htmlheader('HTTP/1.1 403 Forbidden')
-- watchdog('access denied', check_plain(sys['get']['q']), nil, C.WATCHDOG_WARNING)
local result
local path = ajato_path_normal_get(ajato_variable_get('site_403', ''))
if hv(path) and path ~= sys['get']['q'] then
result = ajato_menu_execute(path)
end
if not hv(result) then
ajato_set_title(t('Access denied'))
result = t('You are not authorized to access this page.')
end
return result
end
--[[
- Serialize a table using the small presentation.
-
- Example result:
- table1={['field1']="string",['field2']=123,['field3']={['field3a']="string"}}
-
- @param object
- Any type, the object to be serialized
- @param mode
- String, it can be:
- - '' or nil for the compact mode
- - 'clear' to indent and make new lines for plain text
- - 'html' to indent and make new lines fot HTML
- @param count
- Number (internal), the current indent level
- @param tables
- Tables (internal), internal table that control which tables have
- been already scanned. It avoids self referencing and
- infinit loop
- @return
- String, the serialized object
]]
function ajato_serialize(object, mode, count, tables)
-- Initializing variables
tables = tables or {}
count = count or 0
if type(object) == 'table' and (#object == 0 or not tables[object]) then
-- serial representation to build
local serial = {}
-- Remembering which functions have been scanned
tables[object] = true
local indent = ''
local new_line = ''
if mode then
if mode == 'html' then
indent = ' '
new_line = '
\n'
elseif mode == 'clear' then
indent = ' '
new_line = '\n'
end
end
-- Scan every single value on this table
for index, value in pairs(object) do
-- Insert quotes for strings
if type(i) == 'string' then
index = string.format('%q', index)
end
serial[#serial + 1] = string.rep(indent, count + 1) ..'['.. index ..']='..
ajato_serialize(value, mode, count + 1, tables)
end
-- Return the table creation pattern {}
return '{'.. (((#serial >= 1) and new_line .. table.concat(serial, ','.. new_line) ..
new_line .. string.rep(indent, count)) or '') .. '}'
end
return ajato_serialize_basic(object)
end
--[[
- Serialize a table using the big and redundant presentation
-
- @param variable
- String or Number, the variable name
- @param object
- String or Number, the variable value
- @param args
- table, some features
- @param saved
- String or Number, the variable value
- @return
- String, the serialized object
]]
function ajato_serialize_big(name, object, args, saved)
-- Initial value
saved = saved or {}
args = args or {}
args['newline'] = args['newline'] or '\n'
local output = {}
if not args['no_blank_table'] then
output = {name ..' = '}
end
if type(object) == 'number' or type(object) == 'string' or type(object) == 'boolean' then
output[#output + 1] = ajato_serialize_basic(object) .. args['newline']
elseif type(object) == 'table' then
-- Check if the object is already saved
if saved[object] then
-- Use its previous name
output[#output + 1] = saved[object] .. args['newline']
else
-- Save name for next time
saved[object] = name
if not args['no_blank_table'] then
-- Create a new table
output[#output + 1] = '{}'.. args['newline']
else
args['no_blank_table'] = nil
end
-- Save its fields
for k,v in pairs(object) do
local fieldname = string.format('%s[%s]', name, ajato_serialize_basic(k))
output[#output + 1] = ajato_serialize_big(fieldname, v, args, saved)
end
end
end
return table.concat(output, '')
end
--[[
- Serialize all types of value. Functions and userdata
- are considered nil
-
- @param variable
- Any type, the original variable value
- @return
- String, the variable value
]]
function ajato_serialize_basic(object)
if not object or type(object) == 'number' or type(object) == 'boolean' then
return tostring(object)
elseif type(object) == 'string' then
return string.format('%q', object)
end
-- Everything else is considered nil
return 'nil --[['.. type(object) ..']]'
end
--[[
- Retrieves the current status of a series of files in the system table.
-
- @param files
- Table, list of files
- @param type
- String, the plugin type (module, template, etc)
- @return
- Table,
]]
function ajato_system_get_files_database(files, type)
-- Extract current files from database.
local result = db_query([[SELECT filename, name, type, status, throttle,
schema_version FROM {system} WHERE type = %q]], type)
if hv(result) then
for file in pairs(db_rows(result)) do
if files[file['name']] and type(files[file['name']]) == 'table' then
file['old_filename'] = file['filename']
for key, value in pairs(file) do
if not files[file['name']] or not files[file['name']]['key'] then
files[file['name']]['key'] = value
end
end
end
end
end
return files
end
--[[
- Merge two tables. It maintain the table1 index and add
- table 2 values.
-
- @param table1
- Table, the primary table
- @param table2
- Table, the secondary table
- @param not_overwrite
- Boolean, true to not overwrite values when found same index,
- creating a numeric and sequencial index
- @param not_recursive
- Boolean, true to not go to next table levels
- @return
- Table, the merged table
]]
function ajato_tables_merge(table1, table2, not_overwrite, not_recursive)
-- First, fill the result table with the data from the
-- first table
local result = {}
if type(table1) == 'table' then
for index, value in pairs(table1) do
if not_overwrite then
result[#result + 1] = value
else
result[index] = value
end
end
end
-- Now add the data from the second table
if type(table2) == 'table' then
for index, value in pairs(table2) do
if not_overwrite then
result[#result + 1] = value
else
if not not_recursive and type(result[index]) == 'table' and type(value) == 'table' then
result[index] = ajato_tables_merge(result[index], value, true)
else
result[index] = value
end
end
end
end
return result
end
--[[
- Unserialize a string. In case of being table, it
- will only work in case the table is serialized using
- small method
-
- @param object
- String, the object to be unserialized
- @return
- Any type, the unserialized object
]]
function ajato_unserialize(object)
if type(object) ~= 'string' then
return object
elseif tonumber(object) then -- Seems to be a simple number
return tonumber(object)
elseif object == tostring(nil) then -- Nil
return nil
elseif string.sub(object, 0, 1) == '{' then -- Table
return loadstring('return '.. object)()
else -- Consider it a string
return string.format('%q', object)
end
end