[ Index ]
 

Code source de Drupal 5.3

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/modules/system/ -> system.module (source)

   1  <?php
   2  // $Id: system.module,v 1.440.2.19 2007/10/17 21:29:00 drumm Exp $
   3  
   4  /**
   5   * @file
   6   * Configuration system that lets administrators modify the workings of the site.
   7   */
   8  
   9  define('VERSION', '5.3');
  10  
  11  /**
  12   * Implementation of hook_help().
  13   */
  14  function system_help($section) {
  15    global $base_url;
  16  
  17    switch ($section) {
  18      case 'admin/help#system':
  19        $output = '<p>'. t('The system module provides system-wide defaults such as running jobs at a particular time, and storing web pages to improve efficiency. The ability to run scheduled jobs makes administering the web site more usable, as administrators do not have to manually start jobs. The storing of web pages, or caching, allows the site to efficiently re-use web pages and improve web site performance. The system module provides control over preferences, behaviours including visual and operational settings.') .'</p>';
  20        $output .= '<p>'. t('Some modules require regularly scheduled actions, such as cleaning up logfiles. Cron, which stands for chronograph, is a periodic command scheduler executing commands at intervals specified in seconds. It can be used to control the execution of daily, weekly and monthly jobs (or anything with a period measured in seconds). The aggregator module periodically updates feeds using cron. Ping periodically notifies services of new content on your site. Search periodically indexes the content on your site. Automating tasks is one of the best ways to keep a system running smoothly, and if most of your administration does not require your direct involvement, cron is an ideal solution. Cron can, if necessary, also be run manually.') .'</p>';
  21        $output .= '<p>'. t("There is a caching mechanism which stores dynamically generated web pages in a database. By caching a web page, the system module does not have to create the page each time someone wants to view it, instead it takes only one SQL query to display it, reducing response time and the server's load. Only pages requested by <em>anonymous</em> users are cached. In order to reduce server load and save bandwidth, the system module stores and sends cached pages compressed.") .'</p>';
  22        $output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="@system">System page</a>.', array('@system' => 'http://drupal.org/handbook/modules/system/')) .'</p>';
  23        return $output;
  24      case 'admin':
  25        return '<p>'. t('Welcome to the administration section. Here you may control how your site functions.') .'</p>';
  26      case 'admin/by-module':
  27        return '<p>'. t('This page shows you all available administration tasks for each module.') .'</p>';
  28      case 'admin/build/themes':
  29        return '<p>'. t('Select which themes are available to your users and specify the default theme. To configure site-wide display settings, click the "configure" task above. Alternately, to override these settings in a specific theme, click the "configure" link for the corresponding theme. Note that different themes may have different regions available for rendering content like blocks. If you want consistency in what your users see, you may wish to enable only one theme.') .'</p>';
  30      case 'admin/build/themes/settings':
  31        return '<p>'. t('These options control the default display settings for your entire site, across all themes. Unless they have been overridden by a specific theme, these settings will be used.') .'</p>';
  32      case 'admin/build/themes/settings/'. arg(4):
  33        $reference = explode('.', arg(4), 2);
  34        $theme = array_pop($reference);
  35        return '<p>'. t('These options control the display settings for the <code>%template</code> theme. When your site is displayed using this theme, these settings will be used. By clicking "Reset to defaults," you can choose to use the <a href="@global">global settings</a> for this theme.', array('%template' => $theme, '@global' => url('admin/build/themes/settings'))) .'</p>';
  36      case 'admin/build/modules':
  37        return t('<p>Modules are plugins for Drupal that extend its core functionality. Here you can select which modules are enabled. Click on the name of the module in the navigation menu for their individual configuration pages. Once a module is enabled, new <a href="@permissions">permissions</a> might be made available. Modules can automatically be temporarily disabled to reduce server load when your site becomes extremely busy by enabling the throttle.module and checking throttle. The auto-throttle functionality must be enabled on the <a href="@throttle">throttle configuration page</a> after having enabled the throttle module.</p>
  38  <p>It is important that <a href="@update-php">update.php</a> is run every time a module is updated to a newer version.</p><p>You can find all administration tasks belonging to a particular module on the <a href="@by-module">administration by module page</a>.</p>', array('@permissions' => url('admin/user/access'), '@throttle' => url('admin/settings/throttle'), '@update-php' => $base_url .'/update.php', '@by-module' => url('admin/by-module')));
  39      case 'admin/build/modules/uninstall':
  40        return '<p>'. t('The uninstall process removes all data related to a module. To uninstall a module, you must first disable it. Not all modules support this feature.') .'</p>';
  41      case 'admin/logs/status':
  42        return '<p>'. t("Here you can find a short overview of your Drupal site's parameters as well as any problems detected with your installation. It is useful to copy/paste this information when you need support.") .'</p>';
  43    }
  44  }
  45  
  46  /**
  47   * Implementation of hook_perm().
  48   */
  49  function system_perm() {
  50    return array('administer site configuration', 'access administration pages', 'select different theme');
  51  }
  52  
  53  /**
  54   * Implementation of hook_elements().
  55   */
  56  function system_elements() {
  57    // Top level form
  58    $type['form'] = array('#method' => 'post', '#action' => request_uri());
  59  
  60    // Inputs
  61    $type['checkbox'] = array('#input' => TRUE, '#return_value' => 1);
  62    $type['submit'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => TRUE);
  63    $type['button'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => FALSE);
  64    $type['textfield'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128, '#autocomplete_path' => FALSE);
  65    $type['password'] = array('#input' => TRUE, '#size' => 60);
  66    $type['password_confirm'] = array('#input' => TRUE, '#process' => array('expand_password_confirm' => array()));
  67    $type['textarea'] = array('#input' => TRUE, '#cols' => 60, '#rows' => 5);
  68    $type['radios'] = array('#input' => TRUE, '#process' => array('expand_radios' => array()));
  69    $type['radio'] = array('#input' => TRUE);
  70    $type['checkboxes'] = array('#input' => TRUE, '#process' => array('expand_checkboxes' => array()), '#tree' => TRUE);
  71    $type['select'] = array('#input' => TRUE);
  72    $type['weight'] = array('#input' => TRUE, '#delta' => 10, '#default_value' => 0, '#process' => array('process_weight' => array()));
  73    $type['date'] = array('#input' => TRUE, '#process' => array('expand_date' => array()), '#validate' => array('date_validate' => array()));
  74    $type['file'] = array('#input' => TRUE, '#size' => 60);
  75  
  76    // Form structure
  77    $type['item'] = array();
  78    $type['hidden'] = array('#input' => TRUE);
  79    $type['value'] = array('#input' => TRUE);
  80    $type['markup'] = array('#prefix' => '', '#suffix' => '');
  81    $type['fieldset'] = array('#collapsible' => FALSE, '#collapsed' => FALSE);
  82    $type['token'] = array('#input' => TRUE);
  83    return $type;
  84  }
  85  
  86  /**
  87   * Implementation of hook_menu().
  88   */
  89  function system_menu($may_cache) {
  90    $items = array();
  91  
  92    if ($may_cache) {
  93      $items[] = array('path' => 'system/files', 'title' => t('File download'),
  94        'callback' => 'file_download',
  95        'access' => TRUE,
  96        'type' => MENU_CALLBACK);
  97  
  98      $access = user_access('administer site configuration');
  99  
 100      $items[] = array('path' => 'admin', 'title' => t('Administer'),
 101        'access' => user_access('access administration pages'),
 102        'callback' => 'system_main_admin_page',
 103        'weight' => 9);
 104      $items[] = array('path' => 'admin/compact', 'title' => t('Compact mode'),
 105        'access' => user_access('access administration pages'),
 106        'callback' => 'system_admin_compact_page',
 107        'type' => MENU_CALLBACK);
 108      $items[] = array('path' => 'admin/by-task', 'title' => t('By task'),
 109        'callback' => 'system_main_admin_page',
 110        'type' => MENU_DEFAULT_LOCAL_TASK);
 111      $items[] = array('path' => 'admin/by-module', 'title' => t('By module'),
 112        'callback' => 'system_admin_by_module',
 113        'type' => MENU_LOCAL_TASK,
 114        'weight' => 2);
 115  
 116      // menu items that are basically just menu blocks
 117      $items[] = array(
 118        'path' => 'admin/settings',
 119        'title' => t('Site configuration'),
 120        'description' => t('Adjust basic site configuration options.'),
 121        'position' => 'right',
 122        'weight' => -5,
 123        'callback' => 'system_settings_overview',
 124        'access' => $access);
 125  
 126      $items[] = array('path' => 'admin/build',
 127        'title' => t('Site building'),
 128        'description' => t('Control how your site looks and feels.'),
 129        'position' => 'right',
 130        'weight' => -10,
 131        'callback' => 'system_admin_menu_block_page',
 132        'access' => $access);
 133  
 134      $items[] = array(
 135        'path' => 'admin/settings/admin',
 136        'title' => t('Administration theme'),
 137        'description' => t('Settings for how your administrative pages should look.'),
 138        'position' => 'left',
 139        'callback' => 'drupal_get_form',
 140        'callback arguments' => array('system_admin_theme_settings'),
 141        'block callback' => 'system_admin_theme_settings',
 142        'access' => $access);
 143  
 144      // Themes:
 145      $items[] = array(
 146        'path' => 'admin/build/themes',
 147        'title' => t('Themes'),
 148        'description' => t('Change which theme your site uses or allows users to set.'),
 149        'callback' => 'drupal_get_form',
 150        'callback arguments' => array('system_themes'),
 151        'access' => $access);
 152  
 153      $items[] = array(
 154        'path' => 'admin/build/themes/select',
 155        'title' => t('List'),
 156        'description' => t('Select the default theme.'),
 157        'callback' => 'drupal_get_form',
 158        'callback arguments' => array('system_themes'),
 159        'access' => $access,
 160        'type' => MENU_DEFAULT_LOCAL_TASK,
 161        'weight' => -1);
 162  
 163      $items[] = array('path' => 'admin/build/themes/settings',
 164        'title' => t('Configure'),
 165        'callback' => 'drupal_get_form',
 166        'callback arguments' => array('system_theme_settings'),
 167        'access' => $access,
 168        'type' => MENU_LOCAL_TASK);
 169  
 170      // Theme configuration subtabs
 171      $items[] = array('path' => 'admin/build/themes/settings/global', 'title' => t('Global settings'),
 172        'callback' => 'drupal_get_form',
 173        'callback arguments' => array('system_theme_settings'),
 174        'access' => $access,
 175        'type' => MENU_DEFAULT_LOCAL_TASK,
 176        'weight' => -1);
 177  
 178      foreach (list_themes() as $theme) {
 179        if ($theme->status) {
 180          $items[] = array('path' => 'admin/build/themes/settings/'. $theme->name, 'title' => $theme->name,
 181          'callback' => 'drupal_get_form', 'callback arguments' => array('system_theme_settings', $theme->name),
 182          'access' => $access, 'type' => MENU_LOCAL_TASK);
 183        }
 184      }
 185  
 186      // Modules:
 187      $items[] = array('path' => 'admin/build/modules',
 188        'title' => t('Modules'),
 189        'description' => t('Enable or disable add-on modules for your site.'),
 190        'callback' => 'drupal_get_form',
 191        'callback arguments' => array('system_modules'),
 192        'access' => $access);
 193      $items[] = array('path' => 'admin/build/modules/list',
 194        'title' => t('List'),
 195        'type' => MENU_DEFAULT_LOCAL_TASK,
 196        'access' => $access);
 197      $items[] = array('path' => 'admin/build/modules/list/confirm',
 198        'title' => t('List'),
 199        'callback' => 'drupal_get_form',
 200        'callback arguments' => array('system_modules'),
 201        'type' => MENU_CALLBACK,
 202        'access' => $access);
 203      $items[] = array('path' => 'admin/build/modules/uninstall',
 204        'title' => t('Uninstall'),
 205        'callback' => 'drupal_get_form',
 206        'callback arguments' => array('system_modules_uninstall'),
 207        'type' => MENU_LOCAL_TASK,
 208        'access' => $access);
 209      $items[] = array('path' => 'admin/build/modules/uninstall/confirm',
 210        'title' => t('Uninstall'),
 211        'callback' => 'drupal_get_form',
 212        'callback arguments' => array('system_modules_uninstall'),
 213        'type' => MENU_CALLBACK,
 214        'access' => $access);
 215  
 216      // Settings:
 217      $items[] = array(
 218        'path' => 'admin/settings/site-information',
 219        'title' => t('Site information'),
 220        'description' => t('Change basic site information, such as the site name, slogan, e-mail address, mission, front page and more.'),
 221        'callback' => 'drupal_get_form',
 222        'callback arguments' => array('system_site_information_settings'));
 223      $items[] = array(
 224        'path' => 'admin/settings/error-reporting',
 225        'title' => t('Error reporting'),
 226        'description' => t('Control how Drupal deals with errors including 403/404 errors as well as PHP error reporting.'),
 227        'callback' => 'drupal_get_form',
 228        'callback arguments' => array('system_error_reporting_settings'));
 229      $items[] = array(
 230        'path' => 'admin/settings/performance',
 231        'title' => t('Performance'),
 232        'description' => t('Enable or disable page caching for anonymous users, and enable or disable CSS preprocessor.'),
 233        'callback' => 'drupal_get_form',
 234        'callback arguments' => array('system_performance_settings'));
 235      $items[] = array(
 236        'path' => 'admin/settings/file-system',
 237        'title' => t('File system'),
 238        'description' => t('Tell Drupal where to store uploaded files and how they are accessed.'),
 239        'callback' => 'drupal_get_form',
 240        'callback arguments' => array('system_file_system_settings'));
 241      $items[] = array(
 242        'path' => 'admin/settings/image-toolkit',
 243        'title' => t('Image toolkit'),
 244        'description' => t('Choose which image toolkit to use if you have installed optional toolkits.'),
 245        'callback' => 'drupal_get_form',
 246        'callback arguments' => array('system_image_toolkit_settings'));
 247      $items[] = array(
 248        'path' => 'admin/content/rss-publishing',
 249        'title' => t('RSS publishing'),
 250        'description' => t('Configure the number of items per feed and whether feeds should be titles/teasers/full-text.'),
 251        'callback' => 'drupal_get_form',
 252        'callback arguments' => array('system_rss_feeds_settings'));
 253      $items[] = array(
 254        'path' => 'admin/settings/date-time',
 255        'title' => t('Date and time'),
 256        'description' => t("Settings for how Drupal displays date and time, as well as the system's default timezone."),
 257        'callback' => 'drupal_get_form',
 258        'callback arguments' => array('system_date_time_settings'));
 259      $items[] = array(
 260        'path' => 'admin/settings/site-maintenance',
 261        'title' => t('Site maintenance'),
 262        'description' => t('Take the site off-line for maintenance or bring it back online.'),
 263        'callback' => 'drupal_get_form',
 264        'callback arguments' => array('system_site_maintenance_settings'));
 265      $items[] = array(
 266        'path' => 'admin/settings/clean-urls',
 267        'title' => t('Clean URLs'),
 268        'description' => t('Enable or disable clean URLs for your site.'),
 269        'callback' => 'drupal_get_form',
 270        'callback arguments' => array('system_clean_url_settings'));
 271  
 272  
 273      // Logs:
 274      $items[] = array(
 275        'path' => 'admin/logs',
 276        'title' => t('Logs'),
 277        'description' => t('View system logs and other status information.'),
 278        'callback' => 'system_admin_menu_block_page',
 279        'weight' => 5,
 280        'position' => 'left');
 281      $items[] = array(
 282        'path' => 'admin/logs/status',
 283        'title' => t('Status report'),
 284        'description' => t("Get a status report about your site's operation and any detected problems."),
 285        'callback' => 'system_status',
 286        'weight' => 10,
 287        'access' => $access);
 288      $items[] = array(
 289        'path' => 'admin/logs/status/run-cron',
 290        'title' => t('Run cron'),
 291        'callback' => 'system_run_cron',
 292        'type' => MENU_CALLBACK);
 293      $items[] = array(
 294        'path' => 'admin/logs/status/php',
 295        'title' => t('PHP'),
 296        'callback' => 'system_php',
 297        'type' => MENU_CALLBACK);
 298      $items[] = array(
 299        'path' => 'admin/logs/status/sql',
 300        'title' => t('SQL'),
 301        'callback' => 'system_sql',
 302        'type' => MENU_CALLBACK);
 303    }
 304    else {
 305      /**
 306       * Use the administrative theme if the user is looking at a page in the admin/* path.
 307       */
 308      if (arg(0) == 'admin') {
 309        global $custom_theme;
 310        $custom_theme = variable_get('admin_theme', '0');
 311        drupal_add_css(drupal_get_path('module', 'system') .'/admin.css', 'module');
 312      }
 313  
 314      // Add the CSS for this module. We put this in !$may_cache so it is only
 315      // added once per request.
 316      drupal_add_css(drupal_get_path('module', 'system') .'/defaults.css', 'module');
 317      drupal_add_css(drupal_get_path('module', 'system') .'/system.css', 'module');
 318    }
 319  
 320    return $items;
 321  }
 322  
 323  /**
 324   * Implementation of hook_user().
 325   *
 326   * Allows users to individually set their theme and time zone.
 327   */
 328  function system_user($type, $edit, &$user, $category = NULL) {
 329    if ($type == 'form' && $category == 'account') {
 330      $form['theme_select'] = system_theme_select_form(t('Selecting a different theme will change the look and feel of the site.'), $edit['theme'], 2);
 331  
 332      if (variable_get('configurable_timezones', 1)) {
 333        $zones = _system_zonelist();
 334        $form['timezone'] = array(
 335          '#type'=>'fieldset',
 336          '#title' => t('Locale settings'),
 337          '#weight' => 6,
 338          '#collapsible' => TRUE,
 339        );
 340        $form['timezone']['timezone'] = array(
 341          '#type' => 'select',
 342          '#title' => t('Time zone'),
 343          '#default_value' => strlen($edit['timezone']) ? $edit['timezone'] : variable_get('date_default_timezone', 0),
 344          '#options' => $zones,
 345          '#description' => t('Select your current local time. Dates and times throughout this site will be displayed using this time zone.'),
 346        );
 347      }
 348  
 349      return $form;
 350    }
 351  }
 352  
 353  /**
 354   * Provide the administration overview page.
 355   */
 356  function system_main_admin_page($arg = NULL) {
 357    // If we received an argument, they probably meant some other page.
 358    // Let's 404 them since the menu system cannot be told we do not
 359    // accept arguments.
 360    if (isset($arg) && substr($arg, 0, 3) != 'by-') {
 361      return drupal_not_found();
 362    }
 363  
 364    // Check for status report errors.
 365    if (system_status(TRUE)) {
 366      drupal_set_message(t('One or more problems were detected with your Drupal installation. Check the <a href="@status">status report</a> for more information.', array('@status' => url('admin/logs/status'))), 'error');
 367    }
 368  
 369  
 370    $menu = menu_get_item(NULL, 'admin');
 371    usort($menu['children'], '_menu_sort');
 372    foreach ($menu['children'] as $mid) {
 373      $block = menu_get_item($mid);
 374      if ($block['block callback'] && function_exists($block['block callback'])) {
 375        $arguments = isset($block['block arguments']) ? $block['block arguments'] : array();
 376        $block['content'] .= call_user_func_array($block['block callback'], $arguments);
 377      }
 378      $block['content'] .= theme('admin_block_content', system_admin_menu_block($block));
 379      $blocks[] = $block;
 380    }
 381  
 382    return theme('admin_page', $blocks);
 383  }
 384  
 385  /**
 386   * Provide a single block on the administration overview page.
 387   */
 388  function system_admin_menu_block($block) {
 389    $content = array();
 390    if (is_array($block['children'])) {
 391      usort($block['children'], '_menu_sort');
 392      foreach ($block['children'] as $mid) {
 393        $item = menu_get_item($mid);
 394        if (($item['type'] & MENU_VISIBLE_IN_TREE) && _menu_item_is_accessible($mid)) {
 395          $content[] = $item;
 396        }
 397      }
 398    }
 399    return $content;
 400  }
 401  
 402  /**
 403   * Provide a single block from the administration menu as a page.
 404   * This function is often a destination for these blocks.
 405   * For example, 'admin/content/types' needs to have a destination to be valid
 406   * in the Drupal menu system, but too much information there might be
 407   * hidden, so we supply the contents of the block.
 408   */
 409  function system_admin_menu_block_page() {
 410    $menu = menu_get_item(NULL, $_GET['q']);
 411    $content = system_admin_menu_block($menu);
 412  
 413    $output = theme('admin_block_content', $content);
 414    return $output;
 415  }
 416  
 417  function system_admin_compact_page($mode = 'off') {
 418    global $user;
 419    user_save($user, array('admin_compact_mode' => ($mode == 'on')));
 420    drupal_goto('admin');
 421  }
 422  
 423  /**
 424   * This function allows selection of the theme to show in administration sections.
 425   */
 426  function system_admin_theme_settings() {
 427    $themes = system_theme_data();
 428    ksort($themes);
 429    $options[0] = t('System default');
 430    foreach ($themes as $theme) {
 431      $options[$theme->name] = $theme->name;
 432    }
 433  
 434    $form['admin_theme'] = array(
 435      '#type' => 'select',
 436      '#options' => $options,
 437      '#title' => t('Administration theme'),
 438      '#description' => t('Choose which theme the administration pages should display in. If you choose "System default" the administration pages will use the same theme as the rest of the site.'),
 439      '#default_value' => variable_get('admin_theme', '0'),
 440    );
 441  
 442    // In order to give it our own submit, we have to give it the default submit
 443    // too because the presence of a #submit will prevent the default #submit
 444    // from being used. Also we want ours first.
 445    $form['#submit']['system_admin_theme_submit'] = array();
 446    $form['#submit']['system_settings_form_submit'] = array();
 447    return system_settings_form($form);
 448  }
 449  
 450  
 451  function system_admin_theme_submit($form_id, $form_values) {
 452    // If we're changing themes, make sure the theme has its blocks initialized.
 453    if ($form_values['admin_theme'] != variable_get('admin_theme', '0')) {
 454      $result = db_query("SELECT status FROM {blocks} WHERE theme = '%s'", $form_values['admin_theme']);
 455      if (!db_num_rows($result)) {
 456        system_initialize_theme_blocks($form_values['admin_theme']);
 457      }
 458    }
 459  }
 460  
 461  /*
 462   * Returns a fieldset containing the theme select form.
 463   *
 464   * @param $description
 465   *    description of the fieldset
 466   * @param $default_value
 467   *    default value of theme radios
 468   * @param $weight
 469   *    weight of the fieldset
 470   * @return
 471   *    a form array
 472   */
 473  function system_theme_select_form($description = '', $default_value = '', $weight = 0) {
 474    if (user_access('select different theme')) {
 475      foreach (list_themes() as $theme) {
 476        if ($theme->status) {
 477          $enabled[] = $theme;
 478        }
 479      }
 480  
 481      if (count($enabled) > 1) {
 482        ksort($enabled);
 483  
 484        $form['themes'] = array(
 485          '#type' => 'fieldset',
 486          '#title' => t('Theme configuration'),
 487          '#description' => $description,
 488          '#collapsible' => TRUE,
 489          '#theme' => 'system_theme_select_form'
 490        );
 491  
 492        foreach ($enabled as $info) {
 493          // For the default theme, revert to an empty string so the user's theme updates when the site theme is changed.
 494          $info->key = $info->name == variable_get('theme_default', 'garland') ? '' : $info->name;
 495  
 496          $info->screenshot = dirname($info->filename) .'/screenshot.png';
 497          $screenshot = file_exists($info->screenshot) ? theme('image', $info->screenshot, t('Screenshot for %theme theme', array('%theme' => $info->name)), '', array('class' => 'screenshot'), FALSE) : t('no screenshot');
 498  
 499          $form['themes'][$info->key]['screenshot'] = array('#value' => $screenshot);
 500          $form['themes'][$info->key]['description'] = array('#type' => 'item', '#title' => $info->name,  '#value' => dirname($info->filename) . ($info->name == variable_get('theme_default', 'garland') ? '<br /> <em>'. t('(site default theme)') .'</em>' : ''));
 501          $options[$info->key] = '';
 502        }
 503  
 504        $form['themes']['theme'] = array('#type' => 'radios', '#options' => $options, '#default_value' => $default_value ? $default_value : '');
 505        $form['#weight'] = $weight;
 506        return $form;
 507      }
 508    }
 509  }
 510  
 511  function theme_system_theme_select_form($form) {
 512    foreach (element_children($form) as $key) {
 513      $row = array();
 514      if (is_array($form[$key]['description'])) {
 515        $row[] = drupal_render($form[$key]['screenshot']);
 516        $row[] = drupal_render($form[$key]['description']);
 517        $row[] = drupal_render($form['theme'][$key]);
 518      }
 519      $rows[] = $row;
 520    }
 521  
 522    $header = array(t('Screenshot'), t('Name'), t('Selected'));
 523    $output = theme('table', $header, $rows);
 524    return $output;
 525  }
 526  
 527  function _system_zonelist() {
 528    $timestamp = time();
 529    $zonelist = array(-11, -10, -9.5, -9, -8, -7, -6, -5, -4, -3.5, -3, -2, -1, 0, 1, 2, 3, 3.5, 4, 5, 5.5, 5.75, 6, 6.5, 7, 8, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 14);
 530    $zones = array();
 531    foreach ($zonelist as $offset) {
 532      $zone = $offset * 3600;
 533      $zones[$zone] = format_date($timestamp, 'custom', variable_get('date_format_long', 'l, F j, Y - H:i') .' O', $zone);
 534    }
 535    return $zones;
 536  }
 537  
 538  function system_site_information_settings() {
 539    $form['site_name'] = array(
 540      '#type' => 'textfield',
 541      '#title' => t('Name'),
 542      '#default_value' => variable_get('site_name', 'Drupal'),
 543      '#description' => t('The name of this web site.'),
 544      '#required' => TRUE
 545    );
 546    $form['site_mail'] = array(
 547      '#type' => 'textfield',
 548      '#title' => t('E-mail address'),
 549      '#default_value' => variable_get('site_mail', ini_get('sendmail_from')),
 550      '#description' => t('A valid e-mail address to be used as the "From" address by the auto-mailer during registration, new password requests, notifications, etc.  To lessen the likelihood of e-mail being marked as spam, this e-mail address should use the same domain as the website.'),
 551      '#required' => TRUE,
 552    );
 553    $form['site_slogan'] = array(
 554      '#type' => 'textfield',
 555      '#title' => t('Slogan'),
 556      '#default_value' => variable_get('site_slogan', ''),
 557      '#description' => t('The slogan of this website. Some themes display a slogan when available.')
 558    );
 559  
 560    $form['site_mission'] = array(
 561      '#type' => 'textarea',
 562      '#title' => t('Mission'),
 563      '#default_value' => variable_get('site_mission', ''),
 564      '#description' => t('Your site\'s mission statement or focus.')
 565    );
 566    $form['site_footer'] = array(
 567      '#type' => 'textarea',
 568      '#title' => t('Footer message'),
 569      '#default_value' => variable_get('site_footer', ''),
 570      '#description' => t('This text will be displayed at the bottom of each page. Useful for adding a copyright notice to your pages.')
 571    );
 572    $form['anonymous'] = array(
 573      '#type' => 'textfield',
 574      '#title' => t('Anonymous user'),
 575      '#default_value' => variable_get('anonymous', t('Anonymous')),
 576      '#description' => t('The name used to indicate anonymous users.')
 577    );
 578    $form['site_frontpage'] = array(
 579      '#type' => 'textfield',
 580      '#title' => t('Default front page'),
 581      '#default_value' => variable_get('site_frontpage', 'node'),
 582      '#size' => 40,
 583      '#description' => t('The home page displays content from this relative URL. If unsure, specify "node".'),
 584      '#field_prefix' => url(NULL, NULL, NULL, TRUE) . (variable_get('clean_url', 0) ? '' : '?q=')
 585    );
 586  
 587    return system_settings_form($form);
 588  }
 589  
 590  function system_clean_url_settings() {
 591    // We check for clean URL support using an image on the client side.
 592    $form['clean_url'] = array(
 593      '#type' => 'radios',
 594      '#title' => t('Clean URLs'),
 595      '#default_value' => variable_get('clean_url', 0),
 596      '#options' => array(t('Disabled'), t('Enabled')),
 597      '#description' => t('This option makes Drupal emit "clean" URLs (i.e. without <code>?q=</code> in the URL.)'),
 598    );
 599  
 600    if (!variable_get('clean_url', 0)) {
 601      if (strpos(request_uri(), '?q=') !== FALSE) {
 602        $form['clean_url']['#description'] .= t(' Before enabling clean URLs, you must perform a test to determine if your server is properly configured. If you are able to see this page again after clicking the "Run the clean URL test" link, the test has succeeded and the radio buttons above will be available. If instead you are directed to a "Page not found" error, you will need to change the configuration of your server. The <a href="@handbook">handbook page on Clean URLs</a> has additional troubleshooting information. !run-test', array('@handbook' => 'http://drupal.org/node/15365', '!run-test' => '<a href ="'. base_path() .'admin/settings/clean-urls">'. t('Run the clean URL test') .'</a>'));
 603        $form['clean_url']['#disabled'] = TRUE;
 604      }
 605      else {
 606        $form['clean_url']['#description'] .= t(' You have successfully demonstrated that clean URLs work on your server. You may enable/disable them as you wish.');
 607        $form['#collapsed'] = FALSE;
 608      }
 609    }
 610  
 611    return system_settings_form($form);
 612  }
 613  
 614  function system_error_reporting_settings() {
 615  
 616    $form['site_403'] = array(
 617      '#type' => 'textfield',
 618      '#title' => t('Default 403 (access denied) page'),
 619      '#default_value' => variable_get('site_403', ''),
 620      '#size' => 40,
 621      '#description' => t('This page is displayed when the requested document is denied to the current user. If unsure, specify nothing.'),
 622      '#field_prefix' => url(NULL, NULL, NULL, TRUE) . (variable_get('clean_url', 0) ? '' : '?q=')
 623    );
 624  
 625    $form['site_404'] = array(
 626      '#type' => 'textfield',
 627      '#title' => t('Default 404 (not found) page'),
 628      '#default_value' =>  variable_get('site_404', ''),
 629      '#size' => 40,
 630      '#description' => t('This page is displayed when no other content matches the requested document. If unsure, specify nothing.'),
 631      '#field_prefix' => url(NULL, NULL, NULL, TRUE) . (variable_get('clean_url', 0) ? '' : '?q=')
 632    );
 633  
 634    $form['error_level'] = array(
 635      '#type' => 'select', '#title' => t('Error reporting'), '#default_value' => variable_get('error_level', 1),
 636      '#options' => array(t('Write errors to the log'), t('Write errors to the log and to the screen')),
 637      '#description' =>  t('Where Drupal, PHP and SQL errors are logged. On a production server it is recommended that errors are only written to the error log. On a test server it can be helpful to write logs to the screen.')
 638    );
 639  
 640    $period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200), 'format_interval');
 641    $period['1000000000'] = t('Never');
 642    $form['watchdog_clear'] = array(
 643      '#type' => 'select',
 644      '#title' => t('Discard log entries older than'),
 645      '#default_value' => variable_get('watchdog_clear', 604800),
 646      '#options' => $period,
 647      '#description' => t('The time log entries should be kept. Older entries will be automatically discarded. Requires crontab.')
 648    );
 649  
 650    return system_settings_form($form);
 651  }
 652  
 653  function system_performance_settings() {
 654  
 655    $description = '<p>'. t("The normal cache mode is suitable for most sites and does not cause any side effects. The aggressive cache mode causes Drupal to skip the loading (init) and unloading (exit) of enabled modules when serving a cached page. This results in an additional performance boost but can cause unwanted side effects.") .'</p>';
 656  
 657    $problem_modules = array_unique(array_merge(module_implements('init'), module_implements('exit')));
 658    sort($problem_modules);
 659  
 660    if (count($problem_modules) > 0) {
 661      $description .= '<p>'. t('<strong class="error">The following enabled modules are incompatible with aggressive mode caching and might not function properly: %modules</strong>', array('%modules' => implode(', ', $problem_modules))) .'.</p>';
 662    }
 663    else {
 664      $description .= '<p>'. t('<strong class="ok">Currently, all enabled modules are compatible with the aggressive caching policy.</strong> Please note, if you use aggressive caching and enable new modules, you will need to check this page again to ensure compatibility.') .'</p>';
 665    }
 666    $form['page_cache'] = array(
 667      '#type' => 'fieldset',
 668      '#title' => t('Page cache'),
 669      '#description' => t('Enabling the cache will offer a significant performance boost. Drupal can store and send compressed cached pages requested by <em>anonymous</em> users. By caching a web page, Drupal does not have to construct the page each time someone wants to view it.'),
 670    );
 671  
 672    $form['page_cache']['cache'] = array(
 673      '#type' => 'radios',
 674      '#title' => t('Caching mode'),
 675      '#default_value' => variable_get('cache', CACHE_DISABLED),
 676      '#options' => array(CACHE_DISABLED => t('Disabled'), CACHE_NORMAL => t('Normal (recommended, no side effects)'), CACHE_AGGRESSIVE => t('Aggressive (experts only, possible side effects)')),
 677      '#description' => $description
 678    );
 679  
 680    $period = drupal_map_assoc(array(0, 60, 180, 300, 600, 900, 1800, 2700, 3600, 10800, 21600, 32400, 43200, 86400), 'format_interval');
 681    $period[0] = t('none');
 682    $form['page_cache']['cache_lifetime'] = array(
 683      '#type' => 'select',
 684      '#title' => t('Minimum cache lifetime'),
 685      '#default_value' => variable_get('cache_lifetime', 0),
 686      '#options' => $period,
 687      '#description' => t('On high-traffic sites it can become necessary to enforce a minimum cache lifetime. The minimum cache lifetime is the minimum amount of time that will go by before the cache is emptied and recreated. A larger minimum cache lifetime offers better performance, but users will not see new content for a longer period of time.')
 688    );
 689  
 690    $form['bandwidth_optimizations'] = array(
 691      '#type' => 'fieldset',
 692      '#title' => t('Bandwidth optimizations'),
 693      '#description' => t('These options can help reduce both the size and number of requests made to your website. This can reduce the server load, the bandwidth used, and the average page loading time for your visitors.')
 694    );
 695  
 696    $directory = file_directory_path();
 697    $is_writable = is_dir($directory) && is_writable($directory) && (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC);
 698    $form['bandwidth_optimizations']['preprocess_css'] = array(
 699      '#type' => 'radios',
 700      '#title' => t('Aggregate and compress CSS files'),
 701      '#default_value' => intval(variable_get('preprocess_css', FALSE) && $is_writable),
 702      '#disabled' => !$is_writable,
 703      '#options' => array(t('Disabled'), t('Enabled')),
 704      '#description' => t("Some Drupal modules include their own CSS files. When these modules are enabled, each module's CSS file adds an additional HTTP request to the page, which can increase the load time of each page. These HTTP requests can also slightly increase server load. It is recommended to only turn this option on when your site is in production, as it can interfere with theme development. This option is disabled if you have not set up your files directory, or if your download method is set to private."),
 705    );
 706  
 707    $form['#submit']['system_settings_form_submit'] = array();
 708    $form['#submit']['drupal_clear_css_cache'] = array();
 709  
 710    return system_settings_form($form);
 711  }
 712  
 713  function system_file_system_settings() {
 714  
 715    $form['file_directory_path'] = array(
 716      '#type' => 'textfield',
 717      '#title' => t('File system path'),
 718      '#default_value' => file_directory_path(),
 719      '#maxlength' => 255,
 720      '#description' => t('A file system path where the files will be stored. This directory has to exist and be writable by Drupal. If the download method is set to public this directory has to be relative to the Drupal installation directory, and be accessible over the web. When download method is set to private this directory should not be accessible over the web. Changing this location after the site has been in use will cause problems so only change this setting on an existing site if you know what you are doing.'),
 721      '#after_build' => array('system_check_directory'),
 722    );
 723  
 724    $form['file_directory_temp'] = array(
 725      '#type' => 'textfield',
 726      '#title' => t('Temporary directory'),
 727      '#default_value' => file_directory_temp(),
 728      '#maxlength' => 255,
 729      '#description' => t('Location where uploaded files will be kept during previews. Relative paths will be resolved relative to the Drupal installation directory.'),
 730      '#after_build' => array('system_check_directory'),
 731    );
 732  
 733    $form['file_downloads'] = array(
 734      '#type' => 'radios',
 735      '#title' => t('Download method'),
 736      '#default_value' => variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC),
 737      '#options' => array(FILE_DOWNLOADS_PUBLIC => t('Public - files are available using HTTP directly.'), FILE_DOWNLOADS_PRIVATE => t('Private - files are transferred by Drupal.')),
 738      '#description' => t('If you want any sort of access control on the downloading of files, this needs to be set to <em>private</em>. You can change this at any time, however all download URLs will change and there may be unexpected problems so it is not recommended.')
 739    );
 740  
 741    return system_settings_form($form);
 742  }
 743  
 744  function system_image_toolkit_settings() {
 745    $toolkits_available = image_get_available_toolkits();
 746    if (count($toolkits_available) > 1) {
 747      $form['image_toolkit'] = array(
 748        '#type' => 'radios',
 749        '#title' => t('Select an image processing toolkit'),
 750        '#default_value' => variable_get('image_toolkit', image_get_toolkit()),
 751        '#options' => $toolkits_available
 752      );
 753    }
 754    else {
 755      $form['image_toolkit'] = array('#value' => '<p>'. t("No image toolkits found. Drupal will use PHP's built-in GD library for image handling.") .'</p>');
 756    }
 757    $form['image_toolkit_settings'] = image_toolkit_invoke('settings');
 758    return system_settings_form($form);
 759  }
 760  
 761  function system_rss_feeds_settings() {
 762  
 763    $form['feed_default_items'] = array(
 764      '#type' => 'select',
 765      '#title' => t('Number of items per feed'),
 766      '#default_value' => variable_get('feed_default_items', 10),
 767      '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30)),
 768      '#description' => t('The default number of items to include in a feed.')
 769    );
 770    $form['feed_item_length'] = array(
 771      '#type' => 'select',
 772      '#title' => t('Display of XML feed items'),
 773      '#default_value' => variable_get('feed_item_length', 'teaser'),
 774      '#options' => array('title' => t('Titles only'), 'teaser' => t('Titles plus teaser'), 'fulltext' => t('Full text')),
 775      '#description' => t('Global setting for the length of XML feed items that are output by default.')
 776    );
 777  
 778    return system_settings_form($form);
 779  }
 780  
 781  function system_date_time_settings() {
 782    // Date settings:
 783    $zones = _system_zonelist();
 784  
 785    // Date settings: possible date formats
 786    $dateshort = array('Y-m-d H:i', 'm/d/Y - H:i', 'd/m/Y - H:i', 'Y/m/d - H:i',
 787             'd.m.Y - H:i', 'm/d/Y - g:ia', 'd/m/Y - g:ia', 'Y/m/d - g:ia',
 788             'M j Y - H:i', 'j M Y - H:i', 'Y M j - H:i',
 789             'M j Y - g:ia', 'j M Y - g:ia', 'Y M j - g:ia');
 790    $datemedium = array('D, Y-m-d H:i', 'D, m/d/Y - H:i', 'D, d/m/Y - H:i',
 791            'D, Y/m/d - H:i', 'F j, Y - H:i', 'j F, Y - H:i', 'Y, F j - H:i',
 792            'D, m/d/Y - g:ia', 'D, d/m/Y - g:ia', 'D, Y/m/d - g:ia',
 793            'F j, Y - g:ia', 'j F Y - g:ia', 'Y, F j - g:ia', 'j. F Y - G:i');
 794    $datelong = array('l, F j, Y - H:i', 'l, j F, Y - H:i', 'l, Y,  F j - H:i',
 795          'l, F j, Y - g:ia', 'l, j F Y - g:ia', 'l, Y,  F j - g:ia', 'l, j. F Y - G:i');
 796  
 797    // Date settings: construct choices for user
 798    foreach ($dateshort as $f) {
 799      $dateshortchoices[$f] = format_date(time(), 'custom', $f);
 800    }
 801    foreach ($datemedium as $f) {
 802      $datemediumchoices[$f] = format_date(time(), 'custom', $f);
 803    }
 804    foreach ($datelong as $f) {
 805      $datelongchoices[$f] = format_date(time(), 'custom', $f);
 806    }
 807  
 808    $form['date_default_timezone'] = array(
 809      '#type' => 'select',
 810      '#title' => t('Default time zone'),
 811      '#default_value' => variable_get('date_default_timezone', 0),
 812      '#options' => $zones,
 813      '#description' => t('Select the default site time zone.')
 814    );
 815  
 816    $form['configurable_timezones'] = array(
 817      '#type' => 'radios',
 818      '#title' => t('Configurable time zones'),
 819      '#default_value' => variable_get('configurable_timezones', 1),
 820      '#options' => array(t('Disabled'), t('Enabled')),
 821      '#description' => t('Enable or disable user-configurable time zones. When enabled, users can set their own time zone and dates will be updated accordingly.')
 822    );
 823  
 824    $form['date_format_short'] = array(
 825      '#type' => 'select',
 826      '#title' => t('Short date format'),
 827      '#default_value' => variable_get('date_format_short', $dateshort[1]),
 828      '#options' => $dateshortchoices,
 829      '#description' => t('The short format of date display.')
 830    );
 831  
 832    $form['date_format_medium'] = array(
 833      '#type' => 'select',
 834      '#title' => t('Medium date format'),
 835      '#default_value' => variable_get('date_format_medium', $datemedium[1]),
 836      '#options' => $datemediumchoices,
 837      '#description' => t('The medium sized date display.')
 838    );
 839  
 840    $form['date_format_long'] = array(
 841      '#type' => 'select',
 842      '#title' => t('Long date format'),
 843      '#default_value' => variable_get('date_format_long', $datelong[0]),
 844      '#options' => $datelongchoices,
 845      '#description' => t('Longer date format used for detailed display.')
 846    );
 847  
 848    $form['date_first_day'] = array(
 849      '#type' => 'select',
 850      '#title' => t('First day of week'),
 851      '#default_value' => variable_get('date_first_day', 0),
 852      '#options' => array(0 => t('Sunday'), 1 => t('Monday'), 2 => t('Tuesday'), 3 => t('Wednesday'), 4 => t('Thursday'), 5 => t('Friday'), 6 => t('Saturday')),
 853      '#description' => t('The first day of the week for calendar views.')
 854    );
 855  
 856    return system_settings_form($form);
 857  }
 858  
 859  function system_site_maintenance_settings() {
 860  
 861    $form['site_offline'] = array(
 862      '#type' => 'radios',
 863      '#title' => t('Site status'),
 864      '#default_value' => variable_get('site_offline', 0),
 865      '#options' => array(t('Online'), t('Off-line')),
 866      '#description' => t('When set to "Online", all visitors will be able to browse your site normally. When set to "Off-line", only users with the "administer site configuration" permission will be able to access your site to perform maintenance; all other visitors will see the site off-line message configured below. Authorized users can log in during "Off-line" mode directly via the <a href="@user-login">user login</a> page.', array('@user-login' => url('user'))),
 867    );
 868  
 869    $form['site_offline_message'] = array(
 870      '#type' => 'textarea',
 871      '#title' => t('Site off-line message'),
 872      '#default_value' => variable_get('site_offline_message', t('@site is currently under maintenance. We should be back shortly. Thank you for your patience.', array('@site' => variable_get('site_name', 'Drupal')))),
 873      '#description' => t('Message to show visitors when the site is in off-line mode.')
 874    );
 875  
 876    return system_settings_form($form);
 877  }
 878  
 879  /**
 880   * Checks the existence of the directory specified in $form_element. This
 881   * function is called from the system_settings form to check both the
 882   * file_directory_path and file_directory_temp directories. If validation
 883   * fails, the form element is flagged with an error from within the
 884   * file_check_directory function.
 885   *
 886   * @param $form_element
 887   *   The form element containing the name of the directory to check.
 888   */
 889  function system_check_directory($form_element) {
 890    file_check_directory($form_element['#value'], FILE_CREATE_DIRECTORY, $form_element['#parents'][0]);
 891    return $form_element;
 892  }
 893  
 894  /**
 895   * Retrieves the current status of an array of files in the system table.
 896   */
 897  function system_get_files_database(&$files, $type) {
 898    // Extract current files from database.
 899    $result = db_query("SELECT filename, name, type, status, throttle, schema_version FROM {system} WHERE type = '%s'", $type);
 900    while ($file = db_fetch_object($result)) {
 901      if (isset($files[$file->name]) && is_object($files[$file->name])) {
 902        $file->old_filename = $file->filename;
 903        foreach ($file as $key => $value) {
 904          if (!isset($files[$file->name]) || !isset($files[$file->name]->$key)) {
 905            $files[$file->name]->$key = $value;
 906          }
 907        }
 908      }
 909    }
 910  }
 911  
 912  /**
 913   * Collect data about all currently available themes
 914   */
 915  function system_theme_data() {
 916    include_once  './includes/install.inc';
 917  
 918    // Find themes
 919    $themes = drupal_system_listing('\.theme$', 'themes');
 920  
 921    // Find theme engines
 922    $engines = drupal_system_listing('\.engine$', 'themes/engines');
 923  
 924    // can't iterate over array itself as it uses a copy of the array items
 925    foreach (array_keys($themes) as $key) {
 926      drupal_get_filename('theme', $themes[$key]->name, $themes[$key]->filename);
 927      drupal_load('theme', $themes[$key]->name);
 928      $themes[$key]->owner = $themes[$key]->filename;
 929      $themes[$key]->prefix = $key;
 930    }
 931  
 932    // Remove all theme engines from the system table
 933    db_query("DELETE FROM {system} WHERE type = 'theme_engine'");
 934  
 935    foreach ($engines as $engine) {
 936      // Insert theme engine into system table
 937      drupal_get_filename('theme_engine', $engine->name, $engine->filename);
 938      drupal_load('theme_engine', $engine->name);
 939      db_query("INSERT INTO {system} (name, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', %d, %d, %d)", $engine->name, 'theme_engine', $engine->filename, 1, 0, 0);
 940  
 941      // Add templates to the site listing
 942      foreach (call_user_func($engine->name .'_templates') as $template) {
 943        // Do not double-insert templates with theme files in their directory,
 944        // but do register their engine data.
 945        if (array_key_exists($template->name, $themes)) {
 946          $themes[$template->name]->template = TRUE;
 947          $themes[$template->name]->owner = $engine->filename;
 948          $themes[$template->name]->prefix = $engine->name;
 949        }
 950        else {
 951          $template->template = TRUE;
 952          $template->name = basename(dirname($template->filename));
 953          $template->owner = $engine->filename;
 954          $template->prefix = $engine->name;
 955  
 956          $themes[$template->name] = $template;
 957        }
 958      }
 959    }
 960  
 961    // Find styles in each theme's directory.
 962    foreach ($themes as $theme) {
 963      foreach (file_scan_directory(dirname($theme->filename), 'style.css$') as $style) {
 964        $style->style = TRUE;
 965        $style->template = isset($theme->template) ? $theme->template : FALSE;
 966        $style->name = basename(dirname($style->filename));
 967        $style->owner = $theme->filename;
 968        $style->prefix = $theme->template ? $theme->prefix : $theme->name;
 969        // do not double-insert styles with theme files in their directory
 970        if (array_key_exists($style->name, $themes)) {
 971          continue;
 972        }
 973        $themes[$style->name] = $style;
 974      }
 975    }
 976  
 977    // Extract current files from database.
 978    system_get_files_database($themes, 'theme');
 979  
 980    db_query("DELETE FROM {system} WHERE type = 'theme'");
 981  
 982    foreach ($themes as $theme) {
 983      db_query("INSERT INTO {system} (name, description, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d)", $theme->name, $theme->owner, 'theme', $theme->filename, $theme->status, 0, 0);
 984    }
 985  
 986    return $themes;
 987  }
 988  
 989  /**
 990   * Get a list of available regions from a specified theme.
 991   *
 992   * @param $theme_key
 993   *   The name of a theme.
 994   * @return
 995   *   An array of regions in the form $region['name'] = 'description'.
 996   */
 997  function system_region_list($theme_key) {
 998    static $list = array();
 999  
1000    if (!array_key_exists($theme_key, $list)) {
1001      $theme = db_fetch_object(db_query("SELECT * FROM {system} WHERE type = 'theme' AND name = '%s'", $theme_key));
1002  
1003      // Stylesheets can't have regions; use its theme.
1004      if (strpos($theme->filename, '.css')) {
1005        return system_region_list(basename(dirname($theme->description)));
1006      }
1007  
1008      // If this is a custom theme, load it in before moving on.
1009      if (file_exists($file = dirname($theme->filename) .'/'. $theme_key .'.theme')) {
1010        include_once "./$file";
1011      }
1012  
1013      $regions = array();
1014  
1015      // This theme has defined its own regions.
1016      if (function_exists($theme_key .'_regions')) {
1017        $regions = call_user_func($theme_key .'_regions');
1018      }
1019      // File is an engine; include its regions.
1020      else if (strpos($theme->description, '.engine')) {
1021        include_once './'. $theme->description;
1022        $theme_engine = basename($theme->description, '.engine');
1023        $regions = function_exists($theme_engine .'_regions') ? call_user_func($theme_engine .'_regions') : array();
1024      }
1025  
1026      $list[$theme_key] = $regions;
1027    }
1028  
1029    return $list[$theme_key];
1030  }
1031  
1032  /**
1033   * Get the name of the default region for a given theme.
1034   *
1035   * @param $theme
1036   *   The name of a theme.
1037   * @return
1038   *   A string that is the region name.
1039   */
1040  function system_default_region($theme) {
1041    $regions = array_keys(system_region_list($theme));
1042    return $regions[0];
1043  }
1044  
1045  /**
1046   * Assign an initial, default set of blocks for a theme.
1047   *
1048   * This function is called the first time a new theme is enabled. The new theme
1049   * gets a copy of the default theme's blocks, with the difference that if a
1050   * particular region isn't available in the new theme, the block is assigned
1051   * to the new theme's default region.
1052   *
1053   * @param $theme
1054   *   The name of a theme.
1055   */
1056  function system_initialize_theme_blocks($theme) {
1057    // Initialize theme's blocks if none already registered.
1058    if (!(db_num_rows(db_query("SELECT module FROM {blocks} WHERE theme = '%s'", $theme)))) {
1059      $default_theme = variable_get('theme_default', 'garland');
1060      $regions = system_region_list($theme);
1061      $result = db_query("SELECT * FROM {blocks} WHERE theme = '%s'", $default_theme);
1062      while ($block = db_fetch_array($result)) {
1063        // If the region isn't supported by the theme, assign the block to the theme's default region.
1064        if (!array_key_exists($block['region'], $regions)) {
1065          $block['region'] = system_default_region($theme);
1066        }
1067        db_query("INSERT INTO {blocks} (module, delta, theme, status, weight, region, visibility, pages, custom, throttle) VALUES ('%s', '%s', '%s', %d, %d, '%s', %d, '%s', %d, %d)",
1068            $block['module'], $block['delta'], $theme, $block['status'], $block['weight'], $block['region'], $block['visibility'], $block['pages'], $block['custom'], $block['throttle']);
1069      }
1070    }
1071  }
1072  
1073  /**
1074   * Add default buttons to a form and set its prefix
1075   */
1076  function system_settings_form($form) {
1077    $form['buttons']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration') );
1078    $form['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset to defaults') );
1079  
1080    if (!empty($_POST) && form_get_errors()) {
1081      drupal_set_message(t('The settings have not been saved because of the errors.'), 'error');
1082    }
1083    $form['#base'] = 'system_settings_form';
1084    return $form;
1085  }
1086  
1087  function system_theme_settings_submit($form_id, $form_values) {
1088    $op = isset($_POST['op']) ? $_POST['op'] : '';
1089    $key = $form_values['var'];
1090  
1091    // Exclude unnecessary elements.
1092    unset($form_values['var'], $form_values['submit'], $form_values['reset'], $form_values['form_id']);
1093  
1094    if ($op == t('Reset to defaults')) {
1095      variable_del($key);
1096      drupal_set_message(t('The configuration options have been reset to their default values.'));
1097    }
1098    else {
1099      variable_set($key, $form_values);
1100      drupal_set_message(t('The configuration options have been saved.'));
1101    }
1102  
1103    cache_clear_all();
1104  }
1105  
1106  /**
1107   * Execute the system_settings_form.
1108   *
1109   * If you want node type configure style handling of your checkboxes,
1110   * add an array_filter value to your form.
1111   *
1112   */
1113  function system_settings_form_submit($form_id, $form_values) {
1114    $op = isset($form_values['op']) ? $form_values['op'] : '';
1115  
1116    // Exclude unnecessary elements.
1117    unset($form_values['submit'], $form_values['reset'], $form_values['form_id'], $form_values['op'], $form_values['form_token']);
1118  
1119    foreach ($form_values as $key => $value) {
1120      if ($op == t('Reset to defaults')) {
1121        variable_del($key);
1122      }
1123      else {
1124        if (is_array($value) && isset($form_values['array_filter'])) {
1125          $value = array_keys(array_filter($value));
1126        }
1127        variable_set($key, $value);
1128      }
1129    }
1130    if ($op == t('Reset to defaults')) {
1131      drupal_set_message(t('The configuration options have been reset to their default values.'));
1132    }
1133    else {
1134      drupal_set_message(t('The configuration options have been saved.'));
1135    }
1136  
1137    menu_rebuild();
1138  }
1139  
1140  /**
1141   * Menu callback; displays a listing of all themes.
1142   */
1143  function system_themes() {
1144  
1145    drupal_clear_css_cache();
1146    $themes = system_theme_data();
1147    ksort($themes);
1148  
1149    foreach ($themes as $info) {
1150      $info->screenshot = dirname($info->filename) .'/screenshot.png';
1151      $screenshot = file_exists($info->screenshot) ? theme('image', $info->screenshot, t('Screenshot for %theme theme', array('%theme' => $info->name)), '', array('class' => 'screenshot'), FALSE) : t('no screenshot');
1152  
1153      $form[$info->name]['screenshot'] = array('#value' => $screenshot);
1154      $form[$info->name]['description'] = array('#type' => 'item', '#title' => $info->name,  '#value' => dirname($info->filename));
1155      $options[$info->name] = '';
1156      if ($info->status) {
1157        $status[] = $info->name;
1158      }
1159      if ($info->status && (function_exists($info->prefix .'_settings') || function_exists($info->prefix .'_features'))) {
1160        $form[$info->name]['operations'] = array('#value' => l(t('configure'), 'admin/build/themes/settings/'. $info->name) );
1161      }
1162      else {
1163        // Dummy element for drupal_render. Cleaner than adding a check in the theme function.
1164        $form[$info->name]['operations'] = array();
1165      }
1166    }
1167  
1168    $form['status'] = array('#type' => 'checkboxes', '#options' => $options, '#default_value' => $status);
1169    $form['theme_default'] = array('#type' => 'radios', '#options' => $options, '#default_value' => variable_get('theme_default', 'garland'));
1170    $form['buttons']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration') );
1171    $form['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset to defaults') );
1172  
1173    return $form;
1174  }
1175  
1176  function theme_system_themes($form) {
1177    foreach (element_children($form) as $key) {
1178      $row = array();
1179      if (is_array($form[$key]['description'])) {
1180        $row[] = drupal_render($form[$key]['screenshot']);
1181        $row[] = drupal_render($form[$key]['description']);
1182        $row[] = array('data' => drupal_render($form['status'][$key]), 'align' => 'center');
1183        if ($form['theme_default']) {
1184          $row[] = array('data' => drupal_render($form['theme_default'][$key]), 'align' => 'center');
1185          $row[] = array('data' => drupal_render($form[$key]['operations']), 'align' => 'center');
1186        }
1187      }
1188      $rows[] = $row;
1189    }
1190  
1191    $header = array(t('Screenshot'), t('Name'), t('Enabled'), t('Default'), t('Operations'));
1192    $output = theme('table', $header, $rows);
1193    $output .= drupal_render($form);
1194    return $output;
1195  }
1196  
1197  
1198  function system_themes_submit($form_id, $form_values) {
1199  
1200    db_query("UPDATE {system} SET status = 0 WHERE type = 'theme'");
1201  
1202    if ($form_values['op'] == t('Save configuration')) {
1203      if (is_array($form_values['status'])) {
1204        foreach ($form_values['status'] as $key => $choice) {
1205          // Always enable the default theme, despite its status checkbox being checked:
1206          if ($choice || $form_values['theme_default'] == $key) {
1207            system_initialize_theme_blocks($key);
1208            db_query("UPDATE {system} SET status = 1 WHERE type = 'theme' and name = '%s'", $key);
1209          }
1210        }
1211      }
1212      if (($admin_theme = variable_get('admin_theme', '0')) != '0' && $admin_theme != $form_values['theme_default']) {
1213        drupal_set_message(t('Please note that the <a href="!admin_theme_page">administration theme</a> 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(
1214          '!admin_theme_page' => url('admin/settings/admin'),
1215          '%admin_theme' => $admin_theme,
1216          '%selected_theme' => $form_values['theme_default'],
1217        )));
1218      }
1219      variable_set('theme_default', $form_values['theme_default']);
1220    }
1221    else {
1222      variable_del('theme_default');
1223      db_query("UPDATE {system} SET status = 1 WHERE type = 'theme' AND name = 'garland'");
1224    }
1225  
1226    menu_rebuild();
1227    drupal_set_message(t('The configuration options have been saved.'));
1228    return 'admin/build/themes';
1229  }
1230  
1231  /**
1232   * Menu callback; provides module enable/disable interface.
1233   *
1234   * Modules can be enabled or disabled and set for throttling if the throttle module is enabled.
1235   * The list of modules gets populated by module.info files, which contain each module's name,
1236   * description and dependencies.
1237   * @see _module_parse_info_file for information on module.info descriptors.
1238   *
1239   * Dependency checking is performed to ensure that a module cannot be enabled if the module has
1240   * disabled dependencies and also to ensure that the module cannot be disabled if the module has
1241   * enabled dependents.
1242   *
1243   * @return
1244   *   The form array.
1245   */
1246  function system_modules($form_values = NULL) {
1247    // Get current list of modules.
1248    $files = module_rebuild_cache();
1249    if ($confirm_form = system_modules_confirm_form($files, $form_values)) {
1250      return $confirm_form;
1251    }
1252  
1253    // Store module list for validation callback.
1254    $form['validation_modules'] = array('#type' => 'value', '#value' => $files);
1255  
1256    // Create storage for disabled modules as browser will disable checkboxes.
1257    $form['disabled_modules'] = array('#type' => 'value', '#value' => array());
1258  
1259    // Array for disabling checkboxes in callback system_module_disable.
1260    $disabled = array();
1261    // Traverse the files retrieved and build the form.
1262    foreach ($files as $filename => $file) {
1263      $form['name'][$filename] = array('#value' => $file->info['name']);
1264      $form['version'][$filename] = array('#value' => $file->info['version']);
1265      $form['description'][$filename] = array('#value' => t($file->info['description']));
1266      $options[$filename] = '';
1267      if ($file->status) {
1268        $status[] = $file->name;
1269      }
1270      if ($file->throttle) {
1271        $throttle[] = $file->name;
1272      }
1273  
1274      $dependencies = array();
1275      // Check for missing dependencies.
1276      if (is_array($file->info['dependencies'])) {
1277        foreach ($file->info['dependencies'] as $dependency) {
1278          if (!isset($files[$dependency]) || !$files[$dependency]->status) {
1279            if (isset($files[$dependency])) {
1280              $dependencies[] = $files[$dependency]->info['name'] . t(' (<span class="admin-disabled">disabled</span>)');
1281            }
1282            else {
1283              $dependencies[] = drupal_ucfirst($dependency) . t(' (<span class="admin-missing">missing</span>)');
1284              $disabled[] = $filename;
1285              $form['disabled_modules']['#value'][$filename] = FALSE;
1286            }
1287          }
1288          else {
1289            $dependencies[] = $files[$dependency]->info['name'] . t(' (<span class="admin-enabled">enabled</span>)');
1290          }
1291        }
1292  
1293        // Add text for dependencies.
1294        if (!empty($dependencies)) {
1295          $form['description'][$filename]['dependencies'] = array(
1296            '#value' => t('Depends on: !dependencies', array('!dependencies' => implode(', ', $dependencies))),
1297            '#prefix' => '<div class="admin-dependencies">',
1298            '#suffix' => '</div>',
1299          );
1300        }
1301      }
1302  
1303      // Mark dependents disabled so user can not remove modules being depended on.
1304      $dependents = array();
1305      if (is_array($file->info['dependents'])) {
1306        foreach ($file->info['dependents'] as $dependent) {
1307          if ($files[$dependent]->status == 1) {
1308            $dependents[] = $files[$dependent]->info['name'] . t(' (<span class="admin-enabled">enabled</span>)');
1309            $disabled[] = $filename;
1310            $form['disabled_modules']['#value'][$filename] = TRUE;
1311          }
1312          else {
1313            $dependents[] = $files[$dependent]->info['name'] . t(' (<span class="admin-disabled">disabled</span>)');
1314          }
1315        }
1316      }
1317  
1318      // Add text for enabled dependents.
1319      if (!empty($dependents)) {
1320        $form['description'][$filename]['required'] = array(
1321          '#value' => t('Required by: !required', array('!required' => implode(', ', $dependents))),
1322          '#prefix' => '<div class="admin-required">',
1323          '#suffix' => '</div>',
1324        );
1325      }
1326    }
1327  
1328    // Merge in required modules.
1329    $modules_required = array('block', 'filter', 'node', 'system', 'user', 'watchdog');
1330    foreach ($modules_required as $required) {
1331      $disabled[] = $required;
1332      $form['disabled_modules']['#value'][$required] = TRUE;
1333    }
1334  
1335    // Handle status checkboxes, including overriding
1336    // the generated checkboxes for required modules.
1337    $form['status'] = array(
1338      '#type' => 'checkboxes',
1339      '#default_value' => $status,
1340      '#options' => $options,
1341      '#process' => array(
1342        'expand_checkboxes' => array(),
1343        'system_modules_disable' => array($disabled),
1344      ),
1345    );
1346  
1347    // Handle throttle checkboxes, including overriding the
1348    // generated checkboxes for required modules.
1349    if (module_exists('throttle')) {
1350      $form['throttle'] = array(
1351        '#type' => 'checkboxes',
1352        '#default_value' => $throttle,
1353        '#options' => $options,
1354        '#process' => array(
1355          'expand_checkboxes' => array(),
1356          'system_modules_disable' => array(array_merge($modules_required, array('throttle'))),
1357        ),
1358      );
1359    }
1360  
1361    $form['buttons']['submit'] = array(
1362      '#type' => 'submit',
1363      '#value' => t('Save configuration'),
1364    );
1365    $form['#multistep'] = TRUE;
1366    $form['#action'] = url('admin/build/modules/list/confirm');
1367  
1368    return $form;
1369  }
1370  
1371  /**
1372   * Form process callback function to disable check boxes.
1373   */
1374  function system_modules_disable($form, $edit, $disabled) {
1375    foreach ($disabled as $key) {
1376      $form[$key]['#attributes']['disabled'] = 'disabled';
1377    }
1378    return $form;
1379  }
1380  
1381  function system_modules_confirm_form($modules, $form_values = array()) {
1382    $form = array();
1383    $items = array();
1384  
1385    // Check values for submitted dependency errors.
1386    if ($dependencies = system_module_build_dependencies($modules, $form_values)) {
1387      // preserve the already switched on modules
1388      foreach ($modules as $name => $module) {
1389        if ($module->status) {
1390          $form['status'][$name] = array('#type' => 'hidden', '#value' => 1);
1391        }
1392      }
1393  
1394      $form['validation_modules'] = array('#type' => 'value', '#value' => $modules);
1395      $form['status']['#tree'] = TRUE;
1396      foreach ($dependencies as $name => $missing_dependencies) {
1397        $form['status'][$name] = array('#type' => 'hidden', '#value' => 1);
1398        foreach ($missing_dependencies as $k => $dependency) {
1399          $form['status'][$dependency] = array('#type' => 'hidden', '#value' => 1);
1400          $info = $modules[$dependency]->info;
1401          $missing_dependencies[$k] = $info['name'] ? $info['name'] : drupal_ucfirst($dependency);
1402        }
1403        $t_argument = array(
1404          '%module' => $modules[$name]->info['name'],
1405          '%dependencies' => implode(', ', $missing_dependencies),
1406        );
1407        $items[] = strtr(format_plural(count($missing_dependencies), 'You must enable the %dependencies module to install %module.', 'You must enable the %dependencies modules to install %module.'), $t_argument);
1408      }
1409      $form['text'] = array('#value' => theme('item_list', $items));
1410    }
1411  
1412    if ($form) {
1413      // Set some default form values
1414      $form = confirm_form(
1415        $form,
1416        t('Some required modules must be enabled'),
1417        'admin/build/modules',
1418        t('Would you like to continue with enabling the above?'),
1419        t('Continue'),
1420        t('Cancel'));
1421      return $form;
1422    }
1423  }
1424  
1425  function system_module_build_dependencies($modules, $form_values) {
1426    static $dependencies;
1427  
1428    if (!isset($dependencies) && isset($form_values)) {
1429      $dependencies = array();
1430      foreach ($modules as $name => $module) {
1431        // If the module is disabled, will be switched on and it has dependencies.
1432        if (!$module->status && $form_values['status'][$name] && isset($module->info['dependencies'])) {
1433          foreach ($module->info['dependencies'] as $dependency) {
1434            if (!$form_values['status'][$dependency] && isset($modules[$dependency])) {
1435              if (!isset($dependencies[$name])) {
1436                $dependencies[$name] = array();
1437              }
1438              $dependencies[$name][] = $dependency;
1439            }
1440          }
1441        }
1442      }
1443    }
1444    return $dependencies;
1445  }
1446  
1447  /**
1448   * Submit callback; handles modules form submission.
1449   */
1450  function system_modules_submit($form_id, $form_values) {
1451    include_once  './includes/install.inc';
1452    $new_modules = array();
1453  
1454    // Merge in disabled active modules since they should be enabled.
1455    // They don't appear because disabled checkboxes are not submitted
1456    // by browsers.
1457    $form_values['status'] = array_merge($form_values['status'], $form_values['disabled_modules']);
1458  
1459    // Check values for dependency that we can't install.
1460    if ($dependencies = system_module_build_dependencies($form_values['validation_modules'], $form_values)) {
1461      // These are the modules that depend on existing modules.
1462      foreach (array_keys($dependencies) as $name) {
1463        $form_values['status'][$name] = 0;
1464      }
1465    }
1466  
1467    $enable_modules = array();
1468    $disable_modules = array();
1469    foreach ($form_values['status'] as $key => $choice) {
1470      if ($choice) {
1471        if (drupal_get_installed_schema_version($key) == SCHEMA_UNINSTALLED) {
1472          $new_modules[] = $key;
1473        }
1474        else {
1475          $enable_modules[] = $key;
1476        }
1477      }
1478      else {
1479        $disable_modules[] = $key;
1480      }
1481    }
1482  
1483    $old_module_list = module_list();
1484  
1485    if (!empty($enable_modules)) {
1486      module_enable($enable_modules);
1487    }
1488    if (!empty($disable_modules)) {
1489      module_disable($disable_modules);
1490    }
1491  
1492    // Install new modules.
1493    foreach ($new_modules as $key => $module) {
1494      if (!drupal_check_module($module)) {
1495        unset($new_modules[$key]);
1496      }
1497    }
1498    drupal_install_modules($new_modules);
1499  
1500    $current_module_list = module_list(TRUE, FALSE);
1501  
1502    if (is_array($form_values['throttle'])) {
1503      foreach ($form_values['throttle'] as $key => $choice) {
1504        db_query("UPDATE {system} SET throttle = %d WHERE type = 'module' and name = '%s'", $choice ? 1 : 0, $key);
1505      }
1506    }
1507  
1508    if ($old_module_list != $current_module_list) {
1509      menu_rebuild();
1510      node_types_rebuild();
1511      drupal_set_message(t('The configuration options have been saved.'));
1512    }
1513  
1514    // If there where unmet dependencies and they haven't confirmed don't redirect.
1515    if ($dependencies && !isset($form_values['confirm'])) {
1516      return FALSE;
1517    }
1518  
1519    drupal_clear_css_cache();
1520  
1521    return 'admin/build/modules';
1522  }
1523  
1524  /**
1525   * Theme call back for the modules form.
1526   */
1527  function theme_system_modules($form) {
1528    if (isset($form['confirm'])) {
1529      return drupal_render($form);
1530    }
1531  
1532    // Individual table headers.
1533    $header = array(t('Enabled'));
1534    if (module_exists('throttle')) {
1535      $header[] = t('Throttle');
1536    }
1537    $header[] = t('Name');
1538    $header[] = t('Version');
1539    $header[] = t('Description');
1540  
1541    // Pull package information from module list and start grouping modules.
1542    $modules = $form['validation_modules']['#value'];
1543    foreach ($modules as $module) {
1544      if (!isset($module->info['package']) || !$module->info['package']) {
1545        $module->info['package'] = t('Other');
1546      }
1547      $packages[$module->info['package']][$module->name] = $module->info;
1548    }
1549    ksort($packages);
1550  
1551    // Display packages.
1552    $output = '';
1553    foreach ($packages as $package => $modules) {
1554      $rows = array();
1555      foreach ($modules as $key => $module) {
1556        $row = array();
1557        $row[] = array('data' => drupal_render($form['status'][$key]), 'align' => 'center');
1558  
1559        if (module_exists('throttle')) {
1560          $row[] = array('data' => drupal_render($form['throttle'][$key]), 'align' => 'center');
1561        }
1562        $row[] = '<strong>'. drupal_render($form['name'][$key]) .'</strong>';
1563        $row[] = drupal_render($form['version'][$key]);
1564        $row[] = array('data' => drupal_render($form['description'][$key]), 'class' => 'description');
1565        $rows[] = $row;
1566      }
1567      $fieldset = array(
1568        '#title' => t($package),
1569        '#collapsible' => TRUE,
1570        '#collapsed' => ($package == 'Core - required'),
1571        '#value' => theme('table', $header, $rows, array('class' => 'package')),
1572      );
1573      $output .= theme('fieldset', $fieldset);
1574    }
1575  
1576    $output .= drupal_render($form);
1577    return $output;
1578  }
1579  
1580  /**
1581   * Uninstall functions
1582   */
1583  
1584  /**
1585   * Builds a form of currently disabled modules.
1586   *
1587   * @param
1588   *   $form_values Submitted form values.
1589   * @return
1590   *   A form array representing the currently disabled modules.
1591   */
1592  function system_modules_uninstall($form_values = NULL) {
1593    // Make sure the install API is available.
1594    include_once  './includes/install.inc';
1595  
1596    // Display the confirm form if any modules have been submitted.
1597    if ($confirm_form = system_modules_uninstall_confirm_form($form_values)) {
1598      return $confirm_form;
1599    }
1600  
1601    $form = array();
1602  
1603    // Pull all disabled modules from the system table.
1604    $disabled_modules = db_query("SELECT name, filename FROM {system} WHERE type = 'module' AND status = 0 AND schema_version > %d ORDER BY name", SCHEMA_UNINSTALLED);
1605    while ($module = db_fetch_object($disabled_modules)) {
1606  
1607      // Grab the .info file and set name and description.
1608      $info = _module_parse_info_file(dirname($module->filename) .'/'. $module->name .'.info');
1609  
1610      // Load the .install file, and check for an uninstall hook.
1611      // If the hook exists, the module can be uninstalled.
1612      module_load_install($module->name);
1613      if (module_hook($module->name, 'uninstall')) {
1614        $form['modules'][$module->name]['name'] = array('#value' => $info['name'] ? $info['name'] : $module->name);
1615        $form['modules'][$module->name]['description'] = array('#value' => t($info['description']));
1616        $options[$module->name] = '';
1617      }
1618    }
1619  
1620    // Only build the rest of the form if there are any modules available to uninstall.
1621    if (count($options)) {
1622      $form['uninstall'] = array(
1623        '#type' => 'checkboxes',
1624        '#options' => $options,
1625      );
1626      $form['buttons']['submit'] = array(
1627        '#type' => 'button',
1628        '#value' => t('Uninstall'),
1629      );
1630      $form['#multistep'] = TRUE;
1631      $form['#action'] = url('admin/build/modules/uninstall/confirm');
1632    }
1633  
1634    return $form;
1635  }
1636  
1637  /**
1638   * Confirm uninstall of selected modules.
1639   *
1640   * @param
1641   *   $form_values Submitted form values.
1642   * @return
1643   *   A form array representing modules to confirm.
1644   */
1645  function system_modules_uninstall_confirm_form($form_values) {
1646    // Nothing to build.
1647    if (!isset($form_values)) {
1648      return;
1649    }
1650  
1651    // Construct the hidden form elements and list items.
1652    foreach (array_filter($form_values['uninstall']) as $module => $value) {
1653      $info = _module_parse_info_file(dirname(drupal_get_filename('module', $module)) .'/'. $module .'.info');
1654      $uninstall[] = $info['name'];
1655      $form['uninstall'][$module] = array('#type' => 'hidden',
1656        '#value' => 1,
1657      );
1658    }
1659  
1660    // Display a confirm form if modules have been selected.
1661    if (isset($uninstall)) {
1662      $form['uninstall']['#tree'] = TRUE;
1663      $form['#multistep'] = TRUE;
1664      $form['modules'] = array('#value' => '<p>'. t('The following modules will be completely uninstalled from your site, and <em>all data from these modules will be lost</em>!') .'</p>'. theme('item_list', $uninstall));
1665      $form = confirm_form(
1666        $form,
1667        t('Confirm uninstall'),
1668        'admin/build/modules/uninstall',
1669        t('Would you like to continue with uninstalling the above?'),
1670        t('Uninstall'),
1671        t('Cancel'));
1672      return $form;
1673    }
1674  }
1675  
1676  /**
1677   * Themes a table of currently disabled modules.
1678   *
1679   * @param
1680   *   $form The form array representing the currently disabled modules.
1681   * @return
1682   *   An HTML string representing the table.
1683   */
1684  function theme_system_modules_uninstall($form) {
1685    // No theming for the confirm form.
1686    if (isset($form['confirm'])) {
1687      return drupal_render($form);
1688    }
1689  
1690    // Table headers.
1691    $header = array(t('Uninstall'),
1692      t('Name'),
1693      t('Description'),
1694    );
1695  
1696    // Display table.
1697    $rows = array();
1698    foreach (element_children($form['modules']) as $module) {
1699      $rows[] = array(
1700        array('data' => drupal_render($form['uninstall'][$module]), 'align' => 'center'),
1701        '<strong>'. drupal_render($form['modules'][$module]['name']) .'</strong>',
1702        array('data' => drupal_render($form['modules'][$module]['description']), 'class' => 'description'),
1703      );
1704    }
1705  
1706    // Only display table if there are modules that can be uninstalled.
1707    if (!count($rows)) {
1708      $rows[] = array(array('data' => t('No modules are available to uninstall.'), 'colspan' => '3', 'align' => 'center', 'class' => 'message'));
1709    }
1710  
1711    $output  = theme('table', $header, $rows);
1712    $output .= drupal_render($form);
1713  
1714    return $output;
1715  }
1716  
1717  /**
1718   * Validates the submitted uninstall form.
1719   *
1720   * @param
1721   *   $form_id The form ID.
1722   * @param
1723   *   $form_values Submitted form values.
1724   */
1725  function system_modules_uninstall_validate($form_id, $form_values) {
1726    // Form submitted, but no modules selected.
1727    if (!count(array_filter($form_values['uninstall']))) {
1728      drupal_set_message(t('No modules selected.'), 'error');
1729      drupal_goto('admin/build/modules/uninstall');
1730    }
1731  }
1732  
1733  /**
1734   * Processes the submitted uninstall form.
1735   *
1736   * @param
1737   *   $form_id The form ID.
1738   * @param
1739   *   $form_values Submitted form values.
1740   */
1741  function system_modules_uninstall_submit($form_id, $form_values) {
1742    // Make sure the install API is available.
1743    include_once  './includes/install.inc';
1744  
1745    // Call the uninstall routine for each selected module.
1746    foreach (array_filter($form_values['uninstall']) as $module => $value) {
1747      drupal_uninstall_module($module);
1748    }
1749    drupal_set_message(t('The selected modules have been uninstalled.'));
1750    drupal_goto('admin/build/modules/uninstall');
1751  }
1752  
1753  /**
1754   * Menu callback: run cron manually.
1755   */
1756  function system_run_cron() {
1757     // Run cron manually
1758     if (drupal_cron_run()) {
1759       drupal_set_message(t('Cron ran successfully'));
1760     }
1761     else {
1762       drupal_set_message(t('Cron run failed'));
1763     }
1764  
1765     drupal_goto('admin/logs/status');
1766  }
1767  
1768  /**
1769   * Menu callback: return information about PHP.
1770   */
1771  function system_php() {
1772    phpinfo(INFO_GENERAL | INFO_CONFIGURATION);
1773    exit();
1774  }
1775  
1776  function _system_sql($data, $keys) {
1777    $rows = array();
1778    foreach ($keys as $key => $explanation) {
1779      if (isset($data[$key])) {
1780        $rows[] = array(check_plain($key), check_plain($data[$key]), $explanation);
1781      }
1782    }
1783  
1784    return theme('table', array(t('Variable'), t('Value'), t('Description')), $rows);
1785  }
1786  
1787  /**
1788   * Menu callback: return information about PHP.
1789   */
1790  function system_sql() {
1791  
1792    $result = db_query("SHOW STATUS");
1793    while ($entry = db_fetch_object($result)) {
1794     $data[$entry->Variable_name] = $entry->Value;
1795    }
1796  
1797    $output  = '<h2>'. t('Command counters') .'</h2>';
1798    $output .= _system_sql($data, array(
1799     'Com_select' => t('The number of <code>SELECT</code>-statements.'),
1800     'Com_insert' => t('The number of <code>INSERT</code>-statements.'),
1801     'Com_update' => t('The number of <code>UPDATE</code>-statements.'),
1802     'Com_delete' => t('The number of <code>DELETE</code>-statements.'),
1803     'Com_lock_tables' => t('The number of table locks.'),
1804     'Com_unlock_tables' => t('The number of table unlocks.')
1805    ));
1806  
1807    $output .= '<h2>'. t('Query performance') .'</h2>';
1808    $output .= _system_sql($data, array(
1809     'Select_full_join' => t('The number of joins without an index; should be zero.'),
1810     'Select_range_check' => t('The number of joins without an index; should be zero.'),
1811     'Sort_scan' => t('The number of sorts done without using an index; should be zero.'),
1812     'Table_locks_immediate' => t('The number of times a lock could be acquired immediately.'),
1813     'Table_locks_waited' => t('The number of times the server had to wait for a lock.')
1814    ));
1815  
1816    $output .= '<h2>'. t('Query cache information') .'</h2>';
1817    $output .= '<p>'. t('The MySQL query cache can improve performance of your site by storing the result of queries.  Then, if an identical query is received later, the MySQL server retrieves the result from the query cache rather than parsing and executing the statement again.') .'</p>';
1818    $output .= _system_sql($data, array(
1819     'Qcache_queries_in_cache' => t('The number of queries in the query cache.'),
1820     'Qcache_hits' => t('The number of times that MySQL found previous results in the cache.'),
1821     'Qcache_inserts' => t('The number of times that MySQL added a query to the cache (misses).'),
1822     'Qcache_lowmem_prunes' => t('The number of times that MySQL had to remove queries from the cache because it ran out of memory.  Ideally should be zero.')
1823    ));
1824  
1825    return $output;
1826  }
1827  
1828  /**
1829   * Menu callback: displays the site status report. Can also be used as a pure check.
1830   *
1831   * @param $check
1832   *   If true, only returns a boolean whether there are system status errors.
1833   */
1834  function system_status($check = FALSE) {
1835    // Load .install files
1836    include_once  './includes/install.inc';
1837    drupal_load_updates();
1838  
1839    // Check run-time requirements and status information
1840    $requirements = module_invoke_all('requirements', 'runtime');
1841    usort($requirements, '_system_sort_requirements');
1842  
1843    if ($check) {
1844      return drupal_requirements_severity($requirements) == REQUIREMENT_ERROR;
1845    }
1846  
1847    return theme('status_report', $requirements);
1848  }
1849  
1850  /**
1851   * Helper function to sort requirements.
1852   */
1853  function _system_sort_requirements($a, $b) {
1854    return (isset($a['weight']) || isset($b['weight'])) ? $a['weight'] - $b['weight'] : strcmp($a['title'], $b['title']);
1855  }
1856  
1857  /**
1858   * Theme status report
1859   */
1860  function theme_status_report(&$requirements) {
1861    $i = 0;
1862    $output = '<table class="system-status-report">';
1863    foreach ($requirements as $requirement) {
1864      if ($requirement['#type'] == '') {
1865        $class = ++$i % 2 == 0 ? 'even' : 'odd';
1866  
1867        $classes = array(
1868          REQUIREMENT_INFO => 'info',
1869          REQUIREMENT_OK => 'ok',
1870          REQUIREMENT_WARNING => 'warning',
1871          REQUIREMENT_ERROR => 'error',
1872        );
1873        $class = $classes[(int)$requirement['severity']] .' '. $class;
1874  
1875        // Output table row(s)
1876        if ($requirement['description']) {
1877          $output .= '<tr class="'. $class .' merge-down"><th>'. $requirement['title'] .'</th><td>'. $requirement['value'] .'</td></tr>';
1878          $output .= '<tr class="'. $class .' merge-up"><td colspan="2">'. $requirement['description'] .'</td></tr>';
1879        }
1880        else {
1881          $output .= '<tr class="'. $class .'"><th>'. $requirement['title'] .'</th><td>'. $requirement['value'] .'</td></tr>';
1882        }
1883      }
1884    }
1885  
1886    $output .= '</table>';
1887    return $output;
1888  }
1889  
1890  /**
1891   * Menu callback; displays a module's settings page.
1892   */
1893  function system_settings_overview() {
1894  
1895    // Check database setup if necessary
1896    if (function_exists('db_check_setup') && empty($_POST)) {
1897      db_check_setup();
1898    }
1899  
1900    $menu = menu_get_item(NULL, 'admin/settings');
1901    $content = system_admin_menu_block($menu);
1902  
1903    $output = theme('admin_block_content', $content);
1904  
1905    return $output;
1906  }
1907  
1908  /**
1909   * Menu callback; display theme configuration for entire site and individual themes.
1910   */
1911  function system_theme_settings($key = '') {
1912    $directory_path = file_directory_path();
1913    file_check_directory($directory_path, FILE_CREATE_DIRECTORY, 'file_directory_path');
1914  
1915    // Default settings are defined in theme_get_settings() in includes/theme.inc
1916    if ($key) {
1917      $settings = theme_get_settings($key);
1918      $var = str_replace('/', '_', 'theme_'. $key .'_settings');
1919      $themes = system_theme_data();
1920      $features = function_exists($themes[$key]->prefix .'_features') ? call_user_func($themes[$key]->prefix .'_features') : array();
1921    }
1922    else {
1923      $settings = theme_get_settings('');
1924      $var = 'theme_settings';
1925    }
1926  
1927    $form['var'] = array('#type' => 'hidden', '#value' => $var);
1928  
1929    // Check for a new uploaded logo, and use that instead.
1930    if ($file = file_check_upload('logo_upload')) {
1931      if ($info = image_get_info($file->filepath)) {
1932        $parts = pathinfo($file->filename);
1933        $filename = ($key) ? str_replace('/', '_', $key) .'_logo.'. $parts['extension'] : 'logo.'. $parts['extension'];
1934  
1935        if ($file = file_save_upload('logo_upload', $filename, 1)) {
1936          $_POST['default_logo'] = 0;
1937          $_POST['logo_path'] = $file->filepath;
1938          $_POST['toggle_logo'] = 1;
1939        }
1940      }
1941      else {
1942        form_set_error('file_upload', t('Only JPEG, PNG and GIF images are allowed to be used as logos.'));
1943      }
1944    }
1945  
1946    // Check for a new uploaded favicon, and use that instead.
1947    if ($file = file_check_upload('favicon_upload')) {
1948      $parts = pathinfo($file->filename);
1949      $filename = ($key) ? str_replace('/', '_', $key) .'_favicon.'. $parts['extension'] : 'favicon.'. $parts['extension'];
1950  
1951      if ($file = file_save_upload('favicon_upload', $filename, 1)) {
1952        $_POST['default_favicon'] = 0;
1953        $_POST['favicon_path'] = $file->filepath;
1954        $_POST['toggle_favicon'] = 1;
1955      }
1956    }
1957  
1958    // Toggle settings
1959    $toggles = array(
1960      'toggle_logo'                 => t('Logo'),
1961      'toggle_name'                 => t('Site name'),
1962      'toggle_slogan'               => t('Site slogan'),
1963      'toggle_mission'              => t('Mission statement'),
1964      'toggle_node_user_picture'    => t('User pictures in posts'),
1965      'toggle_comment_user_picture' => t('User pictures in comments'),
1966      'toggle_search'               => t('Search box'),
1967      'toggle_favicon'              => t('Shortcut icon')
1968    );
1969  
1970    // Some features are not always available
1971    $disabled = array();
1972    if (!variable_get('user_pictures', 0)) {
1973      $disabled['toggle_node_user_picture'] = TRUE;
1974      $disabled['toggle_comment_user_picture'] = TRUE;
1975    }
1976    if (!module_exists('search')) {
1977      $disabled['toggle_search'] = TRUE;
1978    }
1979  
1980    $form['theme_settings'] = array(
1981      '#type' => 'fieldset',
1982      '#title' => t('Toggle display'),
1983      '#description' => t('Enable or disable the display of certain page elements.'),
1984    );
1985    foreach ($toggles as $name => $title) {
1986      if ((!$key) || in_array($name, $features)) {
1987        // disable search box if search.module is disabled
1988        $form['theme_settings'][$name] = array('#type' => 'checkbox', '#title' => $title, '#default_value' => $settings[$name]);
1989        if (isset($disabled[$name])) {
1990          $form['theme_settings'][$name]['#disabled'] = TRUE;
1991        }
1992      }
1993    }
1994  
1995    // System wide only settings.
1996    if (!$key) {
1997      // Create neat 2-column layout for the toggles
1998      $form['theme_settings'] += array(
1999        '#prefix' => '<div class="theme-settings-left">',
2000        '#suffix' => '</div>',
2001      );
2002  
2003      // Toggle node display.
2004      $node_types = node_get_types('names');
2005      if ($node_types) {
2006        $form['node_info'] = array(
2007          '#type' => 'fieldset',
2008          '#title' => t('Display post information on'),
2009          '#description' =>  t('Enable or disable the <em>submitted by Username on date</em> text when displaying posts of the following type.'),
2010          '#prefix' => '<div class="theme-settings-right">',
2011          '#suffix' => '</div>',
2012        );
2013        foreach ($node_types as $type => $name) {
2014          $form['node_info']["toggle_node_info_$type"] = array('#type' => 'checkbox', '#title' => check_plain($name), '#default_value' => $settings["toggle_node_info_$type"]);
2015        }
2016      }
2017    }
2018  
2019    // Logo settings
2020    if ((!$key) || in_array('toggle_logo', $features)) {
2021      $form['logo'] = array(
2022        '#type' => 'fieldset',
2023        '#title' => t('Logo image settings'),
2024        '#description' => t('If toggled on, the following logo will be displayed.'),
2025        '#attributes' => array('class' => 'theme-settings-bottom'),
2026      );
2027      $form['logo']["default_logo"] = array(
2028        '#type' => 'checkbox',
2029        '#title' => t('Use the default logo'),
2030        '#default_value' => $settings['default_logo'],
2031        '#tree' => FALSE,
2032        '#description' => t('Check here if you want the theme to use the logo supplied with it.')
2033      );
2034      $form['logo']['logo_path'] = array(
2035        '#type' => 'textfield',
2036        '#title' => t('Path to custom logo'),
2037        '#default_value' => $settings['logo_path'],
2038        '#description' => t('The path to the file you would like to use as your logo file instead of the default logo.'));
2039  
2040      $form['logo']['logo_upload'] = array(
2041        '#type' => 'file',
2042        '#title' => t('Upload logo image'),
2043        '#maxlength' => 40,
2044        '#description' => t("If you don't have direct file access to the server, use this field to upload your logo.")
2045      );
2046    }
2047  
2048    // Icon settings
2049    if ((!$key) || in_array('toggle_favicon', $features)) {
2050      $form['favicon'] = array(
2051        '#type' => 'fieldset',
2052        '#title' => t('Shortcut icon settings'),
2053        '#description' => t("Your shortcut icon or 'favicon' is displayed in the address bar and bookmarks of most browsers.")
2054      );
2055      $form['favicon']['default_favicon'] = array(
2056        '#type' => 'checkbox',
2057        '#title' => t('Use the default shortcut icon.'),
2058        '#default_value' => $settings['default_favicon'],
2059        '#description' => t('Check here if you want the theme to use the default shortcut icon.')
2060      );
2061      $form['favicon']['favicon_path'] = array(
2062        '#type' => 'textfield',
2063        '#title' => t('Path to custom icon'),
2064        '#default_value' =>  $settings['favicon_path'],
2065        '#description' => t('The path to the image file you would like to use as your custom shortcut icon.')
2066      );
2067  
2068      $form['favicon']['favicon_upload'] = array(
2069        '#type' => 'file',
2070        '#title' => t('Upload icon image'),
2071        '#description' => t("If you don't have direct file access to the server, use this field to upload your shortcut icon.")
2072      );
2073    }
2074  
2075    if ($key) {
2076      // Template-specific settings
2077      $function = $themes[$key]->prefix .'_settings';
2078      if (function_exists($function)) {
2079        if ($themes[$key]->template) {
2080          // file is a template or a style of a template
2081          $form['specific'] = array('#type' => 'fieldset', '#title' => t('Engine-specific settings'), '#description' => t('These settings only exist for all the templates and styles based on the %engine theme engine.', array('%engine' => $themes[$key]->prefix)));
2082        }
2083        else {
2084          // file is a theme or a style of a theme
2085          $form['specific'] = array('#type' => 'fieldset', '#title' => t('Theme-specific settings'), '#description' => t('These settings only exist for the %theme theme and all the styles based on it.', array('%theme' => $themes[$key]->prefix)));
2086        }
2087        $group = $function();
2088        $form['specific'] = array_merge($form['specific'], (is_array($group) ? $group : array()));
2089      }
2090    }
2091    $form['#attributes'] = array('enctype' => 'multipart/form-data');
2092  
2093    return system_settings_form($form);
2094  }
2095  
2096  /**
2097   * Implementation of hook_node_type().
2098   *
2099   * Updates theme settings after a node type change.
2100   */
2101  function system_node_type($op, $info) {
2102    if ($op == 'update' && !empty($info->old_type) && $info->type != $info->old_type) {
2103      $old = 'toggle_node_info_'. $info->old_type;
2104      $new = 'toggle_node_info_'. $info->type;
2105  
2106      $theme_settings = variable_get('theme_settings', array());
2107      if (isset($theme_settings[$old])) {
2108        $theme_settings[$new] = $theme_settings[$old];
2109        unset($theme_settings[$old]);
2110        variable_set('theme_settings', $theme_settings);
2111      }
2112    }
2113  }
2114  
2115  /**
2116   * Output a confirmation form
2117   *
2118   * This function returns a complete form for confirming an action. A link is
2119   * offered to go back to the item that is being changed in case the user 
2120   * changes his/her mind.
2121   *
2122   * If the submit handler for this form is invoked, the user successfully
2123   * confirmed the action. You should never directly inspect $_POST to see if an
2124   * action was confirmed.
2125   *
2126   * @param $form
2127   *   Additional elements to inject into the form, for example hidden elements.
2128   * @param $question
2129   *   The question to ask the user (e.g. "Are you sure you want to delete the
2130   *   block <em>foo</em>?").
2131   * @param $path
2132   *   The page to go to if the user denies the action.
2133   *   Can be either a drupal path, or an array with the keys 'path', 'query', 'fragment'.
2134   * @param $description
2135   *   Additional text to display (defaults to "This action cannot be undone.").
2136   * @param $yes
2137   *   A caption for the button which confirms the action (e.g. "Delete",
2138   *   "Replace", ...).
2139   * @param $no
2140   *   A caption for the link which denies the action (e.g. "Cancel").
2141   * @param $name
2142   *   The internal name used to refer to the confirmation item.
2143   * @return
2144   *   The form.
2145   */
2146  function confirm_form($form, $question, $path, $description = NULL, $yes = NULL, $no = NULL, $name = 'confirm') {
2147    $description = isset($description) ? $description : t('This action cannot be undone.');
2148  
2149    // Prepare cancel link
2150    $query = $fragment = NULL;
2151    if (is_array($path)) {
2152      $query = isset($path['query']) ? $path['query'] : NULL;
2153      $fragment = isset($path['fragment']) ? $path['fragment'] : NULL;
2154      $path = isset($path['path']) ? $path['path'] : NULL;
2155    }
2156    $cancel = l($no ? $no : t('Cancel'), $path, array(), $query, $fragment);
2157  
2158    drupal_set_title($question);
2159  
2160    $form['#attributes'] = array('class' => 'confirmation');
2161    $form['description'] = array('#value' => $description);
2162    $form[$name] = array('#type' => 'hidden', '#value' => 1);
2163  
2164    $form['actions'] = array('#prefix' => '<div class="container-inline">', '#suffix' => '</div>');
2165    $form['actions']['submit'] = array('#type' => 'submit', '#value' => $yes ? $yes : t('Confirm'));
2166    $form['actions']['cancel'] = array('#value' => $cancel);
2167    $form['#base'] = 'confirm_form';
2168    return $form;
2169  }
2170  
2171  /**
2172   * Determine if a user is in compact mode.
2173   */
2174  function system_admin_compact_mode() {
2175    global $user;
2176    return (isset($user->admin_compact_mode)) ? $user->admin_compact_mode : variable_get('admin_compact_mode', FALSE);
2177  }
2178  
2179  /**
2180   * This function formats an administrative page for viewing.
2181   *
2182   * @param $blocks
2183   *   An array of blocks to display. Each array should include a
2184   *   'title', a 'description', a formatted 'content' and a
2185   *   'position' which will control which container it will be
2186   *   in. This is usually 'left' or 'right'.
2187   * @themeable
2188   */
2189  function theme_admin_page($blocks) {
2190    $stripe = 0;
2191    $container = array();
2192  
2193    foreach ($blocks as $block) {
2194      if ($block_output = theme('admin_block', $block)) {
2195        if (!$block['position']) {
2196          // perform automatic striping.
2197          $block['position'] = $stripe++ % 2 ? 'left' : 'right';
2198        }
2199        $container[$block['position']] .= $block_output;
2200      }
2201    }
2202  
2203    $output = '<div class="admin clear-block">';
2204    $output .= '<div class="compact-link">';
2205    if (system_admin_compact_mode()) {
2206      $output .= l(t('Show descriptions'), 'admin/compact/off', array('title' => t('Produce a less compact layout that includes descriptions.')));
2207    }
2208    else {
2209      $output .= l(t('Hide descriptions'), 'admin/compact/on', array('title' => t("Produce a more compact layout that doesn't include descriptions.")));
2210    }
2211    $output .= '</div>';
2212  
2213    foreach ($container as $id => $data) {
2214      $output .= '<div class="'. $id .' clear-block">';
2215      $output .= $data;
2216      $output .= '</div>';
2217    }
2218    $output .= '</div>';
2219    return $output;
2220  }
2221  
2222  /**
2223   * This function formats an administrative block for display.
2224   *
2225   * @param $block
2226   *   An array containing information about the block. It should
2227   *   include a 'title', a 'description' and a formatted 'content'.
2228   * @themeable
2229   */
2230  function theme_admin_block($block) {
2231    // Don't display the block if it has no content to display.
2232    if (!$block['content']) {
2233      return '';
2234    }
2235  
2236    $output = <<< EOT
2237    <div class="admin-panel">
2238      <h3>
2239        $block[title]
2240      </h3>
2241      <div class="body">
2242        <p class="description">
2243          $block[description]
2244        </p>
2245        $block[content]
2246      </div>
2247    </div>
2248  EOT;
2249    return $output;
2250  }
2251  
2252  /**
2253   * This function formats the content of an administrative block.
2254   *
2255   * @param $block
2256   *   An array containing information about the block. It should
2257   *   include a 'title', a 'description' and a formatted 'content'.
2258   * @themeable
2259   */
2260  function theme_admin_block_content($content) {
2261    if (!$content) {
2262      return '';
2263    }
2264  
2265    if (system_admin_compact_mode()) {
2266      $output = '<ul class="menu">';
2267      foreach ($content as $item) {
2268        $output .= '<li class="leaf">'. l($item['title'], $item['path'], array('title' => $item['description'])) .'</li>';
2269      }
2270      $output .= '</ul>';
2271    }
2272    else {
2273      $output = '<dl class="admin-list">';
2274      foreach ($content as $item) {
2275        $output .= '<dt>'. l($item['title'], $item['path']) .'</dt>';
2276        $output .= '<dd>'. $item['description'] .'</dd>';
2277      }
2278      $output .= '</dl>';
2279    }
2280    return $output;
2281  }
2282  
2283  /**
2284   * Menu callback; prints a listing of admin tasks for each installed module.
2285   */
2286  function system_admin_by_module() {
2287    $modules = module_rebuild_cache();
2288    $menu_items = array();
2289    foreach ($modules as $file) {
2290      $module = $file->name;
2291      if ($module == 'help') {
2292        continue;
2293      }
2294  
2295      $admin_tasks = system_get_module_admin_tasks($module);
2296  
2297      // Only display a section if there are any available tasks.
2298      if (count($admin_tasks)) {
2299  
2300        // Check for help links.
2301        if (module_invoke($module, 'help', "admin/help#$module")) {
2302          $admin_tasks[100] = l(t('Get help'), "admin/help/$module");
2303        }
2304  
2305        // Sort.
2306        ksort($admin_tasks);
2307  
2308        $menu_items[$file->info['name']] = array($file->info['description'], $admin_tasks);
2309      }
2310    }
2311    return theme('system_admin_by_module', $menu_items);
2312  }
2313  
2314  function system_get_module_admin_tasks($module) {
2315    $admin_access = user_access('administer access control');
2316    $menu = menu_get_menu();
2317    $admin_tasks = array();
2318  
2319    // Check for permissions.
2320    if (module_hook($module, 'perm') && $admin_access) {
2321      $admin_tasks[-1] = l(t('Configure permissions'), 'admin/user/access', NULL, NULL, 'module-'. $module);
2322    }
2323  
2324    // Check for menu items that are admin links.
2325    if ($items = module_invoke($module, 'menu', TRUE)) {
2326      foreach ($items as $item) {
2327        $parts = explode('/', $item['path']);
2328        $n = count($parts);
2329        if ((!isset($item['type']) || ($item['type'] & MENU_VISIBLE_IN_TREE)) && ($parts[0] == 'admin') && ($n >= 3) && _menu_item_is_accessible($menu['path index'][$item['path']])) {
2330          $admin_tasks[$item['title']] = l($item['title'], $item['path']);
2331        }
2332      }
2333    }
2334  
2335    return $admin_tasks;
2336  }
2337  
2338  /**
2339   * Theme output of the dashboard page.
2340   */
2341  function theme_system_admin_by_module($menu_items) {
2342    $stripe = 0;
2343    $output = '';
2344    $container = array();
2345  
2346    // Iterate over all modules
2347    foreach ($menu_items as $module => $block) {
2348      list($description, $items) = $block;
2349  
2350      // Output links
2351      if (count($items)) {
2352        $block = array();
2353        $block['title'] = $module;
2354        $block['content'] = theme('item_list', $items);
2355        $block['description'] = t($description);
2356  
2357        if ($block_output = theme('admin_block', $block)) {
2358          if (!$block['position']) {
2359            // Perform automatic striping.
2360            $block['position'] = ++$stripe % 2 ? 'left' : 'right';
2361          }
2362          $container[$block['position']] .= $block_output;
2363        }
2364      }
2365    }
2366  
2367    $output = '<div class="admin">';
2368    foreach ($container as $id => $data) {
2369      $output .= '<div class="'. $id .' clear-block">';
2370      $output .= $data;
2371      $output .= '</div>';
2372    }
2373    $output .= '</div>';
2374  
2375    return $output;
2376  }


Généré le : Fri Nov 30 16:20:15 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics