--[[ - @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] = ''; 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