--[[
- @author Bruno Massa
- @file system.admin.lua
- All admin functions of system module. Its separated to avoid
- useless loading not used functions
]]
--[[
- Provide a single block on the administration overview page.
]]
function system_admin_menu_block(item)
local content = {}
if not item['mlid'] then
item['mlid'] = db_result(db_query([[SELECT mlid FROM {menu_links} ml
WHERE ml.router_path = %q AND menu_name = "navigation"]], item['path']))
end
local result = db_query([[
SELECT * FROM {menu_links} ml
INNER JOIN {menu_router} m ON ml.router_path = m.path
WHERE ml.plid = %d AND ml.menu_name = "navigation" AND hidden = 0
ORDER BY m.weight, m.title]], item['mlid'])
for item in db_rows(result) do
ajato_menu_link_translate(item)
if item['access'] then
content[#content + 1] = item
end
end
return content
end
--[[
- Provide the administration overview page.
]]
function system_admin_main_page()
-- Check for status report errors.
if system_status(true) then
ajato_add_message(t('One or more problems were detected with your Ajato installation. Check the @status for more information.',
{['@status'] = l(t('status report'), 'admin/logs/status')}), 'error')
end
local result = db_query([[SELECT * FROM {menu_links} ml
INNER JOIN {menu_router} m ON ml.router_path = m.path
WHERE ml.link_path LIKE "admin/%" AND ml.link_path != "admin/help" AND
ml.depth = 2 AND ml.menu_name = "navigation" AND hidden = 0
ORDER BY p1 ASC, p2 ASC, p3 ASC]])
local blocks = {}
if result then
for item in db_rows(result) do
_, item = ajato_menu_link_translate(item)
if hv(item['access']) then
block = item
block['content'] = ''
if item['block_callback'] and _G[item['block_callback']] then
func = item['block_callback']
block['content'] = block['content'] .. _G[func]()
end
block['content'] = block['content'] .. theme('admin_block_content', system_admin_menu_block(item))
blocks[#blocks + 1] = block
end
end
end
return theme('system_admin_main_page', blocks)
end
--[[
- Provide module enable/disable interface.
-
- Modules can be enabled or disabled and set for throttling if the throttle module is enabled.
- The list of modules gets populated by module.info files, which contain each module's name,
- description and dependencies.
- @see ajato_parse_info_file for information on module.info descriptors.
-
- Dependency checking is performed to ensure that a module cannot be enabled if the module has
- disabled dependencies and also to ensure that the module cannot be disabled if the module has
- enabled dependents.
-
- @return
- Table, the form structure
- @ingroup form
]]
function system_modules(form_state)
-- Get current list of modules.
local files = ajato_module_scan() or {}
if form_state and hv(form_state['storage']) then
return system_modules_confirm_form(files, form_state['storage'])
end
local dependencies = {}
local form = {}
-- Store module list for validation callback
form['validation_modules'] = {
['#type'] = 'value',
['#value'] = files
}
-- Create storage for disabled modules as browser will disable checkboxes.
form['disabled_modules'] = {
['#type'] = 'value',
['#value'] = {}
}
-- Table for disabling checkboxes in callback system_module_disable.
local disabled = {}
local throttle = {}
local incompatible_core = {}
local options = {}
local status = {}
form['name'] = {}
form['version'] = {}
form['description'] = {}
-- Traverse the files retrieved and build the form.
for filename, file in pairs(files) do
form['name'][filename] = {['#value'] = file['info']['name']}
form['version'][filename] = {['#value'] = file['info']['version']}
form['description'][filename] = {['#value'] = t(file['info']['description'])}
options[filename] = ''
if hv(file['status']) then
status[#status + 1] = file['name']
end
if hv(file['throttle']) then
throttle[#throttle + 1] = file['name']
end
local dependencies = {}
-- Check for missing dependencies.
if type(file['info']['dependencies']) == 'table' then
for dependency in pairs(file['info']['dependencies']) do
if not files[dependency] or not hv(files[dependency][status]) then
if files[dependency] then
dependencies[#dependencies + 1] = files[dependency][info['name']] ..
t(' (disabled)')
else
dependencies[#dependencies + 1] = dependency ..
t(' (missing)')
disabled[#disabled + 1] = filename
form['disabled_modules']['#value'][filename] = false
end
else
dependencies[#dependencies + 1] = files[dependency][info['name']] ..
t(' (enabled)')
end
end
-- Add text for dependencies.
if hv(dependencies) then
form['description'][filename]['dependencies'] = {
['#prefix'] = '
',
['#suffix'] = '
',
['#value'] = t('Depends on: !dependencies', {['!dependencies'] = table.concat(dependencies, ', ')}),
}
end
end
-- Mark dependents disabled so user can not remove modules being depended on.
local dependents = {}
for dependent in pairs(file['info']['dependents']) do
if files[dependent]['status'] == 1 then
dependents[#dependencies + 1] = files[dependent]['info']['name'] ..
t(' (enabled)')
disabled[#disabled + 1] = filename
form['disabled_modules']['#value'][filename] = true
else
dependents[#dependencies + 1] = files[dependent]['info']['name'] ..
t(' (disabled)')
end
end
-- Add text for enabled dependents.
if hv(dependents) then
form['description'][filename]['required'] = {
['#value'] = t('Required by: !required', {['!required'] = table.concat(dependents, ', ')}),
['#prefix'] = '',
['#suffix'] = '
',
}
end
end
local modules_required = {'block', 'filter', 'node', 'system', 'user'}
-- Merge in required modules.
for _, required in pairs(modules_required) do
disabled[#disabled + 1] = required
form['disabled_modules']['#value'][required] = true
end
-- Handle status checkboxes, including overriding
-- the generated checkboxes for required modules.
form['status'] = {
['#default_value'] = status,
['#disabled_modules'] = disabled,
['#incompatible_modules_core'] = ajato_map_assoc(incompatible_core),
['#options'] = options,
['#process'] = {
'expand_checkboxes',
'system_modules_disable',
},
['#type'] = 'checkboxes',
}
-- Handle throttle checkboxes, including overriding the
-- generated checkboxes for required modules.
if ajato_module_isenabled('throttle') then
form['throttle'] = {
['#type'] = 'checkboxes',
['#default_value'] = throttle,
['#options'] = options,
['#process'] = {
'expand_checkboxes',
'system_modules_disable',
},
['#disabled_modules'] = ajato_tables_merge(modules_required, {'throttle'}, true),
}
end
form['buttons'] = {}
form['buttons']['submit'] = {
['#type'] = 'submit',
['#value'] = t('Save configuration'),
}
form['#action'] = ajato_path_format('admin/build/modules/list/confirm')
return form
end
--[[
- Create a table of dependencies of each module
-
- @param modules
- Table, the modules list
- @param form_values
- Table, the form values of each field
- @return
- Table, the modules dependencies
]]
function system_modules_build_dependencies(modules, form_values)
-- Static Variables
local dependencies
return function(modules, form_values)
if not dependencies and form_values then
dependencies = {}
for name, module in pairs(modules) do
-- If the module is disabled, will be switched on and it has dependencies.
if not hv(module['status']) and hv(form_values['status'][name]) and
module['info']['dependencies'] then
for _, dependency in pairs(module['info']['dependencies']) do
if not hv(form_values['status'][dependency]) and modules[dependency] then
if not dependencies[name] then
dependencies[name] = {}
end
dependencies[name][#dependencies[name] + 1] = dependency
end
end
end
end
end
return dependencies
end
end; system_modules_build_dependencies = system_modules_build_dependencies()
--[[
- Implementation of hook_submit()
-
- Enable or disable modules
]]
function system_modules_submit(form, form_state)
ajato_include_once('./includes/install.lua')
local new_modules = {}
local dependencies
-- If we are coming from the confirm form...
if not hv(form_state['storage']) then
-- Merge in disabled active modules since they should be enabled.
-- They don't appear because disabled checkboxes are not submitted
-- by browsers.
form_state['values']['status'] = ajato_tables_merge(form_state['values']['status'],
form_state['values']['disabled_modules'])
-- Check values for dependency that we can't install.
dependencies = system_modules_build_dependencies(form_state['values']['validation_modules'],
form_state['values'])
if hv(dependencies) then
-- These are the modules that depend on existing modules.
for name in pairs(dependencies) do
form_state['values']['status'][name] = 0
end
end
end
-- Update throttle settings, if present
if form_state['values']['throttle'] then
for key, choice in pairs(form_state['values']['throttle']) do
db_query([[UPDATE {system} SET throttle = %d WHERE
type = "module" and name = %q]], (tonumber(hv(choice))), key)
end
end
-- If there where unmet dependencies and they haven't confirmed don't process
-- the submission yet. Store the form submission data needed later.
if hv(dependencies) then
if not form_state['values']['confirm'] then
form_state['storage'] = {dependencies, form_state['values']['status']}
return
else
form_state['values']['status'] = ajato_tables_merge(form_state['values']['status'],
form_storage[1])
end
end
-- If we have no dependencies, or the dependencies are confirmed
-- to be installed, we don't need the temporary storage anymore.
form_state['storage'] = nil
local enable_modules = {}
local disable_modules = {}
for key, choice in pairs(form_state['values']['status']) do
if hv(choice) then
if ajato_install_schema_version(key) == C.SCHEMA_UNINSTALLED then
new_modules[#new_modules + 1] = key
else
enable_modules[#enable_modules + 1] = key
end
else
disable_modules[#disable_modules + 1] = key
end
end
local changed
if hv(enable_modules) then
changed = ajato_module_enable(enable_modules)
end
if hv(disable_modules) then
changed = ajato_module_disable(disable_modules) or changed
end
-- Install new modules.
for key, module in pairs(new_modules) do
if not ajato_check_module(module) then
new_modules[key] = nil
end
end
if hv(new_modules) then
changed = ajato_install_module(new_modules) or changed
end
if changed then
-- ajato_rebuild_theme_registry()
-- ajato_node_types_rebuild()
ajato_menu_rebuild()
ajato_cache_clear_all('schema', 'cache')
ajato_add_message(t('The configuration options have been saved.'))
end
-- ajato_clear_css_cache()
-- ajato_clear_js_cache()
form_state['redirect'] = 'admin/build/modules'
-- Notify locale module about module changes, so translations can be
-- imported. This might start a batch, and only return to the redirect
-- path after that.
-- locale_system_update(new_modules)
return
end
--[[
- This function formats an administrative page for viewing.
-
- @param blocks
- Table, blocks to display. Each table should include a
- 'title', a 'description', a formatted 'content' and a
- 'position' which will control which container it will be
- in. This is usually 'left' or 'right'.
- @ingroup themeable
]]
function themes.system_admin_main_page(blocks)
local stripe = 0
local container = {}
local output = {}
for block in pairs(blocks) do
block_output = theme('admin_block', block)
if hv(block_output) then
if not hv(block['position']) then
-- Perform automatic striping.
stripe = stripe + 1
block['position'] = ajato_choose(stripe % 2, 'left', 'right')
end
if not container[block['position']] then
container[block['position']] = ''
end
container[block['position']] = container[block['position']] .. block_output
end
end
output[#output + 1] = ''
output[#output + 1] = '
'
if system_admin_compact_mode() then
output[#output + 1] = l(t('Show descriptions'), 'admin/compact/off',
{['title'] = t('Produce a less compact layout that includes descriptions.')})
else
output[#output + 1] = l(t('Hide descriptions'), 'admin/compact/on',
{['title'] = t("Produce a more compact layout that doesn't include descriptions.")})
end
output[#output + 1] = '
';
for id, data in pairs(container) do
output[#output + 1] = '
'
output[#output + 1] = data
output[#output + 1] = '
';
end
output[#output + 1] = '
'
return table.concat(output)
end
--[[
- This function formats the content of an administrative block.
-
- @param block
- Table, information about the block. It should
- include a 'title', a 'description' and a formatted 'content'.
- @ingroup themeable
]]
function themes.admin_block_content(content)
if not content then
return ''
end
if system_admin_compact_mode() then
output = {''
else
output = {''}
for item in pairs(content) do
output[#output + 1] = '- '.. l(item['title'], item['href'], item['options']) ..'
'
output[#output + 1] = '- '.. item['description'] ..'
'
end
output[#output + 1] = '
'
end
return table.concat(output)
end
--[[
- Theme call back for the modules form.
-
- @param form
- Table, the
]]
function themes.system_modules(form)
if form['confirm'] then
return ajato_element_render(form)
end
-- Individual table headers.
local header = {t('Enabled')}
if ajato_module_isenabled('throttle') then
header[#header + 1] = t('Throttle')
end
header[#header + 1] = t('Name')
header[#header + 1] = t('Version')
header[#header + 1] = t('Description')
-- Pull package information from module list and start grouping modules.
modules = form['validation_modules']['#value']
local packages = {}
for _, module in pairs(modules) do
if not hv(module['info']) or not hv(module['info']['package']) then
module['info']['package'] = t('Other')
end
if not packages[module['info']['package']] then
packages[module['info']['package']] = {}
end
packages[module['info']['package']][module['name']] = module['info']
end
-- ksort(packages)
-- Display packages.
local output = ajato_string()
for package, modules in pairs(packages) do
local rows = {}
for key, module in pairs(modules) do
local row = {}
local description = ajato_string(ajato_element_render(form['description'][key]))
-- Status checkbox
row[#row + 1] = {['data'] = ajato_element_render(form['status'][key]), ['align'] = 'center'}
if ajato_module_isenabled('throttle') then
row[#row + 1] = {['data'] = ajato_element_render(form['throttle'][key]), ['align'] = 'center'}
end
-- Module name, version and description
row[#row + 1] = ''.. ajato_element_render(form['name'][key]) ..''
row[#row + 1] = ajato_element_render(form['version'][key]) or ''
row[#row + 1] = {['data'] = tostring(description), ['class'] = 'description'}
rows[#rows + 1] = row
end
local fieldset = {
['#title'] = t(package),
['#collapsible'] = true,
['#collapsed'] = (package == 'Core - required'),
['#value'] = theme('table', header, rows, {['class'] = 'package'}),
}
output = output .. theme('fieldset', fieldset)
end
output = output .. ajato_element_render(form)
return tostring(output)
end