status report for more information.', array('@status' => url('admin/reports/status'))), 'error'); } $blocks = array(); if ($admin = db_query("SELECT menu_name, mlid FROM {menu_links} WHERE link_path = 'admin/config' AND module = 'system'")->fetchAssoc()) { $result = db_query(" SELECT m.*, ml.* FROM {menu_links} ml INNER JOIN {menu_router} m ON ml.router_path = m.path WHERE ml.link_path <> 'admin/help' AND menu_name = :menu_name AND ml.plid = :mlid AND hidden = 0", $admin, array('fetch' => PDO::FETCH_ASSOC)); foreach ($result as $item) { _menu_link_translate($item); if (!$item['access']) { continue; } // The link description, either derived from 'description' in hook_menu() // or customized via menu module is used as title attribute. if (!empty($item['localized_options']['attributes']['title'])) { $item['description'] = $item['localized_options']['attributes']['title']; unset($item['localized_options']['attributes']['title']); } $block = $item; $block['content'] = ''; $block['content'] .= theme('admin_block_content', array('content' => system_admin_menu_block($item))); if (!empty($block['content'])) { $block['show'] = TRUE; } // Prepare for sorting as in function _menu_tree_check_access(). // The weight is offset so it is always positive, with a uniform 5-digits. $blocks[(50000 + $item['weight']) . ' ' . $item['title'] . ' ' . $item['mlid']] = $block; } } if ($blocks) { ksort($blocks); return theme('admin_page', array('blocks' => $blocks)); } else { return t('You do not have any administrative items.'); } } /** * Provide a single block from the administration menu as a page. * * This function is often a destination for these blocks. * For example, 'admin/structure/types' needs to have a destination to be valid * in the Drupal menu system, but too much information there might be * hidden, so we supply the contents of the block. * * @return * The output HTML. */ function system_admin_menu_block_page() { $item = menu_get_item(); if ($content = system_admin_menu_block($item)) { $output = theme('admin_block_content', array('content' => $content)); } else { $output = t('You do not have any administrative items.'); } return $output; } /** * Menu callback; prints a listing of admin tasks, organized by module. */ function system_admin_index() { $module_info = system_get_info('module'); foreach ($module_info as $module => $info) { $module_info[$module] = new stdClass(); $module_info[$module]->info = $info; } uasort($module_info, 'system_sort_modules_by_info_name'); $menu_items = array(); foreach ($module_info as $module => $info) { // Only display a section if there are any available tasks. if ($admin_tasks = system_get_module_admin_tasks($module, $info->info)) { // Sort links by title. uasort($admin_tasks, 'drupal_sort_title'); // Move 'Configure permissions' links to the bottom of each section. $permission_key = "admin/people/permissions#module-$module"; if (isset($admin_tasks[$permission_key])) { $permission_task = $admin_tasks[$permission_key]; unset($admin_tasks[$permission_key]); $admin_tasks[$permission_key] = $permission_task; } $menu_items[$info->info['name']] = array($info->info['description'], $admin_tasks); } } return theme('system_admin_index', array('menu_items' => $menu_items)); } /** * Displays the configuration overview page. * * This menu callback implementation is a legacy function that used to display * the configuration overview page at admin/config. It is currently unused and * will be removed in Drupal 8. The page at admin/config is now generated by * system_admin_config_page(). * * @deprecated * @see system_admin_config_page() */ function system_settings_overview() { // Check database setup if necessary if (function_exists('db_check_setup') && empty($_POST)) { db_check_setup(); } $item = menu_get_item('admin/config'); $content = system_admin_menu_block($item); $output = theme('admin_block_content', array('content' => $content)); return $output; } /** * Menu callback; displays a listing of all themes. */ function system_themes_page() { // Get current list of themes. $themes = system_rebuild_theme_data(); uasort($themes, 'system_sort_modules_by_info_name'); $theme_default = variable_get('theme_default', 'bartik'); $theme_groups = array(); foreach ($themes as &$theme) { if (!empty($theme->info['hidden'])) { continue; } $admin_theme_options[$theme->name] = $theme->info['name']; $theme->is_default = ($theme->name == $theme_default); // Identify theme screenshot. $theme->screenshot = NULL; // Create a list which includes the current theme and all its base themes. if (isset($themes[$theme->name]->base_themes)) { $theme_keys = array_keys($themes[$theme->name]->base_themes); $theme_keys[] = $theme->name; } else { $theme_keys = array($theme->name); } // Look for a screenshot in the current theme or in its closest ancestor. foreach (array_reverse($theme_keys) as $theme_key) { if (isset($themes[$theme_key]) && file_exists($themes[$theme_key]->info['screenshot'])) { $theme->screenshot = array( 'path' => $themes[$theme_key]->info['screenshot'], 'alt' => t('Screenshot for !theme theme', array('!theme' => $theme->info['name'])), 'title' => t('Screenshot for !theme theme', array('!theme' => $theme->info['name'])), 'attributes' => array('class' => array('screenshot')), ); break; } } if (empty($theme->status)) { // Ensure this theme is compatible with this version of core. // Require the 'content' region to make sure the main page // content has a common place in all themes. $theme->incompatible_core = !isset($theme->info['core']) || ($theme->info['core'] != DRUPAL_CORE_COMPATIBILITY) || (!isset($theme->info['regions']['content'])); $theme->incompatible_php = version_compare(phpversion(), $theme->info['php']) < 0; } $query['token'] = drupal_get_token('system-theme-operation-link'); $theme->operations = array(); if (!empty($theme->status) || !$theme->incompatible_core && !$theme->incompatible_php) { // Create the operations links. $query['theme'] = $theme->name; if (drupal_theme_access($theme)) { $theme->operations[] = array( 'title' => t('Settings'), 'href' => 'admin/appearance/settings/' . $theme->name, 'attributes' => array('title' => t('Settings for !theme theme', array('!theme' => $theme->info['name']))), ); } if (!empty($theme->status)) { if (!$theme->is_default) { $theme->operations[] = array( 'title' => t('Disable'), 'href' => 'admin/appearance/disable', 'query' => $query, 'attributes' => array('title' => t('Disable !theme theme', array('!theme' => $theme->info['name']))), ); $theme->operations[] = array( 'title' => t('Set default'), 'href' => 'admin/appearance/default', 'query' => $query, 'attributes' => array('title' => t('Set !theme as default theme', array('!theme' => $theme->info['name']))), ); } } else { $theme->operations[] = array( 'title' => t('Enable'), 'href' => 'admin/appearance/enable', 'query' => $query, 'attributes' => array('title' => t('Enable !theme theme', array('!theme' => $theme->info['name']))), ); $theme->operations[] = array( 'title' => t('Enable and set default'), 'href' => 'admin/appearance/default', 'query' => $query, 'attributes' => array('title' => t('Enable !theme as default theme', array('!theme' => $theme->info['name']))), ); } } // Add notes to default and administration theme. $theme->notes = array(); $theme->classes = array(); if ($theme->is_default) { $theme->classes[] = 'theme-default'; $theme->notes[] = t('default theme'); } // Sort enabled and disabled themes into their own groups. $theme_groups[$theme->status ? 'enabled' : 'disabled'][] = $theme; } // There are two possible theme groups. $theme_group_titles = array( 'enabled' => format_plural(count($theme_groups['enabled']), 'Enabled theme', 'Enabled themes'), ); if (!empty($theme_groups['disabled'])) { $theme_group_titles['disabled'] = format_plural(count($theme_groups['disabled']), 'Disabled theme', 'Disabled themes'); } uasort($theme_groups['enabled'], 'system_sort_themes'); drupal_alter('system_themes_page', $theme_groups); $admin_form = drupal_get_form('system_themes_admin_form', $admin_theme_options); return theme('system_themes_page', array('theme_groups' => $theme_groups, 'theme_group_titles' => $theme_group_titles)) . drupal_render($admin_form); } /** * Form to select the administration theme. * * @ingroup forms * @see system_themes_admin_form_submit() */ function system_themes_admin_form($form, &$form_state, $theme_options) { // Administration theme settings. $form['admin_theme'] = array( '#type' => 'fieldset', '#title' => t('Administration theme'), ); $form['admin_theme']['admin_theme'] = array( '#type' => 'select', '#options' => array(0 => t('Default theme')) + $theme_options, '#title' => t('Administration theme'), '#description' => t('Choose "Default theme" to always use the same theme as the rest of the site.'), '#default_value' => variable_get('admin_theme', 0), ); $form['admin_theme']['node_admin_theme'] = array( '#type' => 'checkbox', '#title' => t('Use the administration theme when editing or creating content'), '#default_value' => variable_get('node_admin_theme', '0'), ); $form['admin_theme']['actions'] = array('#type' => 'actions'); $form['admin_theme']['actions']['submit'] = array( '#type' => 'submit', '#value' => t('Save configuration'), ); return $form; } /** * Process system_themes_admin_form form submissions. */ function system_themes_admin_form_submit($form, &$form_state) { drupal_set_message(t('The configuration options have been saved.')); variable_set('admin_theme', $form_state['values']['admin_theme']); variable_set('node_admin_theme', $form_state['values']['node_admin_theme']); } /** * Menu callback; Enables a theme. */ function system_theme_enable() { if (isset($_REQUEST['theme']) && isset($_REQUEST['token']) && drupal_valid_token($_REQUEST['token'], 'system-theme-operation-link')) { $theme = $_REQUEST['theme']; // Get current list of themes. $themes = list_themes(); // Check if the specified theme is one recognized by the system. if (!empty($themes[$theme])) { theme_enable(array($theme)); drupal_set_message(t('The %theme theme has been enabled.', array('%theme' => $themes[$theme]->info['name']))); } else { drupal_set_message(t('The %theme theme was not found.', array('%theme' => $theme)), 'error'); } drupal_goto('admin/appearance'); } return MENU_ACCESS_DENIED; } /** * Menu callback; Disables a theme. */ function system_theme_disable() { if (isset($_REQUEST['theme']) && isset($_REQUEST['token']) && drupal_valid_token($_REQUEST['token'], 'system-theme-operation-link')) { $theme = $_REQUEST['theme']; // Get current list of themes. $themes = list_themes(); // Check if the specified theme is one recognized by the system. if (!empty($themes[$theme])) { if ($theme == variable_get('theme_default', 'bartik')) { // Don't disable the default theme. drupal_set_message(t('%theme is the default theme and cannot be disabled.', array('%theme' => $themes[$theme]->info['name'])), 'error'); } else { theme_disable(array($theme)); drupal_set_message(t('The %theme theme has been disabled.', array('%theme' => $themes[$theme]->info['name']))); } } else { drupal_set_message(t('The %theme theme was not found.', array('%theme' => $theme)), 'error'); } drupal_goto('admin/appearance'); } return MENU_ACCESS_DENIED; } /** * Menu callback; Set the default theme. */ function system_theme_default() { if (isset($_REQUEST['theme']) && isset($_REQUEST['token']) && drupal_valid_token($_REQUEST['token'], 'system-theme-operation-link')) { $theme = $_REQUEST['theme']; // Get current list of themes. $themes = list_themes(); // Check if the specified theme is one recognized by the system. if (!empty($themes[$theme])) { // Enable the theme if it is currently disabled. if (empty($themes[$theme]->status)) { theme_enable(array($theme)); } // Set the default theme. variable_set('theme_default', $theme); // Rebuild the menu. This duplicates the menu_rebuild() in theme_enable(). // However, modules must know the current default theme in order to use // this information in hook_menu() or hook_menu_alter() implementations, // and doing the variable_set() before the theme_enable() could result // in a race condition where the theme is default but not enabled. menu_rebuild(); // The status message depends on whether an admin theme is currently in use: // a value of 0 means the admin theme is set to be the default theme. $admin_theme = variable_get('admin_theme', 0); if ($admin_theme != 0 && $admin_theme != $theme) { drupal_set_message(t('Please note that the administration theme is still set to the %admin_theme theme; consequently, the theme on this page remains unchanged. All non-administrative sections of the site, however, will show the selected %selected_theme theme by default.', array( '%admin_theme' => $themes[$admin_theme]->info['name'], '%selected_theme' => $themes[$theme]->info['name'], ))); } else { drupal_set_message(t('%theme is now the default theme.', array('%theme' => $themes[$theme]->info['name']))); } } else { drupal_set_message(t('The %theme theme was not found.', array('%theme' => $theme)), 'error'); } drupal_goto('admin/appearance'); } return MENU_ACCESS_DENIED; } /** * Form builder; display theme configuration for entire site and individual themes. * * @param $key * A theme name. * @return * The form structure. * @ingroup forms * @see system_theme_settings_submit() */ function system_theme_settings($form, &$form_state, $key = '') { // Default settings are defined in theme_get_setting() in includes/theme.inc if ($key) { $var = 'theme_' . $key . '_settings'; $themes = list_themes(); $features = $themes[$key]->info['features']; } else { $var = 'theme_settings'; } $form['var'] = array('#type' => 'hidden', '#value' => $var); // Toggle settings $toggles = array( 'logo' => t('Logo'), 'name' => t('Site name'), 'slogan' => t('Site slogan'), 'node_user_picture' => t('User pictures in posts'), 'comment_user_picture' => t('User pictures in comments'), 'comment_user_verification' => t('User verification status in comments'), 'favicon' => t('Shortcut icon'), 'main_menu' => t('Main menu'), 'secondary_menu' => t('Secondary menu'), ); // Some features are not always available $disabled = array(); if (!variable_get('user_pictures', 0)) { $disabled['toggle_node_user_picture'] = TRUE; $disabled['toggle_comment_user_picture'] = TRUE; } if (!module_exists('comment')) { $disabled['toggle_comment_user_picture'] = TRUE; $disabled['toggle_comment_user_verification'] = TRUE; } $form['theme_settings'] = array( '#type' => 'fieldset', '#title' => t('Toggle display'), '#description' => t('Enable or disable the display of certain page elements.'), ); foreach ($toggles as $name => $title) { if ((!$key) || in_array($name, $features)) { $form['theme_settings']['toggle_' . $name] = array('#type' => 'checkbox', '#title' => $title, '#default_value' => theme_get_setting('toggle_' . $name, $key)); // Disable checkboxes for features not supported in the current configuration. if (isset($disabled['toggle_' . $name])) { $form['theme_settings']['toggle_' . $name]['#disabled'] = TRUE; } } } if (!element_children($form['theme_settings'])) { // If there is no element in the theme settings fieldset then do not show // it -- but keep it in the form if another module wants to alter. $form['theme_settings']['#access'] = FALSE; } // Logo settings if ((!$key) || in_array('logo', $features)) { $form['logo'] = array( '#type' => 'fieldset', '#title' => t('Logo image settings'), '#description' => t('If toggled on, the following logo will be displayed.'), '#attributes' => array('class' => array('theme-settings-bottom')), ); $form['logo']['default_logo'] = array( '#type' => 'checkbox', '#title' => t('Use the default logo'), '#default_value' => theme_get_setting('default_logo', $key), '#tree' => FALSE, '#description' => t('Check here if you want the theme to use the logo supplied with it.') ); $form['logo']['settings'] = array( '#type' => 'container', '#states' => array( // Hide the logo settings when using the default logo. 'invisible' => array( 'input[name="default_logo"]' => array('checked' => TRUE), ), ), ); $form['logo']['settings']['logo_path'] = array( '#type' => 'textfield', '#title' => t('Path to custom logo'), '#description' => t('The path to the file you would like to use as your logo file instead of the default logo.'), '#default_value' => theme_get_setting('logo_path', $key), ); $form['logo']['settings']['logo_upload'] = array( '#type' => 'file', '#title' => t('Upload logo image'), '#maxlength' => 40, '#description' => t("If you don't have direct file access to the server, use this field to upload your logo.") ); } if ((!$key) || in_array('favicon', $features)) { $form['favicon'] = array( '#type' => 'fieldset', '#title' => t('Shortcut icon settings'), '#description' => t("Your shortcut icon, or 'favicon', is displayed in the address bar and bookmarks of most browsers."), ); $form['favicon']['default_favicon'] = array( '#type' => 'checkbox', '#title' => t('Use the default shortcut icon.'), '#default_value' => theme_get_setting('default_favicon', $key), '#description' => t('Check here if you want the theme to use the default shortcut icon.') ); $form['favicon']['settings'] = array( '#type' => 'container', '#states' => array( // Hide the favicon settings when using the default favicon. 'invisible' => array( 'input[name="default_favicon"]' => array('checked' => TRUE), ), ), ); $form['favicon']['settings']['favicon_path'] = array( '#type' => 'textfield', '#title' => t('Path to custom icon'), '#description' => t('The path to the image file you would like to use as your custom shortcut icon.'), '#default_value' => theme_get_setting('favicon_path', $key), ); $form['favicon']['settings']['favicon_upload'] = array( '#type' => 'file', '#title' => t('Upload icon image'), '#description' => t("If you don't have direct file access to the server, use this field to upload your shortcut icon.") ); } // Inject human-friendly values for logo and favicon. foreach (array('logo' => 'logo.png', 'favicon' => 'favicon.ico') as $type => $default) { if (isset($form[$type]['settings'][$type . '_path'])) { $element = &$form[$type]['settings'][$type . '_path']; // If path is a public:// URI, display the path relative to the files // directory; stream wrappers are not end-user friendly. $original_path = $element['#default_value']; $friendly_path = NULL; if (file_uri_scheme($original_path) == 'public') { $friendly_path = file_uri_target($original_path); $element['#default_value'] = $friendly_path; } } } if ($key) { // Call engine-specific settings. $function = $themes[$key]->prefix . '_engine_settings'; if (function_exists($function)) { $form['engine_specific'] = array( '#type' => 'fieldset', '#title' => t('Theme-engine-specific settings'), '#description' => t('These settings only exist for the themes based on the %engine theme engine.', array('%engine' => $themes[$key]->prefix)), ); $function($form, $form_state); } // Create a list which includes the current theme and all its base themes. if (isset($themes[$key]->base_themes)) { $theme_keys = array_keys($themes[$key]->base_themes); $theme_keys[] = $key; } else { $theme_keys = array($key); } // Save the name of the current theme (if any), so that we can temporarily // override the current theme and allow theme_get_setting() to work // without having to pass the theme name to it. $default_theme = !empty($GLOBALS['theme_key']) ? $GLOBALS['theme_key'] : NULL; $GLOBALS['theme_key'] = $key; // Process the theme and all its base themes. foreach ($theme_keys as $theme) { // Include the theme-settings.php file. $theme_settings_path = drupal_get_path('theme', $theme) . '/theme-settings.php'; if (file_exists(DRUPAL_ROOT . '/' . $theme_settings_path)) { require_once DRUPAL_ROOT . '/' . $theme_settings_path; $form_state['build_info']['files'][] = $theme_settings_path; } // Call theme-specific settings. $function = $theme . '_form_system_theme_settings_alter'; if (function_exists($function)) { $function($form, $form_state); } } // Restore the original current theme. if (isset($default_theme)) { $GLOBALS['theme_key'] = $default_theme; } else { unset($GLOBALS['theme_key']); } } $form = system_settings_form($form); // We don't want to call system_settings_form_submit(), so change #submit. array_pop($form['#submit']); $form['#submit'][] = 'system_theme_settings_submit'; $form['#validate'][] = 'system_theme_settings_validate'; return $form; } /** * Validator for the system_theme_settings() form. */ function system_theme_settings_validate($form, &$form_state) { // Handle file uploads. $validators = array('file_validate_is_image' => array()); // Check for a new uploaded logo. $file = file_save_upload('logo_upload', $validators); if (isset($file)) { // File upload was attempted. if ($file) { // Put the temporary file in form_values so we can save it on submit. $form_state['values']['logo_upload'] = $file; } else { // File upload failed. form_set_error('logo_upload', t('The logo could not be uploaded.')); } } $validators = array('file_validate_extensions' => array('ico png gif jpg jpeg apng svg')); // Check for a new uploaded favicon. $file = file_save_upload('favicon_upload', $validators); if (isset($file)) { // File upload was attempted. if ($file) { // Put the temporary file in form_values so we can save it on submit. $form_state['values']['favicon_upload'] = $file; } else { // File upload failed. form_set_error('favicon_upload', t('The favicon could not be uploaded.')); } } // If the user provided a path for a logo or favicon file, make sure a file // exists at that path. if (!empty($form_state['values']['logo_path'])) { $path = _system_theme_settings_validate_path($form_state['values']['logo_path']); if (!$path) { form_set_error('logo_path', t('The custom logo path is invalid.')); } } if (!empty($form_state['values']['favicon_path'])) { $path = _system_theme_settings_validate_path($form_state['values']['favicon_path']); if (!$path) { form_set_error('favicon_path', t('The custom favicon path is invalid.')); } } } /** * Helper function for the system_theme_settings form. * * Attempts to validate normal system paths, paths relative to the public files * directory, or stream wrapper URIs. If the given path is any of the above, * returns a valid path or URI that the theme system can display. * * @param $path * A path relative to the Drupal root or to the public files directory, or * a stream wrapper URI. * @return mixed * A valid path that can be displayed through the theme system, or FALSE if * the path could not be validated. */ function _system_theme_settings_validate_path($path) { // Absolute local file paths are invalid. if (drupal_realpath($path) == $path) { return FALSE; } // A path relative to the Drupal root or a fully qualified URI is valid. if (is_file($path)) { return $path; } // Prepend 'public://' for relative file paths within public filesystem. if (file_uri_scheme($path) === FALSE) { $path = 'public://' . $path; } if (is_file($path)) { return $path; } return FALSE; } /** * Process system_theme_settings form submissions. */ function system_theme_settings_submit($form, &$form_state) { // Exclude unnecessary elements before saving. form_state_values_clean($form_state); $values = $form_state['values']; // Extract the name of the theme from the submitted form values, then remove // it from the array so that it is not saved as part of the variable. $key = $values['var']; unset($values['var']); // If the user uploaded a new logo or favicon, save it to a permanent location // and use it in place of the default theme-provided file. if (!empty($values['logo_upload'])) { $file = $values['logo_upload']; unset($values['logo_upload']); $filename = file_unmanaged_copy($file->uri); $values['default_logo'] = 0; $values['logo_path'] = $filename; $values['toggle_logo'] = 1; } if (!empty($values['favicon_upload'])) { $file = $values['favicon_upload']; unset($values['favicon_upload']); $filename = file_unmanaged_copy($file->uri); $values['default_favicon'] = 0; $values['favicon_path'] = $filename; $values['toggle_favicon'] = 1; } // If the user entered a path relative to the system files directory for // a logo or favicon, store a public:// URI so the theme system can handle it. if (!empty($values['logo_path'])) { $values['logo_path'] = _system_theme_settings_validate_path($values['logo_path']); } if (!empty($values['favicon_path'])) { $values['favicon_path'] = _system_theme_settings_validate_path($values['favicon_path']); } if (empty($values['default_favicon']) && !empty($values['favicon_path'])) { $values['favicon_mimetype'] = file_get_mimetype($values['favicon_path']); } variable_set($key, $values); drupal_set_message(t('The configuration options have been saved.')); cache_clear_all(); } /** * Recursively check compatibility. * * @param $incompatible * An associative array which at the end of the check contains all * incompatible files as the keys, their values being TRUE. * @param $files * The set of files that will be tested. * @param $file * The file at which the check starts. * @return * Returns TRUE if an incompatible file is found, NULL (no return value) * otherwise. */ function _system_is_incompatible(&$incompatible, $files, $file) { if (isset($incompatible[$file->name])) { return TRUE; } // Recursively traverse required modules, looking for incompatible modules. foreach ($file->requires as $requires) { if (isset($files[$requires]) && _system_is_incompatible($incompatible, $files, $files[$requires])) { $incompatible[$file->name] = TRUE; return TRUE; } } } /** * Menu callback; provides module enable/disable interface. * * The list of modules gets populated by module.info files, which contain each * module's name, description, and information about which modules it requires. * See drupal_parse_info_file() for information on module.info descriptors. * * Dependency checking is performed to ensure that a module: * - can not be enabled if there are disabled modules it requires. * - can not be disabled if there are enabled modules which depend on it. * * @param $form_state * An associative array containing the current state of the form. * * @return * The form array. * * @ingroup forms * @see theme_system_modules() * @see system_modules_submit() */ function system_modules($form, $form_state = array()) { // Get current list of modules. $files = system_rebuild_module_data(); // Remove hidden modules from display list. $visible_files = $files; foreach ($visible_files as $filename => $file) { if (!empty($file->info['hidden'])) { unset($visible_files[$filename]); } } uasort($visible_files, 'system_sort_modules_by_info_name'); // If the modules form was submitted, then system_modules_submit() runs first // and if there are unfilled required modules, then $form_state['storage'] is // filled, triggering a rebuild. In this case we need to display a // confirmation form. if (!empty($form_state['storage'])) { return system_modules_confirm_form($visible_files, $form_state['storage']); } $modules = array(); $form['modules'] = array('#tree' => TRUE); // Used when checking if module implements a help page. $help_arg = module_exists('help') ? drupal_help_arg() : FALSE; // Used when displaying modules that are required by the installation profile. require_once DRUPAL_ROOT . '/includes/install.inc'; $distribution_name = check_plain(drupal_install_profile_distribution_name()); // Iterate through each of the modules. foreach ($visible_files as $filename => $module) { $extra = array(); $extra['enabled'] = (bool) $module->status; if (!empty($module->info['required'] )) { $extra['disabled'] = TRUE; $extra['required_by'][] = $distribution_name . (!empty($module->info['explanation']) ? ' ('. $module->info['explanation'] .')' : ''); } // If this module requires other modules, add them to the array. foreach ($module->requires as $requires => $v) { if (!isset($files[$requires])) { $extra['requires'][$requires] = t('@module (missing)', array('@module' => drupal_ucfirst($requires))); $extra['disabled'] = TRUE; } // Only display visible modules. elseif (isset($visible_files[$requires])) { $requires_name = $files[$requires]->info['name']; // Disable this module if it is incompatible with the dependency's version. if ($incompatible_version = drupal_check_incompatibility($v, str_replace(DRUPAL_CORE_COMPATIBILITY . '-', '', (string) $files[$requires]->info['version']))) { $extra['requires'][$requires] = t('@module (incompatible with version @version)', array( '@module' => $requires_name . $incompatible_version, '@version' => $files[$requires]->info['version'], )); $extra['disabled'] = TRUE; } // Disable this module if the dependency is incompatible with this // version of Drupal core. elseif ($files[$requires]->info['core'] != DRUPAL_CORE_COMPATIBILITY) { $extra['requires'][$requires] = t('@module (incompatible with this version of Drupal core)', array( '@module' => $requires_name, )); $extra['disabled'] = TRUE; } elseif ($files[$requires]->status) { $extra['requires'][$requires] = t('@module (enabled)', array('@module' => $requires_name)); } else { $extra['requires'][$requires] = t('@module (disabled)', array('@module' => $requires_name)); } } } // Generate link for module's help page, if there is one. if ($help_arg && $module->status && in_array($filename, module_implements('help'))) { if (module_invoke($filename, 'help', "admin/help#$filename", $help_arg)) { $extra['links']['help'] = array( '#type' => 'link', '#title' => t('Help'), '#href' => "admin/help/$filename", '#options' => array('attributes' => array('class' => array('module-link', 'module-link-help'), 'title' => t('Help'))), ); } } // Generate link for module's permission, if the user has access to it. if ($module->status && user_access('administer permissions') && in_array($filename, module_implements('permission'))) { $extra['links']['permissions'] = array( '#type' => 'link', '#title' => t('Permissions'), '#href' => 'admin/people/permissions', '#options' => array('fragment' => 'module-' . $filename, 'attributes' => array('class' => array('module-link', 'module-link-permissions'), 'title' => t('Configure permissions'))), ); } // Generate link for module's configuration page, if the module provides // one. if ($module->status && isset($module->info['configure'])) { $configure_link = menu_get_item($module->info['configure']); if ($configure_link === FALSE) { watchdog('system', 'Module %module specifies an invalid path for configuration: %configure', array( '%module' => $module->info['name'], '%configure' => $module->info['configure'], )); } else if ($configure_link['access']) { $extra['links']['configure'] = array( '#type' => 'link', '#title' => t('Configure'), '#href' => $configure_link['href'], '#options' => array('attributes' => array('class' => array('module-link', 'module-link-configure'), 'title' => $configure_link['description'])), ); } } // If this module is required by other modules, list those, and then make it // impossible to disable this one. foreach ($module->required_by as $required_by => $v) { // Hidden modules are unset already. if (isset($visible_files[$required_by])) { if ($files[$required_by]->status == 1 && $module->status == 1) { $extra['required_by'][] = t('@module (enabled)', array('@module' => $files[$required_by]->info['name'])); $extra['disabled'] = TRUE; } else { $extra['required_by'][] = t('@module (disabled)', array('@module' => $files[$required_by]->info['name'])); } } } $form['modules'][$module->info['package']][$filename] = _system_modules_build_row($module->info, $extra); } // Add basic information to the fieldsets. foreach (element_children($form['modules']) as $package) { $form['modules'][$package] += array( '#type' => 'fieldset', '#title' => t($package), '#collapsible' => TRUE, '#theme' => 'system_modules_fieldset', '#header' => array( array('data' => t('Enabled'), 'class' => array('checkbox')), t('Name'), t('Version'), t('Description'), array('data' => t('Operations'), 'colspan' => 3), ), // Ensure that the "Core" package fieldset comes first. '#weight' => $package == 'Core' ? -10 : NULL, // Hide this package unless we're running a test. '#access' => !($package == 'Only For Testing' && !drupal_valid_test_ua()), ); } // Lastly, sort all fieldsets by title. uasort($form['modules'], 'element_sort_by_title'); $form['actions'] = array('#type' => 'actions'); $form['actions']['submit'] = array( '#type' => 'submit', '#value' => t('Save configuration'), ); $form['#action'] = url('admin/modules/list/confirm'); return $form; } /** * Array sorting callback; sorts modules or themes by their name. */ function system_sort_modules_by_info_name($a, $b) { return strcasecmp($a->info['name'], $b->info['name']); } /** * Sorts themes by their names, with the default theme listed first. * * Callback for uasort() within system_themes_page(). * * @see system_sort_modules_by_info_name(). */ function system_sort_themes($a, $b) { if ($a->is_default) { return -1; } if ($b->is_default) { return 1; } return strcasecmp($a->info['name'], $b->info['name']); } /** * Build a table row for the system modules page. */ function _system_modules_build_row($info, $extra) { // Add in the defaults. $extra += array( 'requires' => array(), 'required_by' => array(), 'disabled' => FALSE, 'enabled' => FALSE, 'links' => array(), ); $form = array( '#tree' => TRUE, ); // Set the basic properties. $form['name'] = array( '#markup' => $info['name'], ); $form['description'] = array( '#markup' => t($info['description']), ); $form['version'] = array( '#markup' => $info['version'], ); $form['#requires'] = $extra['requires']; $form['#required_by'] = $extra['required_by']; // Check the compatibilities. $compatible = TRUE; $status_short = ''; $status_long = ''; // Initialize empty arrays of long and short reasons explaining why the // module is incompatible. // Add each reason as a separate element in both the arrays. $reasons_short = array(); $reasons_long = array(); // Check the core compatibility. if (!isset($info['core']) || $info['core'] != DRUPAL_CORE_COMPATIBILITY) { $compatible = FALSE; $reasons_short[] = t('Incompatible with this version of Drupal core.'); $reasons_long[] = t('This version is not compatible with Drupal !core_version and should be replaced.', array('!core_version' => DRUPAL_CORE_COMPATIBILITY)); } // Ensure this module is compatible with the currently installed version of PHP. if (version_compare(phpversion(), $info['php']) < 0) { $compatible = FALSE; $reasons_short[] = t('Incompatible with this version of PHP'); $php_required = $info['php']; if (substr_count($info['php'], '.') < 2) { $php_required .= '.*'; } $reasons_long[] = t('This module requires PHP version @php_required and is incompatible with PHP version !php_version.', array('@php_required' => $php_required, '!php_version' => phpversion())); } // If this module is compatible, present a checkbox indicating // this module may be installed. Otherwise, show a big red X. if ($compatible) { $form['enable'] = array( '#type' => 'checkbox', '#title' => t('Enable'), '#default_value' => $extra['enabled'], ); if ($extra['disabled']) { $form['enable']['#disabled'] = TRUE; } } else { $status_short = implode(' ', $reasons_short); $status_long = implode(' ', $reasons_long); $form['enable'] = array( '#markup' => theme('image', array('path' => 'misc/watchdog-error.png', 'alt' => $status_short, 'title' => $status_short)), ); $form['description']['#markup'] .= theme('system_modules_incompatible', array('message' => $status_long)); } // Build operation links. foreach (array('help', 'permissions', 'configure') as $key) { $form['links'][$key] = (isset($extra['links'][$key]) ? $extra['links'][$key] : array()); } return $form; } /** * Display confirmation form for required modules. * * @param $modules * Array of module file objects as returned from system_rebuild_module_data(). * @param $storage * The contents of $form_state['storage']; an array with two * elements: the list of required modules and the list of status * form field values from the previous screen. * @ingroup forms */ function system_modules_confirm_form($modules, $storage) { $items = array(); $form['validation_modules'] = array('#type' => 'value', '#value' => $modules); $form['status']['#tree'] = TRUE; foreach ($storage['more_required'] as $info) { $t_argument = array( '@module' => $info['name'], '@required' => implode(', ', $info['requires']), ); $items[] = format_plural(count($info['requires']), 'You must enable the @required module to install @module.', 'You must enable the @required modules to install @module.', $t_argument); } foreach ($storage['missing_modules'] as $name => $info) { $t_argument = array( '@module' => $name, '@depends' => implode(', ', $info['depends']), ); $items[] = format_plural(count($info['depends']), 'The @module module is missing, so the following module will be disabled: @depends.', 'The @module module is missing, so the following modules will be disabled: @depends.', $t_argument); } $form['text'] = array('#markup' => theme('item_list', array('items' => $items))); if ($form) { // Set some default form values $form = confirm_form( $form, t('Some required modules must be enabled'), 'admin/modules', t('Would you like to continue with the above?'), t('Continue'), t('Cancel')); return $form; } } /** * Submit callback; handles modules form submission. */ function system_modules_submit($form, &$form_state) { include_once DRUPAL_ROOT . '/includes/install.inc'; // Builds list of modules. $modules = array(); // If we're not coming from the confirmation form, build the list of modules. if (empty($form_state['storage'])) { // If we're not coming from the confirmation form, build the module list. foreach ($form_state['values']['modules'] as $group_name => $group) { foreach ($group as $module => $enabled) { $modules[$module] = array('group' => $group_name, 'enabled' => $enabled['enable']); } } } else { // If we are coming from the confirmation form, fetch // the modules out of $form_state. $modules = $form_state['storage']['modules']; } // Collect data for all modules to be able to determine dependencies. $files = system_rebuild_module_data(); // Sorts modules by weight. $sort = array(); foreach (array_keys($modules) as $module) { $sort[$module] = $files[$module]->sort; } array_multisort($sort, $modules); // Makes sure all required modules are set to be enabled. $more_required = array(); $missing_modules = array(); foreach ($modules as $name => $module) { if ($module['enabled']) { // Checks that all dependencies are set to be enabled. Stores the ones // that are not in $dependencies variable so that the user can be alerted // in the confirmation form that more modules need to be enabled. $dependencies = array(); foreach (array_keys($files[$name]->requires) as $required) { if (empty($modules[$required]['enabled'])) { if (isset($files[$required])) { $dependencies[] = $files[$required]->info['name']; $modules[$required]['enabled'] = TRUE; } else { $missing_modules[$required]['depends'][] = $name; $modules[$name]['enabled'] = FALSE; } } } // Stores additional modules that need to be enabled in $more_required. if (!empty($dependencies)) { $more_required[$name] = array( 'name' => $files[$name]->info['name'], 'requires' => $dependencies, ); } } } // Redirects to confirmation form if more modules need to be enabled. if ((!empty($more_required) || !empty($missing_modules)) && !isset($form_state['values']['confirm'])) { $form_state['storage'] = array( 'more_required' => $more_required, 'modules' => $modules, 'missing_modules' => $missing_modules, ); $form_state['rebuild'] = TRUE; return; } // Invokes hook_requirements('install'). If failures are detected, makes sure // the dependent modules aren't installed either. foreach ($modules as $name => $module) { // Only invoke hook_requirements() on modules that are going to be installed. if ($module['enabled'] && drupal_get_installed_schema_version($name) == SCHEMA_UNINSTALLED) { if (!drupal_check_module($name)) { $modules[$name]['enabled'] = FALSE; foreach (array_keys($files[$name]->required_by) as $required_by) { $modules[$required_by]['enabled'] = FALSE; } } } } // Initializes array of actions. $actions = array( 'enable' => array(), 'disable' => array(), 'install' => array(), ); // Builds arrays of modules that need to be enabled, disabled, and installed. foreach ($modules as $name => $module) { if ($module['enabled']) { if (drupal_get_installed_schema_version($name) == SCHEMA_UNINSTALLED) { $actions['install'][] = $name; $actions['enable'][] = $name; } elseif (!module_exists($name)) { $actions['enable'][] = $name; } } elseif (module_exists($name)) { $actions['disable'][] = $name; } } // Gets list of modules prior to install process, unsets $form_state['storage'] // so we don't get redirected back to the confirmation form. $pre_install_list = module_list(); unset($form_state['storage']); // Reverse the 'enable' list, to order dependencies before dependents. krsort($actions['enable']); // Installs, enables, and disables modules. module_enable($actions['enable'], FALSE); module_disable($actions['disable'], FALSE); // Gets module list after install process, flushes caches and displays a // message if there are changes. $post_install_list = module_list(TRUE); if ($pre_install_list != $post_install_list) { drupal_flush_all_caches(); drupal_set_message(t('The configuration options have been saved.')); } $form_state['redirect'] = 'admin/modules'; } /** * Uninstall functions */ /** * Builds a form of currently disabled modules. * * @ingroup forms * @see system_modules_uninstall_validate() * @see system_modules_uninstall_submit() * @param $form_state['values'] * Submitted form values. * @return * A form array representing the currently disabled modules. */ function system_modules_uninstall($form, $form_state = NULL) { // Make sure the install API is available. include_once DRUPAL_ROOT . '/includes/install.inc'; // Display the confirm form if any modules have been submitted. if (!empty($form_state['storage']) && $confirm_form = system_modules_uninstall_confirm_form($form_state['storage'])) { return $confirm_form; } // Get a list of disabled, installed modules. $all_modules = system_rebuild_module_data(); $disabled_modules = array(); foreach ($all_modules as $name => $module) { if (empty($module->status) && $module->schema_version > SCHEMA_UNINSTALLED) { $disabled_modules[$name] = $module; } } // Only build the rest of the form if there are any modules available to // uninstall. if (!empty($disabled_modules)) { $profile = drupal_get_profile(); uasort($disabled_modules, 'system_sort_modules_by_info_name'); $form['uninstall'] = array('#tree' => TRUE); foreach ($disabled_modules as $module) { $module_name = $module->info['name'] ? $module->info['name'] : $module->name; $form['modules'][$module->name]['#module_name'] = $module_name; $form['modules'][$module->name]['name']['#markup'] = $module_name; $form['modules'][$module->name]['description']['#markup'] = t($module->info['description']); $form['uninstall'][$module->name] = array( '#type' => 'checkbox', '#title' => t('Uninstall @module module', array('@module' => $module_name)), '#title_display' => 'invisible', ); // All modules which depend on this one must be uninstalled first, before // we can allow this module to be uninstalled. (The installation profile // is excluded from this list.) foreach (array_keys($module->required_by) as $dependent) { if ($dependent != $profile && drupal_get_installed_schema_version($dependent) != SCHEMA_UNINSTALLED) { $dependent_name = isset($all_modules[$dependent]->info['name']) ? $all_modules[$dependent]->info['name'] : $dependent; $form['modules'][$module->name]['#required_by'][] = $dependent_name; $form['uninstall'][$module->name]['#disabled'] = TRUE; } } } $form['actions'] = array('#type' => 'actions'); $form['actions']['submit'] = array( '#type' => 'submit', '#value' => t('Uninstall'), ); $form['#action'] = url('admin/modules/uninstall/confirm'); } else { $form['modules'] = array(); } return $form; } /** * Confirm uninstall of selected modules. * * @ingroup forms * @param $storage * An associative array of modules selected to be uninstalled. * @return * A form array representing modules to confirm. */ function system_modules_uninstall_confirm_form($storage) { // Nothing to build. if (empty($storage)) { return; } // Construct the hidden form elements and list items. foreach (array_filter($storage['uninstall']) as $module => $value) { $info = drupal_parse_info_file(drupal_get_path('module', $module) . '/' . $module . '.info'); $uninstall[] = $info['name']; $form['uninstall'][$module] = array('#type' => 'hidden', '#value' => 1, ); } // Display a confirm form if modules have been selected. if (isset($uninstall)) { $form['#confirmed'] = TRUE; $form['uninstall']['#tree'] = TRUE; $form['modules'] = array('#markup' => '
' . t('The following modules will be completely uninstalled from your site, and all data from these modules will be lost!') . '
' . theme('item_list', array('items' => $uninstall))); $form = confirm_form( $form, t('Confirm uninstall'), 'admin/modules/uninstall', t('Would you like to continue with uninstalling the above?'), t('Uninstall'), t('Cancel')); return $form; } } /** * Validates the submitted uninstall form. */ function system_modules_uninstall_validate($form, &$form_state) { // Form submitted, but no modules selected. if (!count(array_filter($form_state['values']['uninstall']))) { drupal_set_message(t('No modules selected.'), 'error'); drupal_goto('admin/modules/uninstall'); } } /** * Processes the submitted uninstall form. */ function system_modules_uninstall_submit($form, &$form_state) { // Make sure the install API is available. include_once DRUPAL_ROOT . '/includes/install.inc'; if (!empty($form['#confirmed'])) { // Call the uninstall routine for each selected module. $modules = array_keys($form_state['values']['uninstall']); drupal_uninstall_modules($modules); drupal_set_message(t('The selected modules have been uninstalled.')); $form_state['redirect'] = 'admin/modules/uninstall'; } else { $form_state['storage'] = $form_state['values']; $form_state['rebuild'] = TRUE; } } /** * Menu callback. Display blocked IP addresses. * * @param $default_ip * Optional IP address to be passed on to drupal_get_form() for * use as the default value of the IP address form field. */ function system_ip_blocking($default_ip = '') { $rows = array(); $header = array(t('Blocked IP addresses'), t('Operations')); $result = db_query('SELECT * FROM {blocked_ips}'); foreach ($result as $ip) { $rows[] = array( $ip->ip, l(t('delete'), "admin/config/people/ip-blocking/delete/$ip->iid"), ); } $build['system_ip_blocking_form'] = drupal_get_form('system_ip_blocking_form', $default_ip); $build['system_ip_blocking_table'] = array( '#theme' => 'table', '#header' => $header, '#rows' => $rows, '#empty' => t('No blocked IP addresses available.'), ); return $build; } /** * Define the form for blocking IP addresses. * * @ingroup forms * @see system_ip_blocking_form_validate() * @see system_ip_blocking_form_submit() */ function system_ip_blocking_form($form, $form_state, $default_ip) { $form['ip'] = array( '#title' => t('IP address'), '#type' => 'textfield', '#size' => 48, '#maxlength' => 40, '#default_value' => $default_ip, '#description' => t('Enter a valid IP address.'), ); $form['actions'] = array('#type' => 'actions'); $form['actions']['submit'] = array( '#type' => 'submit', '#value' => t('Add'), ); $form['#submit'][] = 'system_ip_blocking_form_submit'; $form['#validate'][] = 'system_ip_blocking_form_validate'; return $form; } function system_ip_blocking_form_validate($form, &$form_state) { $ip = trim($form_state['values']['ip']); if (db_query("SELECT * FROM {blocked_ips} WHERE ip = :ip", array(':ip' => $ip))->fetchField()) { form_set_error('ip', t('This IP address is already blocked.')); } elseif ($ip == ip_address()) { form_set_error('ip', t('You may not block your own IP address.')); } elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE) == FALSE) { form_set_error('ip', t('Enter a valid IP address.')); } } function system_ip_blocking_form_submit($form, &$form_state) { $ip = trim($form_state['values']['ip']); db_insert('blocked_ips') ->fields(array('ip' => $ip)) ->execute(); drupal_set_message(t('The IP address %ip has been blocked.', array('%ip' => $ip))); $form_state['redirect'] = 'admin/config/people/ip-blocking'; return; } /** * IP deletion confirm page. * * @see system_ip_blocking_delete_submit() */ function system_ip_blocking_delete($form, &$form_state, $iid) { $form['blocked_ip'] = array( '#type' => 'value', '#value' => $iid, ); return confirm_form($form, t('Are you sure you want to delete %ip?', array('%ip' => $iid['ip'])), 'admin/config/people/ip-blocking', t('This action cannot be undone.'), t('Delete'), t('Cancel')); } /** * Process system_ip_blocking_delete form submissions. */ function system_ip_blocking_delete_submit($form, &$form_state) { $blocked_ip = $form_state['values']['blocked_ip']; db_delete('blocked_ips') ->condition('iid', $blocked_ip['iid']) ->execute(); watchdog('user', 'Deleted %ip', array('%ip' => $blocked_ip['ip'])); drupal_set_message(t('The IP address %ip was deleted.', array('%ip' => $blocked_ip['ip']))); $form_state['redirect'] = 'admin/config/people/ip-blocking'; } /** * Form builder; The general site information form. * * @ingroup forms * @see system_settings_form() */ function system_site_information_settings() { $form['site_information'] = array( '#type' => 'fieldset', '#title' => t('Site details'), ); $form['site_information']['site_name'] = array( '#type' => 'textfield', '#title' => t('Site name'), '#default_value' => variable_get('site_name', 'Drupal'), '#required' => TRUE ); $form['site_information']['site_slogan'] = array( '#type' => 'textfield', '#title' => t('Slogan'), '#default_value' => variable_get('site_slogan', ''), '#description' => t("How this is used depends on your site's theme."), ); $form['site_information']['site_mail'] = array( '#type' => 'textfield', '#title' => t('E-mail address'), '#default_value' => variable_get('site_mail', ini_get('sendmail_from')), '#description' => t("The From address in automated e-mails sent during registration and new password requests, and other notifications. (Use an address ending in your site's domain to help prevent this e-mail being flagged as spam.)"), '#required' => TRUE, ); $form['front_page'] = array( '#type' => 'fieldset', '#title' => t('Front page'), ); $form['front_page']['default_nodes_main'] = array( '#type' => 'select', '#title' => t('Number of posts on front page'), '#default_value' => variable_get('default_nodes_main', 10), '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30)), '#description' => t('The maximum number of posts displayed on overview pages such as the front page.') ); $form['front_page']['site_frontpage'] = array( '#type' => 'textfield', '#title' => t('Default front page'), '#default_value' => (variable_get('site_frontpage')!='node'?drupal_get_path_alias(variable_get('site_frontpage', 'node')):''), '#size' => 40, '#description' => t('Optionally, specify a relative URL to display as the front page. Leave blank to display the default content feed.'), '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q='), ); $form['error_page'] = array( '#type' => 'fieldset', '#title' => t('Error pages'), ); $form['error_page']['site_403'] = array( '#type' => 'textfield', '#title' => t('Default 403 (access denied) page'), '#default_value' => variable_get('site_403', ''), '#size' => 40, '#description' => t('This page is displayed when the requested document is denied to the current user. Leave blank to display a generic "access denied" page.'), '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=') ); $form['error_page']['site_404'] = array( '#type' => 'textfield', '#title' => t('Default 404 (not found) page'), '#default_value' => variable_get('site_404', ''), '#size' => 40, '#description' => t('This page is displayed when no other content matches the requested document. Leave blank to display a generic "page not found" page.'), '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=') ); $form['#validate'][] = 'system_site_information_settings_validate'; return system_settings_form($form); } /** * Validates the submitted site-information form. */ function system_site_information_settings_validate($form, &$form_state) { // Validate the e-mail address. if ($error = user_validate_mail($form_state['values']['site_mail'])) { form_set_error('site_mail', $error); } // Check for empty front page path. if (empty($form_state['values']['site_frontpage'])) { // Set to default "node". form_set_value($form['front_page']['site_frontpage'], 'node', $form_state); } else { // Get the normal path of the front page. form_set_value($form['front_page']['site_frontpage'], drupal_get_normal_path($form_state['values']['site_frontpage']), $form_state); } // Validate front page path. if (!drupal_valid_path($form_state['values']['site_frontpage'])) { form_set_error('site_frontpage', t("The path '%path' is either invalid or you do not have access to it.", array('%path' => $form_state['values']['site_frontpage']))); } // Get the normal paths of both error pages. if (!empty($form_state['values']['site_403'])) { form_set_value($form['error_page']['site_403'], drupal_get_normal_path($form_state['values']['site_403']), $form_state); } if (!empty($form_state['values']['site_404'])) { form_set_value($form['error_page']['site_404'], drupal_get_normal_path($form_state['values']['site_404']), $form_state); } // Validate 403 error path. if (!empty($form_state['values']['site_403']) && !drupal_valid_path($form_state['values']['site_403'])) { form_set_error('site_403', t("The path '%path' is either invalid or you do not have access to it.", array('%path' => $form_state['values']['site_403']))); } // Validate 404 error path. if (!empty($form_state['values']['site_404']) && !drupal_valid_path($form_state['values']['site_404'])) { form_set_error('site_404', t("The path '%path' is either invalid or you do not have access to it.", array('%path' => $form_state['values']['site_404']))); } } /** * Form builder; Cron form. * * @see system_settings_form() * @ingroup forms */ function system_cron_settings() { global $base_url; $form['description'] = array( '#markup' => '' . t('Cron takes care of running periodic tasks like checking for updates and indexing content for search.') . '
', ); $form['run'] = array( '#type' => 'submit', '#value' => t('Run cron'), '#submit' => array('system_run_cron_submit'), ); $status = '' . t('Last run: %cron-last ago.', array('%cron-last' => format_interval(REQUEST_TIME - variable_get('cron_last')),)) . '
'; $form['status'] = array( '#markup' => $status, ); $form['cron_url'] = array( '#markup' => '' . t('To run cron from outside the site, go to !cron', array('!cron' => url($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => variable_get('cron_key', 'drupal')))))) . '
', ); $form['cron'] = array( '#type' => 'fieldset', ); $form['cron']['cron_safe_threshold'] = array( '#type' => 'select', '#title' => t('Run cron every'), '#description' => t('More information about setting up scheduled tasks can be found by reading the cron tutorial on drupal.org.', array('@url' => url('http://drupal.org/cron'))), '#default_value' => variable_get('cron_safe_threshold', DRUPAL_CRON_DEFAULT_THRESHOLD), '#options' => array(0 => t('Never')) + drupal_map_assoc(array(3600, 10800, 21600, 43200, 86400, 604800), 'format_interval'), ); return system_settings_form($form); } /** * Submit callback; run cron. * * @ingroup forms */ function system_run_cron_submit($form, &$form_state) { // Run cron manually from Cron form. if (drupal_cron_run()) { drupal_set_message(t('Cron run successfully.')); } else { drupal_set_message(t('Cron run failed.'), 'error'); } drupal_goto('admin/config/system/cron'); } /** * Form builder; Configure error reporting settings. * * @ingroup forms * @see system_settings_form() */ function system_logging_settings() { $form['error_level'] = array( '#type' => 'radios', '#title' => t('Error messages to display'), '#default_value' => variable_get('error_level', ERROR_REPORTING_DISPLAY_ALL), '#options' => array( ERROR_REPORTING_HIDE => t('None'), ERROR_REPORTING_DISPLAY_SOME => t('Errors and warnings'), ERROR_REPORTING_DISPLAY_ALL => t('All messages'), ), '#description' => t('It is recommended that sites running on production environments do not display any errors.'), ); return system_settings_form($form); } /** * Form builder; Configure site performance settings. * * @ingroup forms * @see system_settings_form() */ function system_performance_settings() { drupal_add_js(drupal_get_path('module', 'system') . '/system.js'); $form['clear_cache'] = array( '#type' => 'fieldset', '#title' => t('Clear cache'), ); $form['clear_cache']['clear'] = array( '#type' => 'submit', '#value' => t('Clear all caches'), '#submit' => array('system_clear_cache_submit'), ); $form['caching'] = array( '#type' => 'fieldset', '#title' => t('Caching'), ); $cache = variable_get('cache', 0); $form['caching']['cache'] = array( '#type' => 'checkbox', '#title' => t('Cache pages for anonymous users'), '#default_value' => $cache, '#weight' => -2, ); $period = drupal_map_assoc(array(0, 60, 180, 300, 600, 900, 1800, 2700, 3600, 10800, 21600, 32400, 43200, 86400), 'format_interval'); $period[0] = '<' . t('none') . '>'; $form['caching']['cache_lifetime'] = array( '#type' => 'select', '#title' => t('Minimum cache lifetime'), '#default_value' => variable_get('cache_lifetime', 0), '#options' => $period, '#description' => t('Cached pages will not be re-created until at least this much time has elapsed.') ); $form['caching']['page_cache_maximum_age'] = array( '#type' => 'select', '#title' => t('Expiration of cached pages'), '#default_value' => variable_get('page_cache_maximum_age', 0), '#options' => $period, '#description' => t('The maximum time an external cache can use an old version of a page.') ); $directory = 'public://'; $is_writable = is_dir($directory) && is_writable($directory); $disabled = !$is_writable; $disabled_message = ''; if (!$is_writable) { $disabled_message = ' ' . t('Set up the public files directory to make these optimizations available.', array('!file-system' => url('admin/config/media/file-system'))); } $form['bandwidth_optimization'] = array( '#type' => 'fieldset', '#title' => t('Bandwidth optimization'), '#description' => t('External resources can be optimized automatically, which can reduce both the size and number of requests made to your website.') . $disabled_message, ); $js_hide = $cache ? '' : ' class="js-hide"'; $form['bandwidth_optimization']['page_compression'] = array( '#type' => 'checkbox', '#title' => t('Compress cached pages.'), '#default_value' => variable_get('page_compression', TRUE), '#prefix' => 'example.com/user
instead of example.com/?q=user
.'),
);
$form = system_settings_form($form);
if ($conflict) {
// $form_state['redirect'] needs to be set to the non-clean URL,
// otherwise the setting is not saved.
$form_state['redirect'] = url('', array('query' => array('q' => '/admin/config/search/clean-urls')));
}
}
// Show the clean URLs test form.
else {
drupal_add_js(drupal_get_path('module', 'system') . '/system.js');
$form_state['redirect'] = url('admin/config/search/clean-urls');
$form['clean_url_description'] = array(
'#type' => 'markup',
'#markup' => '' . t('Use URLs like example.com/user
instead of example.com/?q=user
.') . '
' . t('Clean URLs cannot be enabled. If you are directed to this page or to a Page not found (404) error after testing for clean URLs, see the online handbook.', array('@handbook' => 'http://drupal.org/node/15365')) . '
', ); $form['actions'] = array( '#type' => 'actions', 'clean_url_test' => array( '#type' => 'submit', '#value' => t('Run the clean URL test'), ), ); $form['clean_url_test_execute'] = array( '#type' => 'hidden', '#value' => 1, ); } return $form; } /** * Menu callback: displays the site status report. Can also be used as a pure check. * * @param $check * If true, only returns a boolean whether there are system status errors. */ function system_status($check = FALSE) { // Load .install files include_once DRUPAL_ROOT . '/includes/install.inc'; drupal_load_updates(); // Check run-time requirements and status information. $requirements = module_invoke_all('requirements', 'runtime'); usort($requirements, '_system_sort_requirements'); if ($check) { return drupal_requirements_severity($requirements) == REQUIREMENT_ERROR; } // MySQL import might have set the uid of the anonymous user to autoincrement // value. Let's try fixing it. See http://drupal.org/node/204411 db_update('users') ->expression('uid', 'uid - uid') ->condition('name', '') ->condition('pass', '') ->condition('status', 0) ->execute(); return theme('status_report', array('requirements' => $requirements)); } /** * Menu callback: run cron manually. */ function system_run_cron() { if (!isset($_GET['token']) || !drupal_valid_token($_GET['token'], 'run-cron')) { return MENU_ACCESS_DENIED; } // Run cron manually if (drupal_cron_run()) { drupal_set_message(t('Cron ran successfully.')); } else { drupal_set_message(t('Cron run failed.'), 'error'); } drupal_goto('admin/reports/status'); } /** * Menu callback: return information about PHP. */ function system_php() { $phpinfo_flags = variable_get('sa_core_2023_004_phpinfo_flags', ~(INFO_VARIABLES | INFO_ENVIRONMENT)); phpinfo($phpinfo_flags); drupal_exit(); } /** * Default page callback for batches. */ function system_batch_page() { require_once DRUPAL_ROOT . '/includes/batch.inc'; $output = _batch_page(); if ($output === FALSE) { drupal_access_denied(); drupal_exit(); } elseif (isset($output)) { // Force a page without blocks or messages to // display a list of collected messages later. drupal_set_page_content($output); $page = element_info('page'); $page['#show_messages'] = FALSE; return $page; } } /** * Returns HTML for an administrative block for display. * * @param $variables * An associative array containing: * - block: An array containing information about the block: * - show: A Boolean whether to output the block. Defaults to FALSE. * - title: The block's title. * - content: (optional) Formatted content for the block. * - description: (optional) Description of the block. Only output if * 'content' is not set. * * @ingroup themeable */ function theme_admin_block($variables) { $block = $variables['block']; $output = ''; // Don't display the block if it has no content to display. if (empty($block['show'])) { return $output; } $output .= '' . $severity['icon'] . ' | ' . $requirement['title'] . ' | ' . $requirement['value'] . ' |
' . $requirement['description'] . ' | ||
' . $severity['icon'] . ' | ' . $requirement['title'] . ' | ' . $requirement['value'] . ' |